Second stage of the milestone-2 frontend. calc-me.flan (12 decls) and sand.flan (20 decls) both parse end to end, and both are test deps so a regression fails `dune test` rather than surfacing at the CLI. Three silent-misparse bugs fixed along the way -- all cases that read cleanly and meant something else: - dotimes/defer/some/try/fn fell through to Call, discarding their binding and control-flow meaning. Now special forms. Forms from later milestones (handler-bind, restart-case, loop/recur, defmacro, signal, with-allocator, errdefer, await) are rejected outright rather than parsed as calls. - (Some 1) in first body position was read as a return type, because (Option f64) and (Some 1) are identical s-expressions and the heuristic was capitalisation. Now decided by the set of names actually declared as types, collected in a pre-pass -- exact, and order-independent so a type declared below its user still resolves. - Array literals in value position were rejected outright. Also adds NEXT.md with the handoff for the checker.
104 lines
4.3 KiB
OCaml
104 lines
4.3 KiB
OCaml
(** The AST: syntax with special forms recognised, before typing.
|
|
|
|
Sugar is gone by this point. [when], [unless], [cond] and [and]/[or] are
|
|
desugared into [If] and [Do]; they are compiler special forms until macros
|
|
arrive at milestone 5, so there is nothing to preserve for a macroexpander
|
|
to see yet.
|
|
|
|
Types here are *surface* type expressions, not resolved types. [Ptr] and
|
|
[Option] are still just names; the checker resolves them. *)
|
|
|
|
(* ── Type expressions ──────────────────────────────────────────────── *)
|
|
|
|
type texpr = { t : texpr_kind; tloc : Loc.t }
|
|
|
|
and texpr_kind =
|
|
| Tname of string (* i32 bool Cursor string *)
|
|
| Tslice of texpr (* [u8] ptr+len *)
|
|
| Tarray of len * texpr (* [4 f32] [rows [cols u32]] *)
|
|
| Tmap of texpr * texpr (* {string i32} *)
|
|
| Tapp of string * texpr list (* (Ptr Cursor) (Option f64) *)
|
|
| Tfn of texpr list * texpr (* (Fn [a a] bool) *)
|
|
|
|
(* An array length is an integer or a compile-time constant's name. *)
|
|
and len =
|
|
| Lint of int64
|
|
| Lname of string
|
|
|
|
(* ── Expressions ───────────────────────────────────────────────────── *)
|
|
|
|
type expr = { e : expr_kind; loc : Loc.t }
|
|
|
|
and expr_kind =
|
|
| Int of int64
|
|
| Float of float
|
|
| Byte of int
|
|
| Str of string
|
|
| Kw of string (* :space — coerced at typed call sites *)
|
|
| Quote of string (* 'skip-form — restart names *)
|
|
| Var of string
|
|
| Do of expr list
|
|
| Let of binding list * expr list
|
|
| If of expr * expr * expr option
|
|
| While of expr * expr list
|
|
| Return of expr option
|
|
| Set of place * expr
|
|
| Field of expr * string (* (.pos c) — auto-derefs one level *)
|
|
| Call of expr * expr list
|
|
| Match of expr * arm list
|
|
| Struct of string * (string * expr) list (* (Cursor {:src s}) *)
|
|
| Arr of expr list (* [0xE6B800FF ...] — a fixed array value *)
|
|
(* These bind names or alter control flow, so none of them can be a call. *)
|
|
| Fn of string list * expr list (* (fn [x y] ...) — non-escaping *)
|
|
| Dotimes of string * expr * expr list (* (dotimes [i n] ...) *)
|
|
| Defer of expr list (* runs on scope exit *)
|
|
| Unwrap of unwrap * expr (* (some x) / (try x) *)
|
|
|
|
(* Two unwrap operators, because they are two different things — plan.org. *)
|
|
and unwrap = Usome | Utry
|
|
|
|
and binding = { bname : string; bty : texpr option; bval : expr; bloc : Loc.t }
|
|
|
|
(* The fixed list of assignable forms — spec-memory.md. Not setf. *)
|
|
and place =
|
|
| Pvar of string
|
|
| Pfield of expr * string (* (set (.hp e) v) *)
|
|
| Pindex of expr * expr list (* (set (at grid r c) v) *)
|
|
| Pkey of expr * expr (* (set (get m k) v) *)
|
|
| Pderef of expr (* (set (deref p) v) *)
|
|
|
|
and arm = { pat : pattern; body : expr list; aloc : Loc.t }
|
|
|
|
and pattern =
|
|
| Pctor of string * string list (* (Some e) (Rect w h) None *)
|
|
| Pwild (* _ :else *)
|
|
|
|
(* ── Declarations ──────────────────────────────────────────────────── *)
|
|
|
|
type field = { fname : string; fty : texpr; floc : Loc.t }
|
|
|
|
type fn = {
|
|
name : string;
|
|
params : field list;
|
|
ret : texpr option; (* None means Unit *)
|
|
fbody : expr list;
|
|
nloc : Loc.t;
|
|
}
|
|
|
|
type decl = { d : decl_kind; dloc : Loc.t }
|
|
|
|
and decl_kind =
|
|
| Package of string
|
|
| Import of string * string (* alias, path *)
|
|
| Defalias of string * texpr
|
|
| Defstruct of string * field list
|
|
| Defunion of string * variant list
|
|
| Defn of fn
|
|
(* value is optional: ZII. `uninit` opts out and is recorded as Uninit. *)
|
|
| Defvar of string * texpr option * init
|
|
| Defconst of string * texpr option * expr
|
|
|
|
and variant = { vname : string; vfields : field list; vloc : Loc.t }
|
|
|
|
and init = Zeroed | Uninit | Init of expr
|