diff options
| author | 2026-10-14 10:05:40 +0000 | |
|---|---|---|
| committer | 2026-10-14 10:05:40 +0000 | |
| commit | ce920b6ff47f32bc06dd27124e1b882f82f3d6ae (patch) | |
| tree | 89f3dac0aa670294053320599a742d670c0ec5a4 /src/compiler/check.zc | |
| parent | todo: tick the parity runner; zc0 follow-ups it found (diff) | |
split compiler.zc into files by phase
src/compiler/compiler.zc is now twelve files under src/compiler/, listed in
order in src/compiler/parts. cat of the parts in order is byte-identical to
the old file, so every compiler and image except the language server's is
unchanged. no function was edited.
consumers read the list: the makefile, bootstrap-check, genmap (which still
writes one compiler.zc into a generated map directory), tinyvm.bat,
test.sh, test_win.ps1 and the lsp drivers. the language server embeds each
part and serves them joined as the one document tinyvm:/compiler.zc.
Diffstat (limited to 'src/compiler/check.zc')
| -rw-r--r-- | src/compiler/check.zc | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/compiler/check.zc b/src/compiler/check.zc new file mode 100644 index 0000000..a22bcdd --- /dev/null +++ b/src/compiler/check.zc @@ -0,0 +1,115 @@ +// ---- check mode: the language server ---- + +// the server runs this compiler, unchanged, over a document it holds in +// memory. chk_unit compiles it as a whole unit, in a machine set up the way +// start() sets one up (the genome's own names, the default operators and +// keywords), so the document's parse words, operators and types change what +// the rest of it means exactly as they would in a real build. the symbols +// the document made stay in the tables afterwards for the highlighter. +// chk_mark is the last function of the compiler proper, and LSP_SERVER (in +// src/lsp/server.zc) the first constant of the server: the server's names are +// hidden from the document, the runtime's and the compiler's are not. +int chk_mark() { return 0; } +// reset check mode for a new document. +int chk_reset() { + statement_hooks = 0; included_modules = 0; + if_local = 0; if_edges = 0; if_value = 0; + rt.code_blocks = 0; code_chunk = rt.CODE_END; + isp = -1; + docs_on = 1; dn = 0; dline = 0; docpending = 0; dsect = 0; dsn = 0; dnm = 0; + pq_n = 0; + pendot = 0; + qdone = 0; + ch = 0; + chkind = 0; + line = 1; + tk = 0; + tv = 0; + tglue = 0; + tline = 1; + toff = 0 - 1; toklen = 0; tpend = 0 - 1; tpline = 1; + infn = 0; + fdepth = 0; + fslots = 0; + fchk = 0; + fret = 0; + live = 0; + bxdepth = 0; + epichain = 0; + fframe = 0; + xbor = 0 - 1; xaf = 0; argfact = 0; xvk = 0; + if (svkind) rt.fill_w(svkind, 0, symcap); + mdbg = 0; mdbg_flags = 0; lv = 0; lvk = 0; lvi = 0; kw_expr = 0; xcls = 0; fty = 0; + check_on = 1; tc_on = ifstrict; dry = 0; ntp = 0; tvauto = 0; ngbind = 0; xgive = 0; xconst = 0; + o3on = 0; o3nxt = 0; no3pend = 0; no3sl = 0; no3free = 0; o3nreg = 0; o3na = 0; o3fn0 = 0; + nfact = 0; fortest = 0; forstep = 0; argloc = 0; arrloc = 0; njps = 0; extop = 0; nnumops = 0; + nenh = 0; panic = 0; nerr = 0; dgprev = 0; nclo = 0; newsz = 0 - 1; nomagic = 0; callpos = 0; + grec = 0; gnew = 0 - 1; gt_n = 0; gi_n = 0; ginst = 0; gtab = 0; + return 0; +} +// src: the document, 4 chars to a word and a 0 at the end. buf, cap: where +// the records go. sets: 4 * LSW words for the name sets. lim: code may grow up +// to here. every block the caller holds is a heap object reachable from its +// globals, so the check's garbage is collected and nothing is cut off. +// check one document in check mode and fill the records it made. +int chk_unit(int src, int buf, int cap, int sets, int lim) { + chk_reset(); + module_name = 0; module_imports = 0; + chk_begin(buf, cap); + lsets = sets; + if (sets) rt.fill_w(sets, 0, 4 * LSW); + if (!chk_heap) { rt.heap_init(); chk_heap = 1; } else rt.gc(); // the caller's blocks are reachable from its globals, the rest goes + rsn = 0; evn = 0; hl_n = 0; literal_doc_n = 0; if (literal_docs) rt.fill_w(literal_docs, 0, literal_doc_cap); curinc = 0; std_done = 0; icon_done = 0; incdepth = 0; dgdrop = 0; probe_has = 0; probe_n = 0; probe_mem = 0; probe_static = 0; nameoff = 0 - 1; rsbase = src; + if (!rsrec) { rscap = RS_CAP; rsrec = rt.new(RS_CAP * RS_W); rstmp = rt.new(RS_CAP * RS_W); } + ifs = 0; ifx = 0; nifx = 0; nift = 0; nif = 0; ifcur = 0; ifkk = 0; ifgk = 0; ifcall = 0 - 1; + if (ifon) { + ifrcap = NIF; ifxcap = IFN; iftcap = IFT; + ifs = rt.new(symcap); ifr = chk_resize(0, 0, ifrcap); ifx = chk_resize(0, 0, ifxcap * 4); ift = chk_resize(0, 0, iftcap); + if_local = chk_resize(0, 0, loccap); if_edges = 0; if_value = 0; + rt.fill_w(ifs, 0, symcap); + } + zc_init(); + blob_load(rt.GORG[5], 1); + zc_tables(); + types_init(); + here = 0; hdelta = 0; hlimit = lim; ptop = 0; + ubase = nsym; vislo = 0; + prescan(3, src); + src_push(3, src, 0, 0); + next(); + unit_top(); + rs_fix(); + unit_end(ubase); + if (ifx) if_emit(); + src_pop(); + rs_sort(); + chk_end(); + return 0; +} +// walk a document's tokens with the lexer as the check left it. hl_begin +// loads the first token into tk, tv, toff and toklen; next() moves on; hl_end +// restores the previous state. +// the syntax highlighter's view of the lexer. it re-lexes the document after +// the check, so the tokens it sees are cut exactly where the compiler's were +// (parse words that changed the operators included). +int hl_begin(int src) { + chkabort = 0; isp = -1; pq_n = 0; pendot = 0; qdone = 0; panic = 0; + dry++; + src_push(3, src, 0, 0); + next(); + return 0; +} +// end a highlight pass: leave the source and the dry run. +int hl_end() { + src_pop(); + dry--; + isp = -1; + pq_n = 0; + return 0; +} +// the source of the std and icon libraries, embedded when the compiler is built, so +// `include std;` and `include icon;` need no file at run time. +embed "src/lib/std.zc" as bstr std_embedded; +embed "src/lib/icon.zc" as bstr icon_embedded; +bstr std_source() { return std_embedded; } +bstr icon_source() { return icon_embedded; } |
