b9ca8894a5
Adds form-A surface (borrow T) / (own T) wrappers in fn-type
params and ret slots. Internally these are not new Type variants
but per-position metadata on Type::Fn:
Type::Fn { params, param_modes, ret, ret_mode, effects }
enum ParamMode { Implicit, Own, Borrow }
This keeps Type itself unchanged, so unification, occurs, apply,
and ~190 other Type match-arms in the typechecker need no new
branch. Fields use serde skip-if-default predicates so canonical
JSON hashes for every pre-18a fixture stay bit-identical (sum,
list, hof, closure, list_map, etc.: zero diff under git).
Iter 18a is purely additive: typechecker treats modes as
transparent (mode-compat check deferred to 18c), no codegen
change (--alloc=gc / Boehm path unchanged), no linearity
enforcement. The annotation info flows into the JSON side-table
that 18c will consume.
Equality of mode slices is length-tolerant: a vec![] (the form
written by mechanically-updated construction sites that elide
modes) compares equal to vec![Implicit; n]. This kept the patch
from being a 100-site mechanical migration through the
typechecker. 18c will choose: keep the slack, or normalise to
full-length on construction.
New fixture examples/borrow_own_demo.{ailx,ail.json} exercises
both modes. list_length declares (borrow (con List)); sum_list
declares (own (con List)). Stdout: 3 then 6.
Documentation: DESIGN.md schema-additions block clarified that
modes are Type::Fn metadata (not Type variants); migration plan
flag rename --memory=rc → --alloc=rc to match the existing CLI
flag.
Verification:
- cargo build --workspace green
- cargo test --workspace green (154 tests, +1 vs baseline 153)
- git diff examples/{sum,list,hof,closure,list_map,...}.ail.json: empty
- borrow_own_demo runtime stdout: "3\n6\n"
- canonical JSON contains "param_modes":["borrow"] and ["own"]
65 lines
1.9 KiB
Plaintext
65 lines
1.9 KiB
Plaintext
; Iter 18a — `(borrow T)` and `(own T)` mode annotations on
|
|
; fn-type params and ret slots.
|
|
;
|
|
; This fixture exercises the schema/parser/printer/typechecker path
|
|
; that Iter 18a adds. It does *not* exercise enforcement: under the
|
|
; semantics shipping with 18a, every mode is treated as
|
|
; `Implicit ≡ Own` and `(borrow ...)` / `(own ...)` are accepted but
|
|
; have no codegen consequence. Linearity / borrow checking comes in
|
|
; Iter 18c.
|
|
;
|
|
; What round-trips through the form-A printer:
|
|
; (borrow (con List)) — list_length's xs parameter
|
|
; (own (con List)) — sum_list's xs parameter
|
|
;
|
|
; Expected stdout (one int per line, via io/print_int + a newline):
|
|
; 3
|
|
; 6
|
|
|
|
(module borrow_own_demo
|
|
|
|
(data List
|
|
(doc "Monomorphic singly-linked Int list — boxed, recursive.")
|
|
(ctor Nil)
|
|
(ctor Cons (con Int) (con List)))
|
|
|
|
(fn list_length
|
|
(doc "Borrow xs, count its elements. Iter 18a: `(borrow (con List))`.")
|
|
(type
|
|
(fn-type
|
|
(params (borrow (con List)))
|
|
(ret (con Int))))
|
|
(params xs)
|
|
(body
|
|
(match xs
|
|
(case (pat-ctor Nil) 0)
|
|
(case (pat-ctor Cons h t)
|
|
(app + 1 (app list_length t))))))
|
|
|
|
(fn sum_list
|
|
(doc "Consume xs, sum its elements. Iter 18a: `(own (con List))`.")
|
|
(type
|
|
(fn-type
|
|
(params (own (con List)))
|
|
(ret (con Int))))
|
|
(params xs)
|
|
(body
|
|
(match xs
|
|
(case (pat-ctor Nil) 0)
|
|
(case (pat-ctor Cons h t)
|
|
(app + h (app sum_list t))))))
|
|
|
|
(fn main
|
|
(doc "Build [1,2,3]; print list_length (3) then sum_list (6).")
|
|
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
|
(params)
|
|
(body
|
|
(let xs
|
|
(term-ctor List Cons 1
|
|
(term-ctor List Cons 2
|
|
(term-ctor List Cons 3
|
|
(term-ctor List Nil))))
|
|
(seq
|
|
(do io/print_int (app list_length xs))
|
|
(do io/print_int (app sum_list xs)))))))
|