aboutsummaryrefslogtreecommitdiff
path: root/src/lsp/server.zc
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-14 10:06:27 +0000
committerGravatar zinc <zinc@downsta.ir> 2026-10-14 10:06:27 +0000
commitc2270cc944424579e4577e67ed17a66512d856b4 (patch)
tree04fc1ede53e0cbf2c2562f724fd539836c450306 /src/lsp/server.zc
parenttodo: tick the spec; list the bugs its appendix b found (diff)
parentsplit compiler.zc into files by phase (diff)
Merge the compiler split into phase files
also: ca_owners in the language server keeps the owner order in a fixed array instead of a heap list the analyzer rejected.
Diffstat (limited to 'src/lsp/server.zc')
-rw-r--r--src/lsp/server.zc78
1 files changed, 60 insertions, 18 deletions
diff --git a/src/lsp/server.zc b/src/lsp/server.zc
index 3262e39..afa8de4 100644
--- a/src/lsp/server.zc
+++ b/src/lsp/server.zc
@@ -3,10 +3,10 @@ include rt, run;
// ============================================================================
// server.zc: the language server. it is appended to the genome after the
-// compiler (cat src/runtime/rt.zc src/compiler/compiler.zc src/lsp/server.zc | zc0), so it does not
+// compiler (the files of src/compiler/parts in order, then this one, read as one stream), so it does not
// analyze zc with a second implementation of the grammar: it runs the
// compiler itself over the document, in check mode (see chk_unit in
-// compiler.zc), and reports what the compiler said. a parse word, an
+// src/compiler/check.zc), and reports what the compiler said. a parse word, an
// operator or a type the document defines changes how the rest of the
// document is read, for the checker and for the highlighter, because both are
// the compiler. it speaks json-rpc on stdin and stdout, and when stdin is not
@@ -14,7 +14,7 @@ include rt, run;
// ============================================================================
// the first constant the server declares: the blob cut for a document starts
-// here (blob_load, compiler.zc), so this name must stay the first one of the server.
+// here (blob_load, src/compiler/image.zc), so this name must stay the first one of the server.
const int LSP_SERVER = 1;
// the compiler's own functions, declared here so this file checks on its own
@@ -2121,15 +2121,51 @@ int do_nav(int i, int refs) {
// the image carries the text of rt.zc, compiler.zc, server.zc, std.zc, icon.zc and core.zc, embedded
// when the image is built, so the definition of a built-in has somewhere to go. each source is a document
-// of its own at tinyvm:/NAME.zc, which the editor shows read only and can ask for with zc/source
+// of its own at tinyvm:/NAME.zc, which the editor shows read only and can ask for with zc/source.
+// the compiler is several files (src/compiler/parts lists them in order); an embed takes a literal
+// path, so they are named here, in the same order, and joined into the one document tinyvm:/compiler.zc
+// when it is loaded. tests/drivers/nav_test.js checks that this list is the parts file.
const int BS_COUNT = 6;
+const int CC_PARTS = 12;
embed "src/runtime/rt.zc" as bstr rt_embedded;
-embed "src/compiler/compiler.zc" as bstr compiler_embedded;
+embed "src/compiler/base.zc" as bstr cc_base;
+embed "src/compiler/lex.zc" as bstr cc_lex;
+embed "src/compiler/ops.zc" as bstr cc_ops;
+embed "src/compiler/analyzer.zc" as bstr cc_analyzer;
+embed "src/compiler/types.zc" as bstr cc_types;
+embed "src/compiler/builtins.zc" as bstr cc_builtins;
+embed "src/compiler/expr.zc" as bstr cc_expr;
+embed "src/compiler/stmt.zc" as bstr cc_stmt;
+embed "src/compiler/decl.zc" as bstr cc_decl;
+embed "src/compiler/image.zc" as bstr cc_image;
+embed "src/compiler/setup.zc" as bstr cc_setup;
+embed "src/compiler/check.zc" as bstr cc_check;
embed "src/lsp/server.zc" as bstr server_embedded;
embed "src/core/core.zc" as bstr core_embedded;
-bstr bs_text(int k) {
+// part i of the compiler, in the order of src/compiler/parts
+bstr cc_part(int i) {
+ if (i == 0) return cc_base;
+ if (i == 1) return cc_lex;
+ if (i == 2) return cc_ops;
+ if (i == 3) return cc_analyzer;
+ if (i == 4) return cc_types;
+ if (i == 5) return cc_builtins;
+ if (i == 6) return cc_expr;
+ if (i == 7) return cc_stmt;
+ if (i == 8) return cc_decl;
+ if (i == 9) return cc_image;
+ if (i == 10) return cc_setup;
+ return cc_check;
+}
+// source k is this many pieces of text: the compiler's parts, or one file
+int bs_pieces(int k) {
+ if (k == 1) return CC_PARTS;
+ return 1;
+}
+// piece i of source k
+bstr bs_text(int k, int i) {
if (k == 0) return rt_embedded;
- if (k == 1) return compiler_embedded;
+ if (k == 1) return cc_part(i);
if (k == 2) return server_embedded;
if (k == 3) return run.std_source();
if (k == 4) return run.icon_source();
@@ -2145,15 +2181,20 @@ char* bs_uri(int k) {
}
// the document of built-in source k, loaded the first time it is asked for
int bs_load(int k) {
- int i, n = 0, j = 0; bstr p; word text;
+ int i, n = 0, j = 0, q = 0, at, len; bstr p; word text;
if (!bs_idx) bs_idx = lsp_grow(0, 0, BS_COUNT);
if (bs_idx[k]) return bs_idx[k] - 1;
- p = bs_text(k); j = rt.len_s(p);
+ while (q < bs_pieces(k)) { j = j + rt.len_s(bs_text(k, q)); q++; }
text = lsp_grow(0, 0, (j >> 2) + 3);
- while (n < j) {
- if ((n & 3) == 0) text[n >> 2] = 0;
- text[n >> 2] = text[n >> 2] | (rt.at_s(p, n) << ((n & 3) * 8));
- n++;
+ q = 0;
+ while (q < bs_pieces(k)) {
+ p = bs_text(k, q); len = rt.len_s(p); at = 0;
+ while (at < len) {
+ if ((n & 3) == 0) text[n >> 2] = 0;
+ text[n >> 2] = text[n >> 2] | (rt.at_s(p, at) << ((n & 3) * 8));
+ n++; at++;
+ }
+ q++;
}
i = docnew(bs_uri(k), rt.len_w(bs_uri(k)));
doff[i] = text; dsize[i] = n; dver[i] = 1; dgen[i]++;
@@ -3199,11 +3240,12 @@ int ca_add(char* owner, char* path, int from) {
return 0;
}
// the fixes for every module that exports name, best first
+word[32] ca_order;
int ca_owners(char* name, int from) {
- word p = run.export_owners(name), q = 0, next;
- // ca_add prepends, so the list goes in backwards and comes out best first
- while (p) { next = rt.new(2); next[0] = q; next[1] = p; q = next; p = p[0]; }
- while (q) { p = q[1]; ca_add(p[1], p[2], from); next = q[0]; rt.free(q); q = next; }
+ word p = run.export_owners(name); int n = 0;
+ // ca_add prepends, so the owners go in backwards and come out best first
+ while (p && n < 32) { ca_order[n] = p; n++; p = p[0]; }
+ while (n > 0) { n--; p = ca_order[n]; ca_add(p[1], p[2], from); }
return 0;
}
int ca_import_point(int i) {
@@ -3658,7 +3700,7 @@ int cli(int first) {
// zclsp --annotate < file.zc prints the file with the types the compiler can
// see written in: locals from their initializers, parameters from what every
// call passes them or from being used as an address, returns from what the
-// function returns (the type facts of compiler.zc). the typechecker is on for
+// function returns (the type facts of the compiler). the typechecker is on for
// it, and every edit has to leave the file with no error it didn't have, so
// what comes out compiles wherever the input did. when a batch of edits
// fails, the batch is cut in halves until the bad edits are found and left