The prelude is lib/prelude.fln, embedded at build time and read by the indented reader.

This commit is contained in:
Joseph Ferano 2026-09-26 16:37:02 +07:00
parent ac752d1405
commit 66fce31dbd
9 changed files with 2576 additions and 2492 deletions

View File

@ -25,6 +25,7 @@ prelude and vendor rewritten in .fln; tests and examples converted with =flan co
then =flan convert=, the .flan source path and =flan-mode= removed. Nothing tracks what
.flan can no longer say. Step 1 is done: the name rule with the =is-=/=has-= renames
through the prelude, vendor and raylib, and =T?=, =??=, =x!=, =if let g = x= and =a?.b=.
Step 2's prelude is done: =lib/prelude.fln=, read by the indented reader.
** DONE x? tests presence, and narrows
CLOSED: [2026-09-26]
Decided (133): =x?= is a bool; =if x?=, =elif x?=, =while x?= and the rest of an =and=

View File

@ -7527,7 +7527,7 @@ prints freed memory.
## String is a prelude struct, and the checker is its wall
`String` is `(defstruct String [bytes (Vec u8)])` in `lib/prelude.ml`, so its
`String` is `struct String(bytes: Vec(u8))` in `lib/prelude.fln`, so its
allocator, free, retry on exhaustion and dev-registry notes are the Vec's and
neither backend has a String of its own. What makes it always valid UTF-8 is
`lib/check.ml`'s String section: outside the prelude the field and the

View File

@ -166,7 +166,7 @@ often `pause' itself, and `P' shows them.")
(defconst flan-cnr-breakpoint "Pause"
"The condition `(pause)' signals.
`lib/prelude.ml' writes it as an ordinary struct under a `restart-case', so
`lib/prelude.fln' writes it as an ordinary struct under a `restart-case', so
nothing in the compiler knows a breakpoint from an error and this buffer is the
first place that can tell the difference. Named here rather than spelled at
its use, because it is a fact about the prelude.")

View File

@ -1528,7 +1528,7 @@ definition, and RET on a frame or on the stop in the break buffer."
(user-error "flan: the daemon gave %s an unreadable location: %s"
subject loc))
((string-match-p "\\`<.*>\\'" (nth 0 parts))
;; The prelude is a string inside the compiler (lib/prelude.ml) and
;; The prelude is a string inside the compiler (lib/prelude.fln) and
;; names itself <prelude>; anything in angle brackets is a placeholder
;; the frontend made up, not a path.
(user-error "flan: %s is defined in %s, which is not a file on disk"

View File

@ -179,7 +179,7 @@ let add (t : t) ~qualify forms =
adds nothing. *)
let table ?file (forms : Form.t list) : t =
let t = create () in
let prelude = try Reader.read_all ~file:Prelude.file Prelude.source with _ -> [] in
let prelude = try Prelude.read () with _ -> [] in
add t ~qualify:Fun.id prelude;
(match file with
| None -> ()

View File

@ -64,3 +64,17 @@
(echo "|c}\n\nlet agent_source = {c|\n")
(cat %{workspace_root}/vendor/agent/flan_agent.c)
(echo "|c}\n")))))
; The prelude, carried the same way: lib/prelude.fln is the source, read by
; the indented reader at every build (lib/prelude.ml). No newline after the
; opening quote, so a location's line is the file's line.
(rule
(target prelude_src.ml)
(deps prelude.fln)
(action
(with-stdout-to
prelude_src.ml
(progn
(echo "let source = {fln|")
(cat prelude.fln)
(echo "|fln}\n")))))

2539
lib/prelude.fln Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,8 @@
([Reader]). Both give the same [Form.t], so nothing past this point knows
which one a file was written in, and a program may mix them freely.
Only program sources come through here. The prelude, the wire protocol and
Only program sources come through here. The prelude is indented text
embedded in the compiler and read by [Prelude.read]; the wire protocol and
the registry's spellings are paren text the compiler writes itself, and
read it with [Reader] directly. *)