A prelude type is a name, not a list head
The last commit put the prelude's types into the set the parser uses to tell a
return type from the first form of a body, and put them in plainly. That set is
read by two arms: a bare symbol, and a list head. The list-head arm is why
(defn f [] (Some 1) (bar)) does not lose its body, and the comment above it has
warned about this since it was written -- so adding Rune plainly made
(defn f [] (Rune {.code 65}) (bar)) a function returning a Rune with a
one-form body, silently, in every file in the language. Confirmed before
fixing: it failed with "a map type is {K V}", which is the misparse arriving a
step later wearing someone else's error.
The enums already solve this one comment up, under their own key, for the same
reason. The prelude's types go in the same way. No prelude type takes
arguments, so a bare symbol is the only type position any of them can occupy.
Both halves are pinned in test_flan.ml's return-type section: Form is a return
type, and a prelude struct literal opening a body is not.
This commit is contained in:
parent
f585df494c
commit
a34b63af5d
24
lib/parse.ml
24
lib/parse.ml
@ -821,7 +821,8 @@ and qualified_type types s =
|
||||
and is_type_form types (f : Form.t) =
|
||||
match f.v with
|
||||
| Sym s ->
|
||||
Names.mem s types || Names.mem ("enum " ^ s) types || qualified_type types s
|
||||
Names.mem s types || Names.mem ("enum " ^ s) types
|
||||
|| Names.mem ("prelude " ^ s) types || qualified_type types s
|
||||
| Vec _ -> true (* [T] and [n T] are only types *)
|
||||
| Map _ -> true (* {K V} in this position *)
|
||||
| List ({ v = Sym n; _ } :: _) ->
|
||||
@ -875,9 +876,28 @@ let types_in (base : Names.t) (forms : Form.t list) : Names.t =
|
||||
because a Vec in that position is a type whatever is in it, which is exactly
|
||||
the kind of half-working that hides this.
|
||||
|
||||
They go in under their own key, for the reason the enums do one comment up.
|
||||
Added plainly, [is_type_form]'s list-head arm would read [(Rune {.code 65})]
|
||||
as a type application and eat it as a return type — silently, in every file
|
||||
in the language, which is the exact failure the comment above
|
||||
[is_type_form] warns about. No prelude type takes arguments, so a bare
|
||||
symbol is the only type position any of them can occupy, and the bare-symbol
|
||||
arm is the only one that asks.
|
||||
|
||||
Read once: the prelude is a constant string and this set is a constant of
|
||||
it. *)
|
||||
let prelude_types = lazy (types_in builtin_types (Prelude.forms ()))
|
||||
let prelude_types =
|
||||
lazy
|
||||
(List.fold_left
|
||||
(fun acc (f : Form.t) ->
|
||||
match f.v with
|
||||
| Form.List [ { v = Form.Sym ("defstruct" | "defunion" | "defalias"); _ };
|
||||
{ v = Form.Sym n; _ }; _ ] ->
|
||||
Names.add ("prelude " ^ n) acc
|
||||
| Form.List [ { v = Form.Sym "defenum"; _ }; { v = Form.Sym n; _ }; _ ] ->
|
||||
Names.add ("enum " ^ n) acc
|
||||
| _ -> acc)
|
||||
builtin_types (Prelude.forms ()))
|
||||
|
||||
let declared_types (forms : Form.t list) : Names.t =
|
||||
types_in (Lazy.force prelude_types) forms
|
||||
|
||||
@ -484,6 +484,21 @@ let () =
|
||||
check "unknown capitalised head is a body form"
|
||||
(ret_and_body "unknown" "(defn f [] (Nope 1) (bar))" = (false, 2));
|
||||
|
||||
(* The prelude's types are every file's types -- Check.program prepends the
|
||||
prelude to every program -- and until macros needed it, nothing told the
|
||||
parser so. A macro is (defn m [args [Form]] Form ...) and bare Form in
|
||||
return position was read as the first form of the body. *)
|
||||
check "a prelude type is a return type"
|
||||
(ret_and_body "prelude" "(defn f [] Form (g))" = (true, 1));
|
||||
|
||||
(* And the other half, which is the whole reason those names go in under
|
||||
their own key: a prelude type is a bare symbol in type position and never
|
||||
a list head, so a struct literal of one opening a body stays a body form.
|
||||
Added plainly this reads as a type application and eats the body, in every
|
||||
file in the language, and nothing would have said so. *)
|
||||
check "a prelude struct literal is NOT a return type"
|
||||
(ret_and_body "preludelit" "(defn f [] (Rune {.code 65}) (bar))" = (false, 2));
|
||||
|
||||
()
|
||||
|
||||
(* ── Checker: AST → typed IR ───────────────────────────────────────── *)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user