diff options
| author | 2026-10-14 10:38:17 +0000 | |
|---|---|---|
| committer | 2026-10-14 10:38:17 +0000 | |
| commit | 93340f97dce404a008f489729df144ace53528ab (patch) | |
| tree | cbada309f3a4683d083d84484f11952418c8dd2b /src | |
| parent | todo: handoff section with state, conventions, in-flight work and architectur... (diff) | |
fix std hover, full capture terminator, bare static calls, void main in run-only images
- hover: a symbol from an embedded library source (tinyvm:std.zc, tinyvm:icon.zc) was
looked up only in the document; look it up by its qualified name in the library source
(hover_embedded_sym), and render a method found that way by its line (bs_hover).
- std.capture: allocate one word more than the 256 it holds, so end() terminates inside the buffer.
- a bare call to a static function of the enclosing struct resolves like a bare struct constant
(mstruct is set for every non-generic struct's methods); the struct's own wins over a global.
- run.zc declares main untyped (fn main();), so a run-only image accepts int, void or untyped main
with both compilers.
Diffstat (limited to 'src')
| -rw-r--r-- | src/compiler/expr.zc | 4 | ||||
| -rw-r--r-- | src/compiler/types.zc | 6 | ||||
| -rw-r--r-- | src/lib/std.zc | 5 | ||||
| -rw-r--r-- | src/lsp/server.zc | 40 | ||||
| -rw-r--r-- | src/runtime/run.zc | 5 |
5 files changed, 47 insertions, 13 deletions
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc index c6d29c6..40de6ef 100644 --- a/src/compiler/expr.zc +++ b/src/compiler/expr.zc @@ -1014,7 +1014,9 @@ int primary() { return C_PLAIN; } s = source_lookup(n); - if (mstruct && !ginst) { ms = lookup(methname(mstruct, n)); if (ms >= 0 && skind[ms] == K_CONST) s = ms; } + // in a method of a struct a bare name is that struct's own constant or static function first, so it + // wins over a global (a top-level function or constant) of the same name + if (mstruct && !ginst) { ms = lookup(methname(mstruct, n)); if (ms >= 0 && (skind[ms] == K_CONST || (skind[ms] == K_FN && (sflag[ms] & F_STATIC)))) s = ms; } if (s < 0 && rt.eq_w(n, "new")) s = source_lookup(s_new); if (s >= 0) rs_put(toff, RS_SYM, rs_sym(s), s); if (s >= 0 && skind[s] == K_KW) { diff --git a/src/compiler/types.zc b/src/compiler/types.zc index c643f0b..6dda110 100644 --- a/src/compiler/types.zc +++ b/src/compiler/types.zc @@ -497,8 +497,9 @@ int dtype() { } return 0; } -// the struct whose body or methods are being compiled, when it declares constants: a bare -// name there is looked up as Struct.name before the global scope +// the struct whose body or methods are being compiled: a bare name there is looked up as Struct.name +// (a constant, or a static function called by its bare name) before the global scope, so the struct's +// own wins over a global of the same name char* mstruct; // does a constant declaration start in a struct body? const NAME = e; const T NAME = e; // (a field of a const type has no initializer, so the = tells them apart) @@ -652,6 +653,7 @@ int kw_struct() { } accept(s_semi); i = 0; + if (!gen) mstruct = n; while (i < nm) { fn_method_compile = 1; methdef(n, mn[i], mq[i], mst[i], mty[i], mrt[i], mrg[i]); fn_method_compile = 0; i++; } mdg = 0; mstruct = msv; diff --git a/src/lib/std.zc b/src/lib/std.zc index 33ab1e9..772b887 100644 --- a/src/lib/std.zc +++ b/src/lib/std.zc @@ -73,7 +73,8 @@ int libinit() { // rt.put_s("hello world!"); // nothing on the terminal // std.capture.end(buf); // rt.put_s(buf); // hello world! -// the buffer holds 256 characters, and output past that is dropped. +// the buffer holds 256 characters, and output past that is dropped. it has one +// more word for the 0 that end() writes, so a full capture is still a string. // one capture at a time, and the buffer belongs to whoever holds it. struct capture { // starts a capture: output goes into a new buffer instead of the terminal. @@ -81,7 +82,7 @@ struct capture { static char* start() { int cap = 256; rt.outmode = 2; rt.outn = 0; rt.outcap = cap; - rt.outbuf = rt.new(cap); + rt.outbuf = rt.new(cap + 1); return rt.outbuf; } // stops the capture and ends the buffer with a 0. diff --git a/src/lsp/server.zc b/src/lsp/server.zc index afa8de4..a43f910 100644 --- a/src/lsp/server.zc +++ b/src/lsp/server.zc @@ -1761,6 +1761,12 @@ int hover_method(int i) { if (!found) ls = le + 1; } if (!found) return 0; + return hover_method_at(i, sg); +} +// the markdown of the method whose signature starts at byte sg of document i: the +// signature up to the body, a ; or the end of the line, then the docs above it +int hover_method_at(int i, int sg) { + int base = doff[i], size = dsize[i], k, se; // the signature: up to the body, a ; or the end of the line se = sg; while (se < size && dc(base, se) != 10 && dc(base, se) != '{' && dc(base, se) != ';') se++; @@ -1919,17 +1925,24 @@ int hover_global(int i, int kind) { r = rs_find(hoff); if (r >= 0 && run.rsrec[r * run.RS_W + 1] == run.RS_SYM && run.rsrec[r * run.RS_W + 3] >= 0 && kind != 2) { s = run.rsrec[r * run.RS_W + 3]; - if (run.skind[s] != run.K_KW && bs_find(run.sname[s])) { hover_fill(bs_load(bs_k)); return hn; } + if (run.skind[s] != run.K_KW && bs_find(run.sname[s])) { bs_hover(); return hn; } } if (kind != 2) { kt = kwtext(); if (kt) return kw_put(kt); } - if (kind == 1) { if (bs_find(hname)) { hover_fill(bs_load(bs_k)); return hn; } hover_blob(i); return hn; } + if (kind == 1) { if (bs_find(hname)) { bs_hover(); return hn; } hover_blob(i); return hn; } if (hover_scan(i)) { hover_fill(i); return hn; } if (hover_method(i)) return hn; if (kind == 0 && hover_local(i)) return hn; - if (kind != 2 && bs_find(hname)) { hover_fill(bs_load(bs_k)); return hn; } + if (kind != 2 && bs_find(hname)) { bs_hover(); return hn; } hover_blob(i); return hn; } +// is symbol s declared in an embedded library source (the text of std or icon, included +// from tinyvm:std.zc and tinyvm:icon.zc)? such a symbol is a user symbol to the compiler +// (rs_sym sets 16 for it) but its text is not in the document, so hover looks it up by +// its qualified name in the library source, as it does for the runtime. +int hover_embedded_sym(int s) { + return s >= 0 && run.sdsrc && run.sdsrc[s] && bs_name(run.sdsrc[s]) && bs_source(run.sdsrc[s]) >= 0; +} // the hover at the cursor. the compiler's record of the name decides what it // is: a local is its declaration, a parameter the header that names it, and a // symbol is looked up as that kind of symbol. a name with no record is found by @@ -1950,7 +1963,9 @@ int do_hover(int i) { else if (k == run.RS_FIELD && v >= 0) hover_named(i, v, 4); else if (k == run.RS_LOCAL) hover_local(i); else if (k == run.RS_SYM) { - if ((v & 15) == run.K_GVAR || (v & 15) == run.K_GARR) { + // a symbol from an embedded library source (std, icon) is above the user's symbols but is not in the document: its declaration is found in that source by its qualified name + if ((v & 16) && hover_embedded_sym(run.rsrec[r * run.RS_W + 3])) hover_global(i, 1); + else if ((v & 15) == run.K_GVAR || (v & 15) == run.K_GARR) { s = run.rsrec[r * run.RS_W + 3]; q = 0; o = 0 - 1; while (q < run.rsn) { if (run.rsrec[q * run.RS_W + 3] == s && lt_find(run.rsrec[q * run.RS_W]) >= 0) { o = run.rsrec[q * run.RS_W]; break; } q++; } if (o >= 0) hover_named(i, o, 3); else if (v & 16) hover_global(i, 2); else hover_global(i, 1); @@ -2261,16 +2276,29 @@ int bs_method(int dd, char* name, int dot) { } return 0 - 1; } +// did the last bs_find_in hit find a method of a struct (bs_off is its name), not a top-level declaration +int bs_meth; +// the hover of the declaration the last successful bs_find found: a method by its line, anything else +// by the scan that found it +int bs_hover() { + int dd = bs_load(bs_k), q; + if (!bs_meth) return hover_fill(dd); + q = bs_off; + while (q > 0 && dc(doff[dd], q - 1) != 10) q--; + while (q < bs_off && (dc(doff[dd], q) == 32 || dc(doff[dd], q) == 9)) q++; + hn = 0; hover_method_at(dd, q); + return hn; +} // locate a declaration inside one source, after removing its module prefix. int bs_find_in(int k, char* name) { int n = 0, dot = -1, o, dd = bs_load(k); while (name[n]) { if (name[n] == '.' && dot < 0) dot = n; n++; } if (dot > 0 && name[dot + 1]) { o = bs_method(dd, name, dot); - if (o >= 0) { bs_k = k; bs_off = o; return 1; } + if (o >= 0) { bs_k = k; bs_off = o; bs_meth = 1; return 1; } } else if (dot < 0) { set_hname(name); - if (hover_scan(dd)) { bs_k = k; bs_off = decl_off(doff[dd], hdl, hdle); return 1; } + if (hover_scan(dd)) { bs_k = k; bs_off = decl_off(doff[dd], hdl, hdle); bs_meth = 0; return 1; } } return 0; } diff --git a/src/runtime/run.zc b/src/runtime/run.zc index a8f82e2..19a5234 100644 --- a/src/runtime/run.zc +++ b/src/runtime/run.zc @@ -8,9 +8,10 @@ include rt; // // cat build/run/rt.zc src/runtime/run.zc examples/hello.zc | ./zc0 >build/run/genome.h -// the program's entry point, written by the program (see start). +// the program's entry point, written by the program (see start). the prototype is untyped so +// that main may be declared int, void or untyped, as in any other program: its value is ignored. namespace; -int main(); +fn main(); namespace run; include rt; |
