Iter 11: deeper dogfood — insertion sort

examples/sort.ail.json: insertion sort over IntList. Defines `insert
:: Int -> IntList -> IntList` and `sort :: IntList -> IntList`
recursively, plus print_list using Iter 10's seq. Sorts an 11-element
input and prints `1 1 2 3 3 4 5 5 5 6 9` one-per-line.

Validates that the language handles deeper ADT recursion + branching
(if + <=) + ctor construction + IO sequencing without surprises.
Wrote, typechecked, ran first try.

The Iter 11 plan called for polymorphism, but on reflection the right
move was one more validation cycle before disturbing the pipeline.
Polymorphism is now queued explicitly as Iter 12 (12a typechecker
substitution, 12b codegen monomorphisation, 12c docs + generic
example).

Tests: 52 green (was 51). New e2e `insertion_sort_orders_list`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 13:17:07 +02:00
parent c75517ac79
commit 1d24907f84
4 changed files with 427 additions and 0 deletions
+328
View File
@@ -0,0 +1,328 @@
{
"schema": "ailang/v0",
"name": "sort",
"imports": [],
"defs": [
{
"kind": "type",
"name": "IntList",
"doc": "Singly-linked Int list, boxed.",
"ctors": [
{ "name": "Nil", "fields": [] },
{
"name": "Cons",
"fields": [
{ "k": "con", "name": "Int" },
{ "k": "con", "name": "IntList" }
]
}
]
},
{
"kind": "fn",
"name": "insert",
"type": {
"k": "fn",
"params": [
{ "k": "con", "name": "Int" },
{ "k": "con", "name": "IntList" }
],
"ret": { "k": "con", "name": "IntList" },
"effects": []
},
"params": ["y", "xs"],
"doc": "Insert y into a sorted list xs, preserving order.",
"body": {
"t": "match",
"scrutinee": { "t": "var", "name": "xs" },
"arms": [
{
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
"body": {
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "var", "name": "y" },
{
"t": "ctor",
"type": "IntList",
"ctor": "Nil",
"args": []
}
]
}
},
{
"pat": {
"p": "ctor",
"ctor": "Cons",
"fields": [
{ "p": "var", "name": "h" },
{ "p": "var", "name": "t" }
]
},
"body": {
"t": "if",
"cond": {
"t": "app",
"fn": { "t": "var", "name": "<=" },
"args": [
{ "t": "var", "name": "y" },
{ "t": "var", "name": "h" }
]
},
"then": {
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "var", "name": "y" },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "var", "name": "h" },
{ "t": "var", "name": "t" }
]
}
]
},
"else": {
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "var", "name": "h" },
{
"t": "app",
"fn": { "t": "var", "name": "insert" },
"args": [
{ "t": "var", "name": "y" },
{ "t": "var", "name": "t" }
]
}
]
}
}
}
]
}
},
{
"kind": "fn",
"name": "sort",
"type": {
"k": "fn",
"params": [{ "k": "con", "name": "IntList" }],
"ret": { "k": "con", "name": "IntList" },
"effects": []
},
"params": ["xs"],
"doc": "Insertion sort: build the result by inserting each head into the sorted tail.",
"body": {
"t": "match",
"scrutinee": { "t": "var", "name": "xs" },
"arms": [
{
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
"body": {
"t": "ctor",
"type": "IntList",
"ctor": "Nil",
"args": []
}
},
{
"pat": {
"p": "ctor",
"ctor": "Cons",
"fields": [
{ "p": "var", "name": "h" },
{ "p": "var", "name": "t" }
]
},
"body": {
"t": "app",
"fn": { "t": "var", "name": "insert" },
"args": [
{ "t": "var", "name": "h" },
{
"t": "app",
"fn": { "t": "var", "name": "sort" },
"args": [{ "t": "var", "name": "t" }]
}
]
}
}
]
}
},
{
"kind": "fn",
"name": "print_list",
"type": {
"k": "fn",
"params": [{ "k": "con", "name": "IntList" }],
"ret": { "k": "con", "name": "Unit" },
"effects": ["IO"]
},
"params": ["xs"],
"body": {
"t": "match",
"scrutinee": { "t": "var", "name": "xs" },
"arms": [
{
"pat": { "p": "ctor", "ctor": "Nil", "fields": [] },
"body": { "t": "lit", "lit": { "kind": "unit" } }
},
{
"pat": {
"p": "ctor",
"ctor": "Cons",
"fields": [
{ "p": "var", "name": "h" },
{ "p": "var", "name": "t" }
]
},
"body": {
"t": "seq",
"lhs": {
"t": "do",
"op": "io/print_int",
"args": [{ "t": "var", "name": "h" }]
},
"rhs": {
"t": "app",
"fn": { "t": "var", "name": "print_list" },
"args": [{ "t": "var", "name": "t" }]
}
}
}
]
}
},
{
"kind": "fn",
"name": "main",
"type": {
"k": "fn",
"params": [],
"ret": { "k": "con", "name": "Unit" },
"effects": ["IO"]
},
"params": [],
"doc": "Sort and print [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].",
"body": {
"t": "let",
"name": "xs",
"value": {
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 3 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 1 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 4 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 1 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 5 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 9 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 2 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 6 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 5 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 3 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Cons",
"args": [
{ "t": "lit", "lit": { "kind": "int", "value": 5 } },
{
"t": "ctor",
"type": "IntList",
"ctor": "Nil",
"args": []
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
},
"body": {
"t": "app",
"fn": { "t": "var", "name": "print_list" },
"args": [
{
"t": "app",
"fn": { "t": "var", "name": "sort" },
"args": [{ "t": "var", "name": "xs" }]
}
]
}
}
}
]
}