aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/base.zc
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 10:11:56 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 10:11:56 +0330
commite1e0a265e931637f452ac05bb7d912e07bcee574 (patch)
tree60289bb1fc3d812dfc576f01e0f8a83091a495c1 /src/compiler/base.zc
parentanalyzer: check borrow returns of forward-called functions at the unit's end;... (diff)
lsp: borrow errors ranged on the use, with related information for where the owner ended and was declared; vscode client passes relatedInformation through
Diffstat (limited to 'src/compiler/base.zc')
-rw-r--r--src/compiler/base.zc25
1 files changed, 22 insertions, 3 deletions
diff --git a/src/compiler/base.zc b/src/compiler/base.zc
index bfed062..7e4b5bc 100644
--- a/src/compiler/base.zc
+++ b/src/compiler/base.zc
@@ -415,6 +415,11 @@ int s_new_k, s_recycle_leaf;
// server streams diagnostics and drops a check whose source has been replaced
word chk_hook;
int cmode, chkabort, chkfuel; word dgbuf, dggrow; int dgcap, dgpos, dgn, dgopen, dgprev, dgmode;
+// related places of check-mode records, for the editor: DGREL_W words each, [the record's
+// offset in dgbuf, the packed place where the owner ended, the packed place of the owner's
+// declaration, how it ended (end_why), the owner's name]. reset by chk_begin.
+const int DGREL_W = 5;
+word dgrel; int dgreln, dgrelcap;
// expand a diagnostic in progress, keeping its output offset within the buffer.
int dg_expand() {
dgbuf = chk_resize(dgbuf, dgpos + 5 + rt.outn, dgcap * 2);
@@ -433,8 +438,22 @@ int dg_expand() {
int probe_off = -1, probe_has, probe_n, probe_cap, probe_static;
char** probe_name; word probe_kind, probe_state, probe_type, probe_decl, probe_mem;
char* curinc; int incdepth, dgdrop; int incplace; // how many includes deep the compile is; a record to throw away; the place of the outermost include
+// an open record's range becomes the packed place p (the use itself, not the token after it).
+int dg_place(int p) {
+ if (!cmode || !dgopen || incdepth > 0 || !p || (p & 0xFFFFFF) != tline) return 0;
+ dgbuf[dgpos + 1] = p & 0xFFFFFF; dgbuf[dgpos + 2] = ((p >> 40) & 0x1FFFFF) - 1; dgbuf[dgpos + 3] = (p >> 24) & 0xFFFF;
+ return 0;
+}
+int dg_related(int end_place, int decl_place, int why, char* owner) {
+ if (!cmode || !dgopen || dgdrop || incdepth > 0) return 0;
+ if (dgreln == dgrelcap) { int cap = dgrelcap * 2; if (!cap) cap = 16; dgrel = chk_resize(dgrel, dgreln * DGREL_W, cap * DGREL_W); dgrelcap = cap; }
+ word e = dgrel + dgreln * DGREL_W;
+ e[0] = dgpos; e[1] = end_place; e[2] = decl_place; e[3] = why; e[4] = owner; dgreln++;
+ return 0;
+}
int dg_close() {
if (!dgopen) return 0;
+ if (dgdrop && dgreln && dgrel[(dgreln - 1) * DGREL_W] == dgpos) dgreln--; // its record is thrown away
if (!dgdrop) { dgbuf[dgpos + 4] = rt.outn; dgpos = dgpos + 5 + rt.outn; dgn++; }
dgdrop = 0;
dgopen = 0; rt.outmode = dgmode; rt.outgrow = dggrow;
@@ -470,7 +489,7 @@ word[256] dgseen_initial; word dgseen = dgseen_initial; int dgseen_cap = 256, dg
// start and stop a check run. chk_begin points the diagnostics at a buffer
// the caller owns; chk_end flushes any open record and restores output.
int chk_begin(int buf, int cap) {
- cmode = 1; chkabort = 0; chkfuel = 0; dgbuf = buf; dgcap = cap; dgpos = 0; dgn = 0; dgopen = 0;
+ cmode = 1; chkabort = 0; chkfuel = 0; dgbuf = buf; dgcap = cap; dgpos = 0; dgn = 0; dgopen = 0; dgreln = 0;
nerr = 0; panic = 0; dgmode = rt.outmode; rt.fill_w(dgseen, 0, dgseen_cap); dgseen_n = 0;
return 0;
}
@@ -963,7 +982,7 @@ int cerr(char* msg) {
// "r: used after it was given away; r borrows t, and t was freed on line 5 (t declared on line 4)"
int ended_message(char* use, word info, char* root, int cause) {
char* owner = root; int why = 0; char* whom = 0;
- if (info) { owner = info[0]; why = info[3]; whom = info[4]; }
+ if (info) { owner = info[0]; why = info[3]; whom = info[4]; dg_related(info[5], info[1], why, owner); }
rt.put_s(use); rt.put_s(": used after it was given away; ");
if (!rt.eq_w(use, owner)) { rt.put_s(use); rt.put_s(" borrows "); rt.put_s(owner); rt.put_s(", and "); }
rt.put_s(owner);
@@ -989,7 +1008,7 @@ int cerrn(int i, char* msg) {
if (!info && local_end_info) info = local_end_info[root];
if (info) cause = info[2]; else if (local_ended) cause = local_ended[root];
}
- if (cause && !panic && !dry) { errat(); ended_message(lname[i], info, lname[root], cause); errend(); }
+ if (cause && !panic && !dry) { errat(); dg_place(lreadpos[i]); ended_message(lname[i], info, lname[root], cause); errend(); }
else serrn(lname[i], msg);
}
return 0;