feat(cma): revive cross-model harness corpus to current language (refs #68)
The cma authoring-form harness corpus had gone dead against the language as it evolved since May. The plan modelled it as merely schema-dead (missing param_modes/ret_mode); it was also drift-dead in the example BODIES. Fixed in place, with `ail check` + both test suites as the oracle: - Schema: param_modes/ret_mode completed on every fn type; existing borrow annotations preserved (data_with_match's borrow over List). - Symbol drift: `<`/`==` -> `lt`/`eq` (operator-routing); the removed `io/print_int` op -> print_str(int_to_str n) followed by a newline print, preserving the trailing newline the references' expected_stdout needs. - Ownership/ADT restructures: data_simple's reuse-as now wraps the source in a match arm (ctor must be statically visible); data_with_match's count_via_letrec + local go switched borrow->own (consume-while-borrowed under the tightened ownership analysis; head_or_zero still exercises borrow over the boxed List). - param_modes_all rewritten to own (Int) + borrow over a boxed ADT -- (borrow Int) is now a borrow-over-value error. - Two new author-facing examples (loop_sum: Loop/Recur; new_rawbuf: New) cover the Term variants that landed since May. - spec_completeness.rs: drop the deleted ParamMode::Implicit; cover Loop/Recur/New; allowlist the non-authorable Term::Intrinsic out. - spec.md section 4 rewritten to own/borrow (mandatory, no implicit) with the borrow-over-value rule; rendered/ regenerated. - mock_full_run fixture's t3 turn-2 program migrated so the harness score assertions hold; usage fields untouched. Both render/ and harness/ cargo test suites green in mock mode; no live IONOS call. Run the harness budget/reference tests with AIL_BIN pointing at target/debug/ail (ail is not on PATH in the test env).
This commit is contained in:
+2
-2
@@ -30,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"content": "{\n \"schema\": \"ailang/v0\",\n \"name\": \"t3_main_prints\",\n \"imports\": [],\n \"defs\": [\n {\n \"kind\": \"fn\",\n \"name\": \"main\",\n \"type\": {\n \"k\": \"fn\",\n \"params\": [],\n \"ret\": { \"k\": \"con\", \"name\": \"Unit\" },\n \"effects\": [\"IO\"]\n },\n \"params\": [],\n \"body\": {\n \"t\": \"seq\",\n \"lhs\": {\n \"t\": \"do\",\n \"op\": \"io/print_int\",\n \"args\": [{ \"t\": \"lit\", \"lit\": { \"kind\": \"int\", \"value\": 42 } }]\n },\n \"rhs\": {\n \"t\": \"do\",\n \"op\": \"io/print_int\",\n \"args\": [{ \"t\": \"lit\", \"lit\": { \"kind\": \"int\", \"value\": 1337 } }]\n }\n }\n }\n ]\n}\n",
|
"content": "{\n \"schema\": \"ailang/v0\",\n \"name\": \"t3_main_prints\",\n \"imports\": [],\n \"defs\": [\n {\n \"kind\": \"fn\",\n \"name\": \"main\",\n \"type\": {\n \"k\": \"fn\",\n \"params\": [],\n \"param_modes\": [],\n \"ret\": {\n \"k\": \"con\",\n \"name\": \"Unit\"\n },\n \"ret_mode\": \"own\",\n \"effects\": [\n \"IO\"\n ]\n },\n \"params\": [],\n \"body\": {\n \"t\": \"seq\",\n \"lhs\": {\n \"t\": \"seq\",\n \"lhs\": {\n \"t\": \"do\",\n \"op\": \"io/print_str\",\n \"args\": [\n {\n \"t\": \"app\",\n \"fn\": {\n \"t\": \"var\",\n \"name\": \"int_to_str\"\n },\n \"args\": [\n {\n \"t\": \"lit\",\n \"lit\": {\n \"kind\": \"int\",\n \"value\": 42\n }\n }\n ]\n }\n ]\n },\n \"rhs\": {\n \"t\": \"do\",\n \"op\": \"io/print_str\",\n \"args\": [\n {\n \"t\": \"lit\",\n \"lit\": {\n \"kind\": \"str\",\n \"value\": \"\\n\"\n }\n }\n ]\n }\n },\n \"rhs\": {\n \"t\": \"seq\",\n \"lhs\": {\n \"t\": \"do\",\n \"op\": \"io/print_str\",\n \"args\": [\n {\n \"t\": \"app\",\n \"fn\": {\n \"t\": \"var\",\n \"name\": \"int_to_str\"\n },\n \"args\": [\n {\n \"t\": \"lit\",\n \"lit\": {\n \"kind\": \"int\",\n \"value\": 1337\n }\n }\n ]\n }\n ]\n },\n \"rhs\": {\n \"t\": \"do\",\n \"op\": \"io/print_str\",\n \"args\": [\n {\n \"t\": \"lit\",\n \"lit\": {\n \"kind\": \"str\",\n \"value\": \"\\n\"\n }\n }\n ]\n }\n }\n }\n }\n ]\n}\n",
|
||||||
"usage": {
|
"usage": {
|
||||||
"prompt_tokens": 1200,
|
"prompt_tokens": 1200,
|
||||||
"completion_tokens": 200,
|
"completion_tokens": 200,
|
||||||
@@ -123,4 +123,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
|
"param_modes": [],
|
||||||
"ret": { "k": "con", "name": "Bool" },
|
"ret": { "k": "con", "name": "Bool" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -23,7 +25,9 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
|
"param_modes": [],
|
||||||
"ret": { "k": "con", "name": "Str" },
|
"ret": { "k": "con", "name": "Str" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -36,7 +40,9 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
|
"param_modes": [],
|
||||||
"ret": { "k": "con", "name": "Unit" },
|
"ret": { "k": "con", "name": "Unit" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "var", "name": "a" } ],
|
"params": [ { "k": "var", "name": "a" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Str" },
|
"ret": { "k": "con", "name": "Str" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1 @@
|
|||||||
{
|
{"defs":[{"ctors":[{"fields":[{"k":"var","name":"a"}],"name":"MkBox"}],"kind":"type","name":"Box","vars":["a"]},{"body":{"arms":[{"body":{"body":{"args":[{"lit":{"kind":"int","value":1},"t":"lit"}],"ctor":"MkBox","t":"ctor","type":"Box"},"source":{"name":"src","t":"var"},"t":"reuse-as"},"pat":{"ctor":"MkBox","fields":[{"name":"v","p":"var"}],"p":"ctor"}}],"scrutinee":{"name":"src","t":"var"},"t":"match"},"kind":"fn","name":"wrap_one","params":["src"],"type":{"effects":[],"k":"fn","param_modes":["own"],"params":[{"args":[{"k":"con","name":"Int"}],"k":"con","name":"Box"}],"ret":{"args":[{"k":"con","name":"Int"}],"k":"con","name":"Box"},"ret_mode":"own"}}],"imports":[],"name":"data_simple","schema":"ailang/v0"}
|
||||||
"schema": "ailang/v0",
|
|
||||||
"name": "data_simple",
|
|
||||||
"imports": [],
|
|
||||||
"defs": [
|
|
||||||
{
|
|
||||||
"kind": "type",
|
|
||||||
"name": "Box",
|
|
||||||
"vars": ["a"],
|
|
||||||
"doc": "A unary box around a polymorphic value.",
|
|
||||||
"ctors": [
|
|
||||||
{
|
|
||||||
"name": "MkBox",
|
|
||||||
"fields": [ { "k": "var", "name": "a" } ]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "fn",
|
|
||||||
"name": "wrap_one",
|
|
||||||
"doc": "Construct a Box Int via MkBox. The body uses (reuse-as src body) — a hint that the freshly-allocated Box should reuse the source's memory slot under --alloc=rc. Exercises TermCtor, ReuseAs, and Type::Var inside a ctor field position.",
|
|
||||||
"type": {
|
|
||||||
"k": "fn",
|
|
||||||
"params": [
|
|
||||||
{ "k": "con", "name": "Box", "args": [ { "k": "con", "name": "Int" } ] }
|
|
||||||
],
|
|
||||||
"param_modes": ["own"],
|
|
||||||
"ret": { "k": "con", "name": "Box", "args": [ { "k": "con", "name": "Int" } ] },
|
|
||||||
"ret_mode": "own",
|
|
||||||
"effects": []
|
|
||||||
},
|
|
||||||
"params": ["src"],
|
|
||||||
"body": {
|
|
||||||
"t": "reuse-as",
|
|
||||||
"source": { "t": "var", "name": "src" },
|
|
||||||
"body": {
|
|
||||||
"t": "ctor",
|
|
||||||
"type": "Box",
|
|
||||||
"ctor": "MkBox",
|
|
||||||
"args": [ { "t": "lit", "lit": { "kind": "int", "value": 1 } } ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
+145
-33
@@ -6,14 +6,23 @@
|
|||||||
{
|
{
|
||||||
"kind": "type",
|
"kind": "type",
|
||||||
"name": "List",
|
"name": "List",
|
||||||
"doc": "Monomorphic singly-linked Int list — boxed, recursive.",
|
"doc": "Monomorphic singly-linked Int list \u2014 boxed, recursive.",
|
||||||
"ctors": [
|
"ctors": [
|
||||||
{ "name": "Nil", "fields": [] },
|
{
|
||||||
|
"name": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Cons",
|
"name": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "k": "con", "name": "Int" },
|
{
|
||||||
{ "k": "con", "name": "List" }
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "List"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -24,30 +33,64 @@
|
|||||||
"doc": "Return the head of xs, or 0 if empty. Exercises TermMatch with two arms, PatternCtor (both nullary Nil and binary Cons), and PatternWild on the tail field.",
|
"doc": "Return the head of xs, or 0 if empty. Exercises TermMatch with two arms, PatternCtor (both nullary Nil and binary Cons), and PatternWild on the tail field.",
|
||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "List" } ],
|
"params": [
|
||||||
"param_modes": ["borrow"],
|
{
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"k": "con",
|
||||||
|
"name": "List"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"param_modes": [
|
||||||
|
"borrow"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["xs"],
|
"params": [
|
||||||
|
"xs"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "match",
|
"t": "match",
|
||||||
"scrutinee": { "t": "var", "name": "xs" },
|
"scrutinee": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "xs"
|
||||||
|
},
|
||||||
"arms": [
|
"arms": [
|
||||||
{
|
{
|
||||||
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
|
"pat": {
|
||||||
"body": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
"p": "ctor",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pat": {
|
"pat": {
|
||||||
"p": "ctor",
|
"p": "ctor",
|
||||||
"ctor": "Cons",
|
"ctor": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "p": "var", "name": "h" },
|
{
|
||||||
{ "p": "wild" }
|
"p": "var",
|
||||||
|
"name": "h"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "wild"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"body": { "t": "var", "name": "h" }
|
"body": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "h"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -58,49 +101,110 @@
|
|||||||
"doc": "Walk xs counting nodes using a local recursive let. Exercises TermLetRec and TermVar; the recursive `go` is bound locally.",
|
"doc": "Walk xs counting nodes using a local recursive let. Exercises TermLetRec and TermVar; the recursive `go` is bound locally.",
|
||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "List" } ],
|
"params": [
|
||||||
"param_modes": ["borrow"],
|
{
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"k": "con",
|
||||||
|
"name": "List"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"param_modes": [
|
||||||
|
"own"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["xs"],
|
"params": [
|
||||||
|
"xs"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "letrec",
|
"t": "letrec",
|
||||||
"name": "go",
|
"name": "go",
|
||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "List" } ],
|
"params": [
|
||||||
"param_modes": ["borrow"],
|
{
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"k": "con",
|
||||||
|
"name": "List"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"param_modes": [
|
||||||
|
"own"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["ys"],
|
"params": [
|
||||||
|
"ys"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "match",
|
"t": "match",
|
||||||
"scrutinee": { "t": "var", "name": "ys" },
|
"scrutinee": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "ys"
|
||||||
|
},
|
||||||
"arms": [
|
"arms": [
|
||||||
{
|
{
|
||||||
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
|
"pat": {
|
||||||
"body": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
"p": "ctor",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pat": {
|
"pat": {
|
||||||
"p": "ctor",
|
"p": "ctor",
|
||||||
"ctor": "Cons",
|
"ctor": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "p": "wild" },
|
{
|
||||||
{ "p": "var", "name": "t" }
|
"p": "wild"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "var",
|
||||||
|
"name": "t"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"body": {
|
"body": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "+" },
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "+"
|
||||||
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 1 } },
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "go" },
|
"fn": {
|
||||||
"args": [ { "t": "var", "name": "t" } ]
|
"t": "var",
|
||||||
|
"name": "go"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "t"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -109,8 +213,16 @@
|
|||||||
},
|
},
|
||||||
"in": {
|
"in": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "go" },
|
"fn": {
|
||||||
"args": [ { "t": "var", "name": "xs" } ]
|
"t": "var",
|
||||||
|
"name": "go"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "xs"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@
|
|||||||
{ "k": "con", "name": "Int" },
|
{ "k": "con", "name": "Int" },
|
||||||
{ "k": "con", "name": "Int" }
|
{ "k": "con", "name": "Int" }
|
||||||
],
|
],
|
||||||
|
"param_modes": ["own", "own"],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["x", "y"],
|
"params": ["x", "y"],
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
|
"param_modes": [],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
|
|||||||
+81
-8
@@ -10,21 +10,94 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
"ret": { "k": "con", "name": "Unit" },
|
"param_modes": [],
|
||||||
"effects": ["IO"]
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Unit"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
|
"effects": [
|
||||||
|
"IO"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "seq",
|
"t": "seq",
|
||||||
"lhs": {
|
"lhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [ { "t": "lit", "lit": { "kind": "int", "value": 1 } } ]
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"rhs": {
|
"rhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [ { "t": "lit", "lit": { "kind": "int", "value": 2 } } ]
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,16 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
"params": [ { "k": "con", "name": "Int" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": {
|
"ret": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
"params": [ { "k": "con", "name": "Int" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["x"],
|
"params": ["x"],
|
||||||
|
|||||||
+2
@@ -13,7 +13,9 @@
|
|||||||
"body": {
|
"body": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "var", "name": "a" } ],
|
"params": [ { "k": "var", "name": "a" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "var", "name": "a" },
|
"ret": { "k": "var", "name": "a" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "var", "name": "a" } ],
|
"params": [ { "k": "var", "name": "a" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Str" },
|
"ret": { "k": "con", "name": "Str" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{"defs":[{"body":{"binders":[{"init":{"lit":{"kind":"int","value":0},"t":"lit"},"name":"acc","type":{"k":"con","name":"Int"}},{"init":{"lit":{"kind":"int","value":1},"t":"lit"},"name":"i","type":{"k":"con","name":"Int"}}],"body":{"cond":{"args":[{"name":"i","t":"var"},{"name":"n","t":"var"}],"fn":{"name":"gt","t":"var"},"t":"app"},"else":{"args":[{"args":[{"name":"acc","t":"var"},{"name":"i","t":"var"}],"fn":{"name":"+","t":"var"},"t":"app"},{"args":[{"name":"i","t":"var"},{"lit":{"kind":"int","value":1},"t":"lit"}],"fn":{"name":"+","t":"var"},"t":"app"}],"t":"recur"},"t":"if","then":{"name":"acc","t":"var"}},"t":"loop"},"kind":"fn","name":"sum_to","params":["n"],"type":{"effects":[],"k":"fn","param_modes":["own"],"params":[{"k":"con","name":"Int"}],"ret":{"k":"con","name":"Int"},"ret_mode":"own"}}],"imports":[],"name":"loop_sum","schema":"ailang/v0"}
|
||||||
+6
-2
@@ -10,7 +10,9 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
"params": [ { "k": "con", "name": "Int" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["n"],
|
"params": ["n"],
|
||||||
@@ -36,7 +38,9 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
"params": [ { "k": "con", "name": "Int" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["n"],
|
"params": ["n"],
|
||||||
@@ -44,7 +48,7 @@
|
|||||||
"t": "if",
|
"t": "if",
|
||||||
"cond": {
|
"cond": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "<" },
|
"fn": { "t": "var", "name": "lt" },
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "var", "name": "n" },
|
{ "t": "var", "name": "n" },
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
||||||
@@ -55,7 +59,7 @@
|
|||||||
"t": "if",
|
"t": "if",
|
||||||
"cond": {
|
"cond": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "==" },
|
"fn": { "t": "var", "name": "eq" },
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "var", "name": "n" },
|
{ "t": "var", "name": "n" },
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{"defs":[{"body":{"body":{"args":[{"args":[{"name":"b","t":"var"}],"fn":{"name":"RawBuf.size","t":"var"},"t":"app"}],"fn":{"name":"print","t":"var"},"t":"app"},"name":"b","t":"let","value":{"args":[{"kind":"type","value":{"k":"con","name":"Int"}},{"kind":"value","value":{"lit":{"kind":"int","value":3},"t":"lit"}}],"t":"new","type":"RawBuf"}},"kind":"fn","name":"main","params":[],"type":{"effects":["IO"],"k":"fn","param_modes":[],"params":[],"ret":{"k":"con","name":"Unit"},"ret_mode":"own"}}],"imports":[],"name":"new_rawbuf","schema":"ailang/v0"}
|
||||||
+1
-48
@@ -1,48 +1 @@
|
|||||||
{
|
{"defs":[{"ctors":[{"fields":[],"name":"Nil"},{"fields":[{"k":"con","name":"Int"},{"k":"con","name":"List"}],"name":"Cons"}],"kind":"type","name":"List"},{"body":{"name":"x","t":"var"},"doc":"(own Int) — unboxed value types (Int/Bool/Float/Unit) are always own; borrow over them is a borrow-over-value error.","kind":"fn","name":"f_own_value","params":["x"],"type":{"effects":[],"k":"fn","param_modes":["own"],"params":[{"k":"con","name":"Int"}],"ret":{"k":"con","name":"Int"},"ret_mode":"own"}},{"body":{"arms":[{"body":{"lit":{"kind":"int","value":0},"t":"lit"},"pat":{"ctor":"Nil","fields":[],"p":"ctor"}},{"body":{"args":[{"lit":{"kind":"int","value":1},"t":"lit"},{"args":[{"name":"t","t":"var"}],"fn":{"name":"f_borrow_boxed","t":"var"},"t":"app"}],"fn":{"name":"+","t":"var"},"t":"app"},"pat":{"ctor":"Cons","fields":[{"name":"h","p":"var"},{"name":"t","p":"var"}],"p":"ctor"}}],"scrutinee":{"name":"xs","t":"var"},"t":"match"},"doc":"(borrow List) — boxed types may be borrowed; the callee reads without consuming.","kind":"fn","name":"f_borrow_boxed","params":["xs"],"type":{"effects":[],"k":"fn","param_modes":["borrow"],"params":[{"k":"con","name":"List"}],"ret":{"k":"con","name":"Int"},"ret_mode":"own"}}],"imports":[],"name":"param_modes_all","schema":"ailang/v0"}
|
||||||
"schema": "ailang/v0",
|
|
||||||
"name": "param_modes_all",
|
|
||||||
"imports": [],
|
|
||||||
"defs": [
|
|
||||||
{
|
|
||||||
"kind": "fn",
|
|
||||||
"name": "f_implicit",
|
|
||||||
"doc": "Implicit mode is the legacy default — `param_modes` is omitted from canonical JSON when every entry is Implicit, which is the case here. The visitor still observes ParamMode::Implicit via the (defaulted) ret_mode field on Type::Fn.",
|
|
||||||
"type": {
|
|
||||||
"k": "fn",
|
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
|
||||||
"ret": { "k": "con", "name": "Int" },
|
|
||||||
"effects": []
|
|
||||||
},
|
|
||||||
"params": ["x"],
|
|
||||||
"body": { "t": "var", "name": "x" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "fn",
|
|
||||||
"name": "f_own",
|
|
||||||
"doc": "(own T) — caller transfers ownership; callee consumes.",
|
|
||||||
"type": {
|
|
||||||
"k": "fn",
|
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
|
||||||
"param_modes": ["own"],
|
|
||||||
"ret": { "k": "con", "name": "Int" },
|
|
||||||
"effects": []
|
|
||||||
},
|
|
||||||
"params": ["x"],
|
|
||||||
"body": { "t": "var", "name": "x" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "fn",
|
|
||||||
"name": "f_borrow",
|
|
||||||
"doc": "(borrow T) — caller retains ownership; callee may not consume.",
|
|
||||||
"type": {
|
|
||||||
"k": "fn",
|
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
|
||||||
"param_modes": ["borrow"],
|
|
||||||
"ret": { "k": "con", "name": "Int" },
|
|
||||||
"effects": []
|
|
||||||
},
|
|
||||||
"params": ["x"],
|
|
||||||
"body": { "t": "var", "name": "x" }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -133,38 +133,30 @@ BODY-TYPE)`.
|
|||||||
|
|
||||||
## 4. Mode annotations
|
## 4. Mode annotations
|
||||||
|
|
||||||
Every function parameter carries a mode. The mode says how the
|
Every function parameter carries a mode, and so does the return
|
||||||
callee may treat the value: `implicit` is the legacy default
|
position. There are exactly two modes. `own` means the caller
|
||||||
(treated as `own`), `own` means the caller transfers ownership and
|
transfers ownership and the callee consumes the value; `borrow`
|
||||||
the callee consumes the value, `borrow` means the caller retains
|
means the caller retains ownership and the callee may inspect but
|
||||||
ownership and the callee may inspect but not consume.
|
not consume. `borrow` is legal only over a boxed type (an algebraic
|
||||||
|
data type): unboxed value types (`Int`, `Bool`, `Float`, `Unit`)
|
||||||
|
are always `own`, and borrowing one is a `borrow-over-value` error.
|
||||||
|
|
||||||
The mode also applies to the return value: `ret_mode` says whether
|
The return position is always `own` — a function returns a fresh
|
||||||
the function transfers ownership to the caller (`own`) or returns a
|
owned value; borrow-returns are not permitted.
|
||||||
borrow (`borrow`). For most functions the return mode is `own` or
|
|
||||||
implicit; `borrow` returns are rare and used only for accessor-style
|
|
||||||
functions.
|
|
||||||
|
|
||||||
Modes are mandatory on every parameter and on the return position.
|
Modes are mandatory: every parameter and the return position carries
|
||||||
The schema rejects unannotated fn signatures only when annotations
|
exactly one mode. There is no default or omitted mode.
|
||||||
are explicitly requested; for compatibility the legacy form (no
|
|
||||||
mode field at all) is treated as all-implicit.
|
|
||||||
|
|
||||||
{form-only: json}
|
{form-only: json}
|
||||||
On `Type::Fn`, two optional fields carry modes:
|
On `Type::Fn`, two required fields carry modes:
|
||||||
|
|
||||||
- `param_modes`: array of strings `"implicit"`, `"own"`, or
|
- `param_modes`: an array of strings, each `"own"` or `"borrow"`,
|
||||||
`"borrow"`, one per parameter, in the same order as `params`. The
|
one per parameter, in the same order as `params`.
|
||||||
array is omitted from the canonical bytes when every entry is
|
- `ret_mode`: a single string, always `"own"`.
|
||||||
`"implicit"`; this is purely a serialisation optimisation. Author
|
|
||||||
the field explicitly when at least one parameter is `own` or
|
|
||||||
`borrow`.
|
|
||||||
- `ret_mode`: a single string of the same vocabulary. Omitted when
|
|
||||||
it would be `"implicit"`.
|
|
||||||
|
|
||||||
Example: a fn that borrows two ints and returns an int:
|
Both are present on every fn type. Example — a fn that borrows a
|
||||||
`"param_modes": ["borrow", "borrow"]`, `ret_mode` omitted (implicit).
|
boxed list and returns an int: `"param_modes": ["borrow"]`,
|
||||||
A fn that consumes a list and returns a new list:
|
`"ret_mode": "own"`. A fn that consumes an int and returns an int:
|
||||||
`"param_modes": ["own"]`, `"ret_mode": "own"`.
|
`"param_modes": ["own"]`, `"ret_mode": "own"`.
|
||||||
{/form-only}
|
{/form-only}
|
||||||
|
|
||||||
@@ -173,21 +165,13 @@ Modes are surface wrappers around the type in parameter and return
|
|||||||
position. Inside a `(fn-type ...)`:
|
position. Inside a `(fn-type ...)`:
|
||||||
|
|
||||||
- `(params (own T1) (borrow T2))` — `T1` is owned, `T2` is borrowed.
|
- `(params (own T1) (borrow T2))` — `T1` is owned, `T2` is borrowed.
|
||||||
- `(ret (own T))` — the function returns an owned value.
|
- `(ret (own T))` — the return is always owned.
|
||||||
- A bare type with no mode wrapper is implicit (legacy default).
|
|
||||||
|
|
||||||
When all parameters and the return are implicit, the surface omits
|
Every parameter and the return carries a mode wrapper; there is no
|
||||||
the mode wrappers entirely; this is the canonical form for fns that
|
bare-type (mode-less) form. `borrow` is legal only over a boxed
|
||||||
do not yet need explicit annotations. Adding modes is a forward
|
type: `(borrow (con Int))` is a `borrow-over-value` error — write
|
||||||
change: an existing fn keeps the same canonical bytes as long as no
|
`(own (con Int))`. The mode is part of the fn's signature and
|
||||||
annotation is added.
|
contributes to its content hash.
|
||||||
|
|
||||||
Writing `(borrow T)` on a parameter the typechecker wants `own`
|
|
||||||
for surfaces as the `over-strict-mode` diagnostic — advisory, and
|
|
||||||
suppressable via the fn def's `suppress` clause. The mode is part
|
|
||||||
of the fn's signature and contributes to its content hash, so
|
|
||||||
making the choice explicit at authoring time avoids surprise
|
|
||||||
hash changes when the typechecker's defaults shift.
|
|
||||||
{/form-only}
|
{/form-only}
|
||||||
|
|
||||||
{example: param_modes_all}
|
{example: param_modes_all}
|
||||||
|
|||||||
+170
-30
@@ -9,25 +9,62 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [
|
"params": [
|
||||||
{ "k": "con", "name": "Int" },
|
{
|
||||||
{ "k": "con", "name": "Int" },
|
"k": "con",
|
||||||
{ "k": "con", "name": "Int" }
|
"name": "Int"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"param_modes": [
|
||||||
|
"own",
|
||||||
|
"own",
|
||||||
|
"own"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["a", "b", "c"],
|
"params": [
|
||||||
|
"a",
|
||||||
|
"b",
|
||||||
|
"c"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "+" },
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "+"
|
||||||
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "var", "name": "a" },
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "a"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "+" },
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "+"
|
||||||
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "var", "name": "b" },
|
{
|
||||||
{ "t": "var", "name": "c" }
|
"t": "var",
|
||||||
|
"name": "b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "c"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -39,37 +76,140 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
"ret": { "k": "con", "name": "Unit" },
|
"param_modes": [],
|
||||||
"effects": ["IO"]
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Unit"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
|
"effects": [
|
||||||
|
"IO"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "seq",
|
"t": "seq",
|
||||||
"lhs": {
|
"lhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [{
|
"t": "do",
|
||||||
"t": "app",
|
"op": "io/print_str",
|
||||||
"fn": { "t": "var", "name": "add_three" },
|
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 1 } },
|
{
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 2 } },
|
"t": "app",
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 3 } }
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "add_three"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}]
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"rhs": {
|
"rhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [{
|
"t": "do",
|
||||||
"t": "app",
|
"op": "io/print_str",
|
||||||
"fn": { "t": "var", "name": "add_three" },
|
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 10 } },
|
{
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 20 } },
|
"t": "app",
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 30 } }
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "add_three"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 30
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}]
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+227
-50
@@ -6,14 +6,31 @@
|
|||||||
{
|
{
|
||||||
"kind": "type",
|
"kind": "type",
|
||||||
"name": "List",
|
"name": "List",
|
||||||
"vars": ["a"],
|
"vars": [
|
||||||
|
"a"
|
||||||
|
],
|
||||||
"ctors": [
|
"ctors": [
|
||||||
{ "name": "Nil", "fields": [] },
|
{
|
||||||
|
"name": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Cons",
|
"name": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "k": "var", "name": "a" },
|
{
|
||||||
{ "k": "con", "name": "List", "args": [{ "k": "var", "name": "a" }] }
|
"k": "var",
|
||||||
|
"name": "a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "List",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"k": "var",
|
||||||
|
"name": "a"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -23,43 +40,98 @@
|
|||||||
"name": "length",
|
"name": "length",
|
||||||
"type": {
|
"type": {
|
||||||
"k": "forall",
|
"k": "forall",
|
||||||
"vars": ["a"],
|
"vars": [
|
||||||
|
"a"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [
|
"params": [
|
||||||
{ "k": "con", "name": "List", "args": [{ "k": "var", "name": "a" }] }
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "List",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"k": "var",
|
||||||
|
"name": "a"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"param_modes": [
|
||||||
|
"own"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"params": ["xs"],
|
"params": [
|
||||||
|
"xs"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "match",
|
"t": "match",
|
||||||
"scrutinee": { "t": "var", "name": "xs" },
|
"scrutinee": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "xs"
|
||||||
|
},
|
||||||
"arms": [
|
"arms": [
|
||||||
{
|
{
|
||||||
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
|
"pat": {
|
||||||
"body": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
"p": "ctor",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pat": {
|
"pat": {
|
||||||
"p": "ctor",
|
"p": "ctor",
|
||||||
"ctor": "Cons",
|
"ctor": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "p": "wild" },
|
{
|
||||||
{ "p": "var", "name": "rest" }
|
"p": "wild"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "var",
|
||||||
|
"name": "rest"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"body": {
|
"body": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "+" },
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "+"
|
||||||
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 1 } },
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "length" },
|
"fn": {
|
||||||
"args": [{ "t": "var", "name": "rest" }]
|
"t": "var",
|
||||||
|
"name": "length"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "rest"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -73,47 +145,152 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
"ret": { "k": "con", "name": "Unit" },
|
"param_modes": [],
|
||||||
"effects": ["IO"]
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Unit"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
|
"effects": [
|
||||||
|
"IO"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "seq",
|
"t": "seq",
|
||||||
"lhs": {
|
"lhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [{
|
"t": "do",
|
||||||
"t": "app",
|
"op": "io/print_str",
|
||||||
"fn": { "t": "var", "name": "length" },
|
"args": [
|
||||||
"args": [{ "t": "ctor", "type": "List", "ctor": "Nil", "args": [] }]
|
{
|
||||||
}]
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "length"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"rhs": {
|
"rhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [{
|
"t": "do",
|
||||||
"t": "app",
|
"op": "io/print_str",
|
||||||
"fn": { "t": "var", "name": "length" },
|
"args": [
|
||||||
"args": [{
|
{
|
||||||
"t": "ctor", "type": "List", "ctor": "Cons",
|
"t": "app",
|
||||||
"args": [
|
"fn": {
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 7 } },
|
"t": "var",
|
||||||
{
|
"name": "int_to_str"
|
||||||
"t": "ctor", "type": "List", "ctor": "Cons",
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 8 } },
|
{
|
||||||
{
|
"t": "app",
|
||||||
"t": "ctor", "type": "List", "ctor": "Cons",
|
"fn": {
|
||||||
"args": [
|
"t": "var",
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 9 } },
|
"name": "length"
|
||||||
{ "t": "ctor", "type": "List", "ctor": "Nil", "args": [] }
|
},
|
||||||
]
|
"args": [
|
||||||
}
|
{
|
||||||
]
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Cons",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Cons",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Cons",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}]
|
]
|
||||||
}]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+81
-8
@@ -9,21 +9,94 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
"ret": { "k": "con", "name": "Unit" },
|
"param_modes": [],
|
||||||
"effects": ["IO"]
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Unit"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
|
"effects": [
|
||||||
|
"IO"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "seq",
|
"t": "seq",
|
||||||
"lhs": {
|
"lhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [{ "t": "lit", "lit": { "kind": "int", "value": 42 } }]
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"rhs": {
|
"rhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [{ "t": "lit", "lit": { "kind": "int", "value": 1337 } }]
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 1337
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+277
-65
@@ -6,14 +6,31 @@
|
|||||||
{
|
{
|
||||||
"kind": "type",
|
"kind": "type",
|
||||||
"name": "List",
|
"name": "List",
|
||||||
"vars": ["a"],
|
"vars": [
|
||||||
|
"a"
|
||||||
|
],
|
||||||
"ctors": [
|
"ctors": [
|
||||||
{ "name": "Nil", "fields": [] },
|
{
|
||||||
|
"name": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Cons",
|
"name": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "k": "var", "name": "a" },
|
{
|
||||||
{ "k": "con", "name": "List", "args": [{ "k": "var", "name": "a" }] }
|
"k": "var",
|
||||||
|
"name": "a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "List",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"k": "var",
|
||||||
|
"name": "a"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -24,55 +41,129 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [
|
"params": [
|
||||||
{ "k": "con", "name": "List", "args": [{ "k": "con", "name": "Int" }] }
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "List",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"param_modes": [
|
||||||
|
"own"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["xs"],
|
"params": [
|
||||||
|
"xs"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "match",
|
"t": "match",
|
||||||
"scrutinee": { "t": "var", "name": "xs" },
|
"scrutinee": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "xs"
|
||||||
|
},
|
||||||
"arms": [
|
"arms": [
|
||||||
{
|
{
|
||||||
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
|
"pat": {
|
||||||
"body": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
"p": "ctor",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pat": {
|
"pat": {
|
||||||
"p": "ctor",
|
"p": "ctor",
|
||||||
"ctor": "Cons",
|
"ctor": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "p": "var", "name": "h" },
|
{
|
||||||
{ "p": "var", "name": "rest" }
|
"p": "var",
|
||||||
|
"name": "h"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "var",
|
||||||
|
"name": "rest"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"body": {
|
"body": {
|
||||||
"t": "if",
|
"t": "if",
|
||||||
"cond": {
|
"cond": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "eq" },
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "eq"
|
||||||
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "var", "name": "h" },
|
{
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
"t": "var",
|
||||||
|
"name": "h"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "+" },
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "+"
|
||||||
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 1 } },
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "count_zeros" },
|
"fn": {
|
||||||
"args": [{ "t": "var", "name": "rest" }]
|
"t": "var",
|
||||||
|
"name": "count_zeros"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "rest"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"else": {
|
"else": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "count_zeros" },
|
"fn": {
|
||||||
"args": [{ "t": "var", "name": "rest" }]
|
"t": "var",
|
||||||
|
"name": "count_zeros"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "rest"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,59 +176,180 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
"ret": { "k": "con", "name": "Unit" },
|
"param_modes": [],
|
||||||
"effects": ["IO"]
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Unit"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
|
"effects": [
|
||||||
|
"IO"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "seq",
|
"t": "seq",
|
||||||
"lhs": {
|
"lhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [{
|
"t": "do",
|
||||||
"t": "app",
|
"op": "io/print_str",
|
||||||
"fn": { "t": "var", "name": "count_zeros" },
|
"args": [
|
||||||
"args": [{ "t": "ctor", "type": "List", "ctor": "Nil", "args": [] }]
|
{
|
||||||
}]
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "count_zeros"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"rhs": {
|
"rhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [{
|
"t": "do",
|
||||||
"t": "app",
|
"op": "io/print_str",
|
||||||
"fn": { "t": "var", "name": "count_zeros" },
|
"args": [
|
||||||
"args": [{
|
{
|
||||||
"t": "ctor", "type": "List", "ctor": "Cons",
|
"t": "app",
|
||||||
"args": [
|
"fn": {
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 0 } },
|
"t": "var",
|
||||||
{
|
"name": "int_to_str"
|
||||||
"t": "ctor", "type": "List", "ctor": "Cons",
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 5 } },
|
{
|
||||||
{
|
"t": "app",
|
||||||
"t": "ctor", "type": "List", "ctor": "Cons",
|
"fn": {
|
||||||
"args": [
|
"t": "var",
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 0 } },
|
"name": "count_zeros"
|
||||||
{
|
},
|
||||||
"t": "ctor", "type": "List", "ctor": "Cons",
|
"args": [
|
||||||
"args": [
|
{
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 3 } },
|
"t": "ctor",
|
||||||
{
|
"type": "List",
|
||||||
"t": "ctor", "type": "List", "ctor": "Cons",
|
"ctor": "Cons",
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 0 } },
|
{
|
||||||
{ "t": "ctor", "type": "List", "ctor": "Nil", "args": [] }
|
"t": "lit",
|
||||||
]
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
}
|
}
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
]
|
"t": "ctor",
|
||||||
}
|
"type": "List",
|
||||||
]
|
"ctor": "Cons",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Cons",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Cons",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Cons",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": "ctor",
|
||||||
|
"type": "List",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}]
|
]
|
||||||
}]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use std::collections::HashSet;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use ailang_core::ast::{
|
use ailang_core::ast::{
|
||||||
Def, InstanceMethod, Literal, Module, ParamMode, Pattern, Term, Type,
|
Def, InstanceMethod, Literal, Module, NewArg, ParamMode, Pattern, Term, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
@@ -41,6 +41,9 @@ enum VariantTag {
|
|||||||
TermSeq,
|
TermSeq,
|
||||||
TermClone,
|
TermClone,
|
||||||
TermReuseAs,
|
TermReuseAs,
|
||||||
|
TermLoop,
|
||||||
|
TermRecur,
|
||||||
|
TermNew,
|
||||||
// Pattern
|
// Pattern
|
||||||
PatternWild,
|
PatternWild,
|
||||||
PatternVar,
|
PatternVar,
|
||||||
@@ -58,7 +61,6 @@ enum VariantTag {
|
|||||||
TypeVar,
|
TypeVar,
|
||||||
TypeForall,
|
TypeForall,
|
||||||
// ParamMode
|
// ParamMode
|
||||||
ParamModeImplicit,
|
|
||||||
ParamModeOwn,
|
ParamModeOwn,
|
||||||
ParamModeBorrow,
|
ParamModeBorrow,
|
||||||
}
|
}
|
||||||
@@ -86,6 +88,9 @@ const EXPECTED_VARIANTS: &[VariantTag] = &[
|
|||||||
VariantTag::TermSeq,
|
VariantTag::TermSeq,
|
||||||
VariantTag::TermClone,
|
VariantTag::TermClone,
|
||||||
VariantTag::TermReuseAs,
|
VariantTag::TermReuseAs,
|
||||||
|
VariantTag::TermLoop,
|
||||||
|
VariantTag::TermRecur,
|
||||||
|
VariantTag::TermNew,
|
||||||
VariantTag::PatternWild,
|
VariantTag::PatternWild,
|
||||||
VariantTag::PatternVar,
|
VariantTag::PatternVar,
|
||||||
VariantTag::PatternLit,
|
VariantTag::PatternLit,
|
||||||
@@ -99,7 +104,6 @@ const EXPECTED_VARIANTS: &[VariantTag] = &[
|
|||||||
VariantTag::TypeFn,
|
VariantTag::TypeFn,
|
||||||
VariantTag::TypeVar,
|
VariantTag::TypeVar,
|
||||||
VariantTag::TypeForall,
|
VariantTag::TypeForall,
|
||||||
VariantTag::ParamModeImplicit,
|
|
||||||
VariantTag::ParamModeOwn,
|
VariantTag::ParamModeOwn,
|
||||||
VariantTag::ParamModeBorrow,
|
VariantTag::ParamModeBorrow,
|
||||||
];
|
];
|
||||||
@@ -222,6 +226,37 @@ fn visit_term(t: &Term, observed: &mut HashSet<VariantTag>) {
|
|||||||
visit_term(source, observed);
|
visit_term(source, observed);
|
||||||
visit_term(body, observed);
|
visit_term(body, observed);
|
||||||
}
|
}
|
||||||
|
Term::Loop { binders, body } => {
|
||||||
|
observed.insert(VariantTag::TermLoop);
|
||||||
|
for b in binders {
|
||||||
|
visit_type(&b.ty, observed);
|
||||||
|
visit_term(&b.init, observed);
|
||||||
|
}
|
||||||
|
visit_term(body, observed);
|
||||||
|
}
|
||||||
|
Term::Recur { args } => {
|
||||||
|
observed.insert(VariantTag::TermRecur);
|
||||||
|
for a in args {
|
||||||
|
visit_term(a, observed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Term::New { type_name: _, args } => {
|
||||||
|
observed.insert(VariantTag::TermNew);
|
||||||
|
for a in args {
|
||||||
|
match a {
|
||||||
|
NewArg::Type(t) => visit_type(t, observed),
|
||||||
|
NewArg::Value(v) => visit_term(v, observed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// `Intrinsic` is the compiler-supplied body marker — non-authorable
|
||||||
|
// (absent from the parser's term dispatch; typecheck enforces
|
||||||
|
// kernel-tier-only via IntrinsicOutsideKernelTier). A foreign-author
|
||||||
|
// mini-spec must not show it and no master example can legally
|
||||||
|
// contain it, so it is allowlisted OUT of completeness: no VariantTag,
|
||||||
|
// no EXPECTED entry, a no-op arm here so the match compiles without
|
||||||
|
// claiming coverage.
|
||||||
|
Term::Intrinsic => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,9 +332,6 @@ fn visit_type(t: &Type, observed: &mut HashSet<VariantTag>) {
|
|||||||
|
|
||||||
fn visit_param_mode(m: &ParamMode, observed: &mut HashSet<VariantTag>) {
|
fn visit_param_mode(m: &ParamMode, observed: &mut HashSet<VariantTag>) {
|
||||||
match m {
|
match m {
|
||||||
ParamMode::Implicit => {
|
|
||||||
observed.insert(VariantTag::ParamModeImplicit);
|
|
||||||
}
|
|
||||||
ParamMode::Own => {
|
ParamMode::Own => {
|
||||||
observed.insert(VariantTag::ParamModeOwn);
|
observed.insert(VariantTag::ParamModeOwn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ through this pair is gated by an integration test.
|
|||||||
(module fn_returns_int
|
(module fn_returns_int
|
||||||
(fn answer
|
(fn answer
|
||||||
(doc "The simplest possible fn — no params, returns a fixed Int.")
|
(doc "The simplest possible fn — no params, returns a fixed Int.")
|
||||||
(type (fn-type (params) (ret (con Int))))
|
(type (fn-type (params) (ret (own (con Int)))))
|
||||||
(params)
|
(params)
|
||||||
(body 42)))
|
(body 42)))
|
||||||
```
|
```
|
||||||
@@ -99,68 +99,57 @@ BODY-TYPE)`.
|
|||||||
(module forall_polymorphic
|
(module forall_polymorphic
|
||||||
(fn id
|
(fn id
|
||||||
(doc "The polymorphic identity function. Exercises Type::Forall and Type::Var.")
|
(doc "The polymorphic identity function. Exercises Type::Forall and Type::Var.")
|
||||||
(type (forall (vars a) (fn-type (params a) (ret a))))
|
(type (forall (vars a) (fn-type (params (own a)) (ret (own a)))))
|
||||||
(params x)
|
(params x)
|
||||||
(body x)))
|
(body x)))
|
||||||
```
|
```
|
||||||
|
|
||||||
## 4. Mode annotations
|
## 4. Mode annotations
|
||||||
|
|
||||||
Every function parameter carries a mode. The mode says how the
|
Every function parameter carries a mode, and so does the return
|
||||||
callee may treat the value: `implicit` is the legacy default
|
position. There are exactly two modes. `own` means the caller
|
||||||
(treated as `own`), `own` means the caller transfers ownership and
|
transfers ownership and the callee consumes the value; `borrow`
|
||||||
the callee consumes the value, `borrow` means the caller retains
|
means the caller retains ownership and the callee may inspect but
|
||||||
ownership and the callee may inspect but not consume.
|
not consume. `borrow` is legal only over a boxed type (an algebraic
|
||||||
|
data type): unboxed value types (`Int`, `Bool`, `Float`, `Unit`)
|
||||||
|
are always `own`, and borrowing one is a `borrow-over-value` error.
|
||||||
|
|
||||||
The mode also applies to the return value: `ret_mode` says whether
|
The return position is always `own` — a function returns a fresh
|
||||||
the function transfers ownership to the caller (`own`) or returns a
|
owned value; borrow-returns are not permitted.
|
||||||
borrow (`borrow`). For most functions the return mode is `own` or
|
|
||||||
implicit; `borrow` returns are rare and used only for accessor-style
|
|
||||||
functions.
|
|
||||||
|
|
||||||
Modes are mandatory on every parameter and on the return position.
|
Modes are mandatory: every parameter and the return position carries
|
||||||
The schema rejects unannotated fn signatures only when annotations
|
exactly one mode. There is no default or omitted mode.
|
||||||
are explicitly requested; for compatibility the legacy form (no
|
|
||||||
mode field at all) is treated as all-implicit.
|
|
||||||
|
|
||||||
|
|
||||||
Modes are surface wrappers around the type in parameter and return
|
Modes are surface wrappers around the type in parameter and return
|
||||||
position. Inside a `(fn-type ...)`:
|
position. Inside a `(fn-type ...)`:
|
||||||
|
|
||||||
- `(params (own T1) (borrow T2))` — `T1` is owned, `T2` is borrowed.
|
- `(params (own T1) (borrow T2))` — `T1` is owned, `T2` is borrowed.
|
||||||
- `(ret (own T))` — the function returns an owned value.
|
- `(ret (own T))` — the return is always owned.
|
||||||
- A bare type with no mode wrapper is implicit (legacy default).
|
|
||||||
|
|
||||||
When all parameters and the return are implicit, the surface omits
|
Every parameter and the return carries a mode wrapper; there is no
|
||||||
the mode wrappers entirely; this is the canonical form for fns that
|
bare-type (mode-less) form. `borrow` is legal only over a boxed
|
||||||
do not yet need explicit annotations. Adding modes is a forward
|
type: `(borrow (con Int))` is a `borrow-over-value` error — write
|
||||||
change: an existing fn keeps the same canonical bytes as long as no
|
`(own (con Int))`. The mode is part of the fn's signature and
|
||||||
annotation is added.
|
contributes to its content hash.
|
||||||
|
|
||||||
Writing `(borrow T)` on a parameter the typechecker wants `own`
|
|
||||||
for surfaces as the `over-strict-mode` diagnostic — advisory, and
|
|
||||||
suppressable via the fn def's `suppress` clause. The mode is part
|
|
||||||
of the fn's signature and contributes to its content hash, so
|
|
||||||
making the choice explicit at authoring time avoids surprise
|
|
||||||
hash changes when the typechecker's defaults shift.
|
|
||||||
|
|
||||||
```ail
|
```ail
|
||||||
(module param_modes_all
|
(module param_modes_all
|
||||||
(fn f_implicit
|
(data List
|
||||||
(doc "Implicit mode is the legacy default — `param_modes` is omitted from canonical JSON when every entry is Implicit, which is the case here. The visitor still observes ParamMode::Implicit via the (defaulted) ret_mode field on Type::Fn.")
|
(ctor Nil)
|
||||||
(type (fn-type (params (con Int)) (ret (con Int))))
|
(ctor Cons (con Int) (con List)))
|
||||||
|
(fn f_own_value
|
||||||
|
(doc "(own Int) — unboxed value types (Int/Bool/Float/Unit) are always own; borrow over them is a borrow-over-value error.")
|
||||||
|
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
|
||||||
(params x)
|
(params x)
|
||||||
(body x))
|
(body x))
|
||||||
(fn f_own
|
(fn f_borrow_boxed
|
||||||
(doc "(own T) — caller transfers ownership; callee consumes.")
|
(doc "(borrow List) — boxed types may be borrowed; the callee reads without consuming.")
|
||||||
(type (fn-type (params (own (con Int))) (ret (con Int))))
|
(type (fn-type (params (borrow (con List))) (ret (own (con Int)))))
|
||||||
(params x)
|
(params xs)
|
||||||
(body x))
|
(body (match xs
|
||||||
(fn f_borrow
|
(case (pat-ctor Nil) 0)
|
||||||
(doc "(borrow T) — caller retains ownership; callee may not consume.")
|
(case (pat-ctor Cons h t) (app + 1 (app f_borrow_boxed t)))))))
|
||||||
(type (fn-type (params (borrow (con Int))) (ret (con Int))))
|
|
||||||
(params x)
|
|
||||||
(body x)))
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 5. Functions
|
## 5. Functions
|
||||||
@@ -211,7 +200,7 @@ number, a string is a double-quoted string, a bool is `true` or
|
|||||||
(module fn_calls_prelude
|
(module fn_calls_prelude
|
||||||
(fn add
|
(fn add
|
||||||
(doc "Add two Ints via the polymorphic prelude `+`. Also exercises TermLet by binding the sum to a local name before returning it, and TermClone by re-using the let-bound value.")
|
(doc "Add two Ints via the polymorphic prelude `+`. Also exercises TermLet by binding the sum to a local name before returning it, and TermClone by re-using the let-bound value.")
|
||||||
(type (fn-type (params (con Int) (con Int)) (ret (con Int))))
|
(type (fn-type (params (own (con Int)) (own (con Int))) (ret (own (con Int)))))
|
||||||
(params x y)
|
(params x y)
|
||||||
(body (let s (app + x y) (clone s)))))
|
(body (let s (app + x y) (clone s)))))
|
||||||
```
|
```
|
||||||
@@ -220,7 +209,7 @@ number, a string is a double-quoted string, a bool is `true` or
|
|||||||
(module fn_with_lambda
|
(module fn_with_lambda
|
||||||
(fn make_adder
|
(fn make_adder
|
||||||
(doc "Curried adder: takes an Int and returns an Int -> Int closure. Exercises TermLam and Type::Fn appearing as a return type.")
|
(doc "Curried adder: takes an Int and returns an Int -> Int closure. Exercises TermLam and Type::Fn appearing as a return type.")
|
||||||
(type (fn-type (params (con Int)) (ret (fn-type (params (con Int)) (ret (con Int))))))
|
(type (fn-type (params (own (con Int))) (ret (own (fn-type (params (own (con Int))) (ret (own (con Int))))))))
|
||||||
(params x)
|
(params x)
|
||||||
(body (lam (params (typed y (con Int))) (ret (con Int)) (body (app + x y))))))
|
(body (lam (params (typed y (con Int))) (ret (con Int)) (body (app + x y))))))
|
||||||
```
|
```
|
||||||
@@ -264,13 +253,12 @@ element list.
|
|||||||
```ail
|
```ail
|
||||||
(module data_simple
|
(module data_simple
|
||||||
(data Box (vars a)
|
(data Box (vars a)
|
||||||
(doc "A unary box around a polymorphic value.")
|
|
||||||
(ctor MkBox a))
|
(ctor MkBox a))
|
||||||
(fn wrap_one
|
(fn wrap_one
|
||||||
(doc "Construct a Box Int via MkBox. The body uses (reuse-as src body) — a hint that the freshly-allocated Box should reuse the source's memory slot under --alloc=rc. Exercises TermCtor, ReuseAs, and Type::Var inside a ctor field position.")
|
|
||||||
(type (fn-type (params (own (con Box (con Int)))) (ret (own (con Box (con Int))))))
|
(type (fn-type (params (own (con Box (con Int)))) (ret (own (con Box (con Int))))))
|
||||||
(params src)
|
(params src)
|
||||||
(body (reuse-as src (term-ctor Box MkBox 1)))))
|
(body (match src
|
||||||
|
(case (pat-ctor MkBox v) (reuse-as src (term-ctor Box MkBox 1)))))))
|
||||||
```
|
```
|
||||||
|
|
||||||
## 7. Pattern matching
|
## 7. Pattern matching
|
||||||
@@ -319,16 +307,16 @@ arms or into code outside the `match`.
|
|||||||
(ctor Cons (con Int) (con List)))
|
(ctor Cons (con Int) (con List)))
|
||||||
(fn head_or_zero
|
(fn head_or_zero
|
||||||
(doc "Return the head of xs, or 0 if empty. Exercises TermMatch with two arms, PatternCtor (both nullary Nil and binary Cons), and PatternWild on the tail field.")
|
(doc "Return the head of xs, or 0 if empty. Exercises TermMatch with two arms, PatternCtor (both nullary Nil and binary Cons), and PatternWild on the tail field.")
|
||||||
(type (fn-type (params (borrow (con List))) (ret (con Int))))
|
(type (fn-type (params (borrow (con List))) (ret (own (con Int)))))
|
||||||
(params xs)
|
(params xs)
|
||||||
(body (match xs
|
(body (match xs
|
||||||
(case (pat-ctor Nil) 0)
|
(case (pat-ctor Nil) 0)
|
||||||
(case (pat-ctor Cons h _) h))))
|
(case (pat-ctor Cons h _) h))))
|
||||||
(fn count_via_letrec
|
(fn count_via_letrec
|
||||||
(doc "Walk xs counting nodes using a local recursive let. Exercises TermLetRec and TermVar; the recursive `go` is bound locally.")
|
(doc "Walk xs counting nodes using a local recursive let. Exercises TermLetRec and TermVar; the recursive `go` is bound locally.")
|
||||||
(type (fn-type (params (borrow (con List))) (ret (con Int))))
|
(type (fn-type (params (own (con List))) (ret (own (con Int)))))
|
||||||
(params xs)
|
(params xs)
|
||||||
(body (let-rec go (params ys) (type (fn-type (params (borrow (con List))) (ret (con Int)))) (body (match ys
|
(body (let-rec go (params ys) (type (fn-type (params (own (con List))) (ret (own (con Int))))) (body (match ys
|
||||||
(case (pat-ctor Nil) 0)
|
(case (pat-ctor Nil) 0)
|
||||||
(case (pat-ctor Cons _ t) (app + 1 (app go t))))) (in (app go xs))))))
|
(case (pat-ctor Cons _ t) (app + 1 (app go t))))) (in (app go xs))))))
|
||||||
```
|
```
|
||||||
@@ -337,16 +325,16 @@ arms or into code outside the `match`.
|
|||||||
(module match_literal_pattern
|
(module match_literal_pattern
|
||||||
(fn classify
|
(fn classify
|
||||||
(doc "Classify an Int via literal patterns plus a wildcard fallback. Exercises PatternLit and PatternWild.")
|
(doc "Classify an Int via literal patterns plus a wildcard fallback. Exercises PatternLit and PatternWild.")
|
||||||
(type (fn-type (params (con Int)) (ret (con Int))))
|
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
|
||||||
(params n)
|
(params n)
|
||||||
(body (match n
|
(body (match n
|
||||||
(case (pat-lit 0) 100)
|
(case (pat-lit 0) 100)
|
||||||
(case _ 200))))
|
(case _ 200))))
|
||||||
(fn sign_if
|
(fn sign_if
|
||||||
(doc "Return -1 / 0 / 1 for the sign of n using nested TermIf. Exercises TermIf in both then/else positions plus TermApp on the polymorphic comparison.")
|
(doc "Return -1 / 0 / 1 for the sign of n using nested TermIf. Exercises TermIf in both then/else positions plus TermApp on the polymorphic comparison.")
|
||||||
(type (fn-type (params (con Int)) (ret (con Int))))
|
(type (fn-type (params (own (con Int))) (ret (own (con Int)))))
|
||||||
(params n)
|
(params n)
|
||||||
(body (if (app < n 0) -1 (if (app == n 0) 0 1)))))
|
(body (if (app lt n 0) -1 (if (app eq n 0) 0 1)))))
|
||||||
```
|
```
|
||||||
|
|
||||||
## 8. Effects
|
## 8. Effects
|
||||||
@@ -390,9 +378,9 @@ value.
|
|||||||
(module fn_with_do_seq
|
(module fn_with_do_seq
|
||||||
(fn main
|
(fn main
|
||||||
(doc "Print two Ints in sequence. Exercises TermDo, TermSeq, and the IO effect on a fn type. The trailing unit return is implicit in the last Do (op returns Unit).")
|
(doc "Print two Ints in sequence. Exercises TermDo, TermSeq, and the IO effect on a fn type. The trailing unit return is implicit in the last Do (op returns Unit).")
|
||||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
(type (fn-type (params) (ret (own (con Unit))) (effects IO)))
|
||||||
(params)
|
(params)
|
||||||
(body (seq (do io/print_int 1) (do io/print_int 2)))))
|
(body (seq (seq (do io/print_str (app int_to_str 1)) (do io/print_str "\n")) (seq (do io/print_str (app int_to_str 2)) (do io/print_str "\n"))))))
|
||||||
```
|
```
|
||||||
|
|
||||||
## 9. Literals
|
## 9. Literals
|
||||||
@@ -447,17 +435,17 @@ authoring surface; for non-finite values use the prelude constants
|
|||||||
(module bool_str
|
(module bool_str
|
||||||
(fn is_true
|
(fn is_true
|
||||||
(doc "Trivial Bool literal. Exercises Literal::Bool.")
|
(doc "Trivial Bool literal. Exercises Literal::Bool.")
|
||||||
(type (fn-type (params) (ret (con Bool))))
|
(type (fn-type (params) (ret (own (con Bool)))))
|
||||||
(params)
|
(params)
|
||||||
(body true))
|
(body true))
|
||||||
(fn greeting
|
(fn greeting
|
||||||
(doc "Trivial Str literal. Exercises Literal::Str.")
|
(doc "Trivial Str literal. Exercises Literal::Str.")
|
||||||
(type (fn-type (params) (ret (con Str))))
|
(type (fn-type (params) (ret (own (con Str)))))
|
||||||
(params)
|
(params)
|
||||||
(body "hi"))
|
(body "hi"))
|
||||||
(fn unit_value
|
(fn unit_value
|
||||||
(doc "Trivial Unit literal — needed so Literal::Unit appears at least once in the corpus.")
|
(doc "Trivial Unit literal — needed so Literal::Unit appears at least once in the corpus.")
|
||||||
(type (fn-type (params) (ret (con Unit))))
|
(type (fn-type (params) (ret (own (con Unit)))))
|
||||||
(params)
|
(params)
|
||||||
(body (lit-unit))))
|
(body (lit-unit))))
|
||||||
```
|
```
|
||||||
@@ -508,7 +496,7 @@ also legal (typically a typecheck error unless an instance exists).
|
|||||||
(param a)
|
(param a)
|
||||||
(doc "A toy single-method class. The instance in instance_def.ail.json provides a body for `show` at type Int.")
|
(doc "A toy single-method class. The instance in instance_def.ail.json provides a body for `show` at type Int.")
|
||||||
(method show
|
(method show
|
||||||
(type (fn-type (params a) (ret (con Str)))))))
|
(type (fn-type (params (own a)) (ret (own (con Str))))))))
|
||||||
```
|
```
|
||||||
|
|
||||||
```ail
|
```ail
|
||||||
@@ -517,7 +505,7 @@ also legal (typically a typecheck error unless an instance exists).
|
|||||||
(param a)
|
(param a)
|
||||||
(doc "Re-declared here so this fixture is self-contained; class_def.ail.json declares the same class verbatim.")
|
(doc "Re-declared here so this fixture is self-contained; class_def.ail.json declares the same class verbatim.")
|
||||||
(method show
|
(method show
|
||||||
(type (fn-type (params a) (ret (con Str))))))
|
(type (fn-type (params (own a)) (ret (own (con Str)))))))
|
||||||
(instance
|
(instance
|
||||||
(class MyShow)
|
(class MyShow)
|
||||||
(type (con Int))
|
(type (con Int))
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ carries a `kind` discriminator.
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
|
"param_modes": [],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -123,7 +125,9 @@ optional `constraints` array for class constraints (see section 10).
|
|||||||
"body": {
|
"body": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "var", "name": "a" } ],
|
"params": [ { "k": "var", "name": "a" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "var", "name": "a" },
|
"ret": { "k": "var", "name": "a" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -136,89 +140,34 @@ optional `constraints` array for class constraints (see section 10).
|
|||||||
|
|
||||||
## 4. Mode annotations
|
## 4. Mode annotations
|
||||||
|
|
||||||
Every function parameter carries a mode. The mode says how the
|
Every function parameter carries a mode, and so does the return
|
||||||
callee may treat the value: `implicit` is the legacy default
|
position. There are exactly two modes. `own` means the caller
|
||||||
(treated as `own`), `own` means the caller transfers ownership and
|
transfers ownership and the callee consumes the value; `borrow`
|
||||||
the callee consumes the value, `borrow` means the caller retains
|
means the caller retains ownership and the callee may inspect but
|
||||||
ownership and the callee may inspect but not consume.
|
not consume. `borrow` is legal only over a boxed type (an algebraic
|
||||||
|
data type): unboxed value types (`Int`, `Bool`, `Float`, `Unit`)
|
||||||
|
are always `own`, and borrowing one is a `borrow-over-value` error.
|
||||||
|
|
||||||
The mode also applies to the return value: `ret_mode` says whether
|
The return position is always `own` — a function returns a fresh
|
||||||
the function transfers ownership to the caller (`own`) or returns a
|
owned value; borrow-returns are not permitted.
|
||||||
borrow (`borrow`). For most functions the return mode is `own` or
|
|
||||||
implicit; `borrow` returns are rare and used only for accessor-style
|
|
||||||
functions.
|
|
||||||
|
|
||||||
Modes are mandatory on every parameter and on the return position.
|
Modes are mandatory: every parameter and the return position carries
|
||||||
The schema rejects unannotated fn signatures only when annotations
|
exactly one mode. There is no default or omitted mode.
|
||||||
are explicitly requested; for compatibility the legacy form (no
|
|
||||||
mode field at all) is treated as all-implicit.
|
|
||||||
|
|
||||||
On `Type::Fn`, two optional fields carry modes:
|
On `Type::Fn`, two required fields carry modes:
|
||||||
|
|
||||||
- `param_modes`: array of strings `"implicit"`, `"own"`, or
|
- `param_modes`: an array of strings, each `"own"` or `"borrow"`,
|
||||||
`"borrow"`, one per parameter, in the same order as `params`. The
|
one per parameter, in the same order as `params`.
|
||||||
array is omitted from the canonical bytes when every entry is
|
- `ret_mode`: a single string, always `"own"`.
|
||||||
`"implicit"`; this is purely a serialisation optimisation. Author
|
|
||||||
the field explicitly when at least one parameter is `own` or
|
|
||||||
`borrow`.
|
|
||||||
- `ret_mode`: a single string of the same vocabulary. Omitted when
|
|
||||||
it would be `"implicit"`.
|
|
||||||
|
|
||||||
Example: a fn that borrows two ints and returns an int:
|
Both are present on every fn type. Example — a fn that borrows a
|
||||||
`"param_modes": ["borrow", "borrow"]`, `ret_mode` omitted (implicit).
|
boxed list and returns an int: `"param_modes": ["borrow"]`,
|
||||||
A fn that consumes a list and returns a new list:
|
`"ret_mode": "own"`. A fn that consumes an int and returns an int:
|
||||||
`"param_modes": ["own"]`, `"ret_mode": "own"`.
|
`"param_modes": ["own"]`, `"ret_mode": "own"`.
|
||||||
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{"defs":[{"ctors":[{"fields":[],"name":"Nil"},{"fields":[{"k":"con","name":"Int"},{"k":"con","name":"List"}],"name":"Cons"}],"kind":"type","name":"List"},{"body":{"name":"x","t":"var"},"doc":"(own Int) — unboxed value types (Int/Bool/Float/Unit) are always own; borrow over them is a borrow-over-value error.","kind":"fn","name":"f_own_value","params":["x"],"type":{"effects":[],"k":"fn","param_modes":["own"],"params":[{"k":"con","name":"Int"}],"ret":{"k":"con","name":"Int"},"ret_mode":"own"}},{"body":{"arms":[{"body":{"lit":{"kind":"int","value":0},"t":"lit"},"pat":{"ctor":"Nil","fields":[],"p":"ctor"}},{"body":{"args":[{"lit":{"kind":"int","value":1},"t":"lit"},{"args":[{"name":"t","t":"var"}],"fn":{"name":"f_borrow_boxed","t":"var"},"t":"app"}],"fn":{"name":"+","t":"var"},"t":"app"},"pat":{"ctor":"Cons","fields":[{"name":"h","p":"var"},{"name":"t","p":"var"}],"p":"ctor"}}],"scrutinee":{"name":"xs","t":"var"},"t":"match"},"doc":"(borrow List) — boxed types may be borrowed; the callee reads without consuming.","kind":"fn","name":"f_borrow_boxed","params":["xs"],"type":{"effects":[],"k":"fn","param_modes":["borrow"],"params":[{"k":"con","name":"List"}],"ret":{"k":"con","name":"Int"},"ret_mode":"own"}}],"imports":[],"name":"param_modes_all","schema":"ailang/v0"}
|
||||||
"schema": "ailang/v0",
|
|
||||||
"name": "param_modes_all",
|
|
||||||
"imports": [],
|
|
||||||
"defs": [
|
|
||||||
{
|
|
||||||
"kind": "fn",
|
|
||||||
"name": "f_implicit",
|
|
||||||
"doc": "Implicit mode is the legacy default — `param_modes` is omitted from canonical JSON when every entry is Implicit, which is the case here. The visitor still observes ParamMode::Implicit via the (defaulted) ret_mode field on Type::Fn.",
|
|
||||||
"type": {
|
|
||||||
"k": "fn",
|
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
|
||||||
"ret": { "k": "con", "name": "Int" },
|
|
||||||
"effects": []
|
|
||||||
},
|
|
||||||
"params": ["x"],
|
|
||||||
"body": { "t": "var", "name": "x" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "fn",
|
|
||||||
"name": "f_own",
|
|
||||||
"doc": "(own T) — caller transfers ownership; callee consumes.",
|
|
||||||
"type": {
|
|
||||||
"k": "fn",
|
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
|
||||||
"param_modes": ["own"],
|
|
||||||
"ret": { "k": "con", "name": "Int" },
|
|
||||||
"effects": []
|
|
||||||
},
|
|
||||||
"params": ["x"],
|
|
||||||
"body": { "t": "var", "name": "x" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "fn",
|
|
||||||
"name": "f_borrow",
|
|
||||||
"doc": "(borrow T) — caller retains ownership; callee may not consume.",
|
|
||||||
"type": {
|
|
||||||
"k": "fn",
|
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
|
||||||
"param_modes": ["borrow"],
|
|
||||||
"ret": { "k": "con", "name": "Int" },
|
|
||||||
"effects": []
|
|
||||||
},
|
|
||||||
"params": ["x"],
|
|
||||||
"body": { "t": "var", "name": "x" }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 5. Functions
|
## 5. Functions
|
||||||
@@ -279,7 +228,9 @@ the difference.
|
|||||||
{ "k": "con", "name": "Int" },
|
{ "k": "con", "name": "Int" },
|
||||||
{ "k": "con", "name": "Int" }
|
{ "k": "con", "name": "Int" }
|
||||||
],
|
],
|
||||||
|
"param_modes": ["own", "own"],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["x", "y"],
|
"params": ["x", "y"],
|
||||||
@@ -314,20 +265,24 @@ the difference.
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
"params": [ { "k": "con", "name": "Int" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": {
|
"ret": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
"params": [ { "k": "con", "name": "Int" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["x"],
|
"params": ["x"],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "lam",
|
"t": "lam",
|
||||||
"params": ["y"],
|
"params": ["y"],
|
||||||
"paramTypes": [ { "k": "con", "name": "Int" } ],
|
"param-types": [ { "k": "con", "name": "Int" } ],
|
||||||
"retType": { "k": "con", "name": "Int" },
|
"ret-type": { "k": "con", "name": "Int" },
|
||||||
"effects": [],
|
"effects": [],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
@@ -378,51 +333,7 @@ carry `"args": []`.
|
|||||||
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{"defs":[{"ctors":[{"fields":[{"k":"var","name":"a"}],"name":"MkBox"}],"kind":"type","name":"Box","vars":["a"]},{"body":{"arms":[{"body":{"body":{"args":[{"lit":{"kind":"int","value":1},"t":"lit"}],"ctor":"MkBox","t":"ctor","type":"Box"},"source":{"name":"src","t":"var"},"t":"reuse-as"},"pat":{"ctor":"MkBox","fields":[{"name":"v","p":"var"}],"p":"ctor"}}],"scrutinee":{"name":"src","t":"var"},"t":"match"},"kind":"fn","name":"wrap_one","params":["src"],"type":{"effects":[],"k":"fn","param_modes":["own"],"params":[{"args":[{"k":"con","name":"Int"}],"k":"con","name":"Box"}],"ret":{"args":[{"k":"con","name":"Int"}],"k":"con","name":"Box"},"ret_mode":"own"}}],"imports":[],"name":"data_simple","schema":"ailang/v0"}
|
||||||
"schema": "ailang/v0",
|
|
||||||
"name": "data_simple",
|
|
||||||
"imports": [],
|
|
||||||
"defs": [
|
|
||||||
{
|
|
||||||
"kind": "type",
|
|
||||||
"name": "Box",
|
|
||||||
"vars": ["a"],
|
|
||||||
"doc": "A unary box around a polymorphic value.",
|
|
||||||
"ctors": [
|
|
||||||
{
|
|
||||||
"name": "MkBox",
|
|
||||||
"fields": [ { "k": "var", "name": "a" } ]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "fn",
|
|
||||||
"name": "wrap_one",
|
|
||||||
"doc": "Construct a Box Int via MkBox. The body uses (reuse-as src body) — a hint that the freshly-allocated Box should reuse the source's memory slot under --alloc=rc. Exercises TermCtor, ReuseAs, and Type::Var inside a ctor field position.",
|
|
||||||
"type": {
|
|
||||||
"k": "fn",
|
|
||||||
"params": [
|
|
||||||
{ "k": "con", "name": "Box", "args": [ { "k": "con", "name": "Int" } ] }
|
|
||||||
],
|
|
||||||
"param_modes": ["own"],
|
|
||||||
"ret": { "k": "con", "name": "Box", "args": [ { "k": "con", "name": "Int" } ] },
|
|
||||||
"ret_mode": "own",
|
|
||||||
"effects": []
|
|
||||||
},
|
|
||||||
"params": ["src"],
|
|
||||||
"body": {
|
|
||||||
"t": "reuse-as",
|
|
||||||
"source": { "t": "var", "name": "src" },
|
|
||||||
"body": {
|
|
||||||
"t": "ctor",
|
|
||||||
"type": "Box",
|
|
||||||
"ctor": "MkBox",
|
|
||||||
"args": [ { "t": "lit", "lit": { "kind": "int", "value": 1 } } ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 7. Pattern matching
|
## 7. Pattern matching
|
||||||
@@ -470,14 +381,23 @@ single pattern. Repeating a name is a typecheck error.
|
|||||||
{
|
{
|
||||||
"kind": "type",
|
"kind": "type",
|
||||||
"name": "List",
|
"name": "List",
|
||||||
"doc": "Monomorphic singly-linked Int list — boxed, recursive.",
|
"doc": "Monomorphic singly-linked Int list \u2014 boxed, recursive.",
|
||||||
"ctors": [
|
"ctors": [
|
||||||
{ "name": "Nil", "fields": [] },
|
{
|
||||||
|
"name": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Cons",
|
"name": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "k": "con", "name": "Int" },
|
{
|
||||||
{ "k": "con", "name": "List" }
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"k": "con",
|
||||||
|
"name": "List"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -488,30 +408,64 @@ single pattern. Repeating a name is a typecheck error.
|
|||||||
"doc": "Return the head of xs, or 0 if empty. Exercises TermMatch with two arms, PatternCtor (both nullary Nil and binary Cons), and PatternWild on the tail field.",
|
"doc": "Return the head of xs, or 0 if empty. Exercises TermMatch with two arms, PatternCtor (both nullary Nil and binary Cons), and PatternWild on the tail field.",
|
||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "List" } ],
|
"params": [
|
||||||
"param_modes": ["borrow"],
|
{
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"k": "con",
|
||||||
|
"name": "List"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"param_modes": [
|
||||||
|
"borrow"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["xs"],
|
"params": [
|
||||||
|
"xs"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "match",
|
"t": "match",
|
||||||
"scrutinee": { "t": "var", "name": "xs" },
|
"scrutinee": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "xs"
|
||||||
|
},
|
||||||
"arms": [
|
"arms": [
|
||||||
{
|
{
|
||||||
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
|
"pat": {
|
||||||
"body": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
"p": "ctor",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pat": {
|
"pat": {
|
||||||
"p": "ctor",
|
"p": "ctor",
|
||||||
"ctor": "Cons",
|
"ctor": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "p": "var", "name": "h" },
|
{
|
||||||
{ "p": "wild" }
|
"p": "var",
|
||||||
|
"name": "h"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "wild"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"body": { "t": "var", "name": "h" }
|
"body": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "h"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -522,49 +476,110 @@ single pattern. Repeating a name is a typecheck error.
|
|||||||
"doc": "Walk xs counting nodes using a local recursive let. Exercises TermLetRec and TermVar; the recursive `go` is bound locally.",
|
"doc": "Walk xs counting nodes using a local recursive let. Exercises TermLetRec and TermVar; the recursive `go` is bound locally.",
|
||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "List" } ],
|
"params": [
|
||||||
"param_modes": ["borrow"],
|
{
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"k": "con",
|
||||||
|
"name": "List"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"param_modes": [
|
||||||
|
"own"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["xs"],
|
"params": [
|
||||||
|
"xs"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "letrec",
|
"t": "letrec",
|
||||||
"name": "go",
|
"name": "go",
|
||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "List" } ],
|
"params": [
|
||||||
"param_modes": ["borrow"],
|
{
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"k": "con",
|
||||||
|
"name": "List"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"param_modes": [
|
||||||
|
"own"
|
||||||
|
],
|
||||||
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Int"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["ys"],
|
"params": [
|
||||||
|
"ys"
|
||||||
|
],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "match",
|
"t": "match",
|
||||||
"scrutinee": { "t": "var", "name": "ys" },
|
"scrutinee": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "ys"
|
||||||
|
},
|
||||||
"arms": [
|
"arms": [
|
||||||
{
|
{
|
||||||
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
|
"pat": {
|
||||||
"body": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
"p": "ctor",
|
||||||
|
"ctor": "Nil",
|
||||||
|
"fields": []
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pat": {
|
"pat": {
|
||||||
"p": "ctor",
|
"p": "ctor",
|
||||||
"ctor": "Cons",
|
"ctor": "Cons",
|
||||||
"fields": [
|
"fields": [
|
||||||
{ "p": "wild" },
|
{
|
||||||
{ "p": "var", "name": "t" }
|
"p": "wild"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"p": "var",
|
||||||
|
"name": "t"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"body": {
|
"body": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "+" },
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "+"
|
||||||
|
},
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 1 } },
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "go" },
|
"fn": {
|
||||||
"args": [ { "t": "var", "name": "t" } ]
|
"t": "var",
|
||||||
|
"name": "go"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "t"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -573,8 +588,16 @@ single pattern. Repeating a name is a typecheck error.
|
|||||||
},
|
},
|
||||||
"in": {
|
"in": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "go" },
|
"fn": {
|
||||||
"args": [ { "t": "var", "name": "xs" } ]
|
"t": "var",
|
||||||
|
"name": "go"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "var",
|
||||||
|
"name": "xs"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,7 +618,9 @@ single pattern. Repeating a name is a typecheck error.
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
"params": [ { "k": "con", "name": "Int" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["n"],
|
"params": ["n"],
|
||||||
@@ -621,7 +646,9 @@ single pattern. Repeating a name is a typecheck error.
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "con", "name": "Int" } ],
|
"params": [ { "k": "con", "name": "Int" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Int" },
|
"ret": { "k": "con", "name": "Int" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": ["n"],
|
"params": ["n"],
|
||||||
@@ -629,7 +656,7 @@ single pattern. Repeating a name is a typecheck error.
|
|||||||
"t": "if",
|
"t": "if",
|
||||||
"cond": {
|
"cond": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "<" },
|
"fn": { "t": "var", "name": "lt" },
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "var", "name": "n" },
|
{ "t": "var", "name": "n" },
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
||||||
@@ -640,7 +667,7 @@ single pattern. Repeating a name is a typecheck error.
|
|||||||
"t": "if",
|
"t": "if",
|
||||||
"cond": {
|
"cond": {
|
||||||
"t": "app",
|
"t": "app",
|
||||||
"fn": { "t": "var", "name": "==" },
|
"fn": { "t": "var", "name": "eq" },
|
||||||
"args": [
|
"args": [
|
||||||
{ "t": "var", "name": "n" },
|
{ "t": "var", "name": "n" },
|
||||||
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
{ "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
||||||
@@ -704,21 +731,94 @@ discarded but its effects count toward the enclosing fn's row.
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
"ret": { "k": "con", "name": "Unit" },
|
"param_modes": [],
|
||||||
"effects": ["IO"]
|
"ret": {
|
||||||
|
"k": "con",
|
||||||
|
"name": "Unit"
|
||||||
|
},
|
||||||
|
"ret_mode": "own",
|
||||||
|
"effects": [
|
||||||
|
"IO"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
"body": {
|
"body": {
|
||||||
"t": "seq",
|
"t": "seq",
|
||||||
"lhs": {
|
"lhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [ { "t": "lit", "lit": { "kind": "int", "value": 1 } } ]
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"rhs": {
|
"rhs": {
|
||||||
"t": "do",
|
"t": "seq",
|
||||||
"op": "io/print_int",
|
"lhs": {
|
||||||
"args": [ { "t": "lit", "lit": { "kind": "int", "value": 2 } } ]
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "app",
|
||||||
|
"fn": {
|
||||||
|
"t": "var",
|
||||||
|
"name": "int_to_str"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "int",
|
||||||
|
"value": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rhs": {
|
||||||
|
"t": "do",
|
||||||
|
"op": "io/print_str",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"t": "lit",
|
||||||
|
"lit": {
|
||||||
|
"kind": "str",
|
||||||
|
"value": "\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -795,7 +895,9 @@ not by the author. When you write `3.14` in AIL, the parser emits
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
|
"param_modes": [],
|
||||||
"ret": { "k": "con", "name": "Bool" },
|
"ret": { "k": "con", "name": "Bool" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -808,7 +910,9 @@ not by the author. When you write `3.14` in AIL, the parser emits
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
|
"param_modes": [],
|
||||||
"ret": { "k": "con", "name": "Str" },
|
"ret": { "k": "con", "name": "Str" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -821,7 +925,9 @@ not by the author. When you write `3.14` in AIL, the parser emits
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [],
|
"params": [],
|
||||||
|
"param_modes": [],
|
||||||
"ret": { "k": "con", "name": "Unit" },
|
"ret": { "k": "con", "name": "Unit" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
"params": [],
|
"params": [],
|
||||||
@@ -889,7 +995,9 @@ constraints; omitted from canonical bytes when empty.
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "var", "name": "a" } ],
|
"params": [ { "k": "var", "name": "a" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Str" },
|
"ret": { "k": "con", "name": "Str" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -916,7 +1024,9 @@ constraints; omitted from canonical bytes when empty.
|
|||||||
"type": {
|
"type": {
|
||||||
"k": "fn",
|
"k": "fn",
|
||||||
"params": [ { "k": "var", "name": "a" } ],
|
"params": [ { "k": "var", "name": "a" } ],
|
||||||
|
"param_modes": ["own"],
|
||||||
"ret": { "k": "con", "name": "Str" },
|
"ret": { "k": "con", "name": "Str" },
|
||||||
|
"ret_mode": "own",
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user