aboutsummaryrefslogtreecommitdiff
path: root/src/lsp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lsp')
-rw-r--r--src/lsp/server.zc10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/lsp/server.zc b/src/lsp/server.zc
index 65881a9..d776b1d 100644
--- a/src/lsp/server.zc
+++ b/src/lsp/server.zc
@@ -412,6 +412,7 @@ int gap_out(int from, int to) {
return 0;
}
// is c an operator character, which the highlighter marks as an operator.
+int hov_shared; // the hold block of the global being hovered, when it is shared
int isopc(int c) {
char* s = "+-*/%=<>!&|^~?@#$";
int i = 0;
@@ -1725,6 +1726,8 @@ char* kwtext() {
if (hname_is("switch")) return "switch (e) { case 1, 2: ... default: ... }~a branch on constant labels. the cases don't fall through, and break leaves early.";
if (hname_is("break")) return "break;~leaves the innermost loop or switch.";
if (hname_is("continue")) return "continue;~goes on to the next pass of the innermost loop.";
+ if (hname_is("hold")) return "hold { shared let c; fn a() { } fn b() { } }~a monitor at the top level. its shared variables are one copy for every actor, and only the functions written in the block can use them. each call to one of those functions holds the block's lock for the whole call; a call from one to another doesn't lock again. blocks are entered in the order they are declared.";
+ if (hname_is("shared")) return "shared let c; / shared int[4] counts;~inside a hold block: a variable every actor sees, used only by the block's functions under its lock. it holds numbers or arrays of numbers, since each actor has its own heap.";
if (hname_is("defer")) return "defer e; or defer { }~runs the statement when the enclosing block ends, on every way out of it (falling off the end, return, break, continue). several run last registered first, and what they name is read when they run. return, break and continue are not allowed inside. defer rt.free(p); is the transfer of p for the ownership analysis.";
if (hname_is("return")) return "return e; or return;~leaves the function with a value, or leaves a void function. returning an owned local transfers it to the caller automatically.";
if (hname_is("enum")) return "enum name { A, B = 5 };~global constants. under typecheck on they are a type of their own, and a member can carry fields to make a constructor.";
@@ -1843,6 +1846,7 @@ int hover_named(int i, int o, int kind) {
else if (st == run.S_U) hov_text(".u"); else if (st == run.S_D) hov_text(".d"); else if (st == run.S_DEAD) hov_text(".expired");
hov_put(' '); k = o; while (k < end) { hov_put(dc(base, k)); k++; }
if (kind == 1) hov_text(" // parameter;");
+ else if (kind == 3 && hov_shared > 0) { hov_text(" // shared in hold block "); hov_number(hov_shared); hov_text(": the block's functions use it under its lock;"); }
else if (kind == 3) hov_text(" // global;");
else if (kind == 4) hov_text(" // field;");
else hov_text("; // local");
@@ -2004,7 +2008,9 @@ int do_hover(int i) {
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++; }
+ hov_shared = 0; if (s >= 0 && (run.sflag[s] & run.F_SHARED)) hov_shared = run.sflag[s] / run.F_SHARED_RANK;
if (o >= 0) hover_named(i, o, 3); else if (v & 16) hover_global(i, 2); else hover_global(i, 1);
+ hov_shared = 0;
} else if (v & 16) hover_global(i, 2); else hover_global(i, 1);
}
else hover_global(i, 0);
@@ -3123,7 +3129,7 @@ int cp_symbol(int s, char* label) {
bstr sig = cp_signature(run.sname[s]), doc; int k = 0, kind = 6;
hn = 0;
if (sig) { while (k < rt.len_s(sig)) { hov_put(rt.at_s(sig, k)); k++; } }
- else { if (run.stype[s]) { hov_type(run.stype[s]); hov_put(' '); } hov_text(label); }
+ else { if ((run.skind[s] == run.K_GVAR || run.skind[s] == run.K_GARR) && (run.sflag[s] & run.F_SHARED)) hov_text("shared "); if (run.stype[s]) { hov_type(run.stype[s]); hov_put(' '); } hov_text(label); }
if (run.skind[s] == run.K_FN || run.skind[s] == run.K_ENH) kind = 3;
else if (run.skind[s] == run.K_TYPE) kind = 22;
else if (run.skind[s] == run.K_CONST) kind = 21;
@@ -3264,6 +3270,8 @@ int do_completion(int i) {
if (run.skind[s] != run.K_DOC && run.lookup(run.sname[s]) == s && (run.skind[s] != run.K_FN || (run.sflag[s] & (run.F_DEF | run.F_DECL)))) cp_symbol(s, run.sname[s]);
s++;
}
+ if (cp_score("hold") >= 0) { hn = 0; hov_text("hold { shared let c; fn f() { } }"); if (cp_add("hold", 14, 0, 1)) cp_docs[cp_n - 1] = cp_copy("a monitor: shared variables for every actor, used under the block's lock by the functions written in it"); }
+ if (cp_score("shared") >= 0) { hn = 0; hov_text("shared let name;"); if (cp_add("shared", 14, 0, 1)) cp_docs[cp_n - 1] = cp_copy("inside a hold block: a variable every actor sees, used only by the block's functions"); }
run.probe_off = cp_cursor; old = chk_stream; chk_stream = 0; check_doc(i); chk_stream = old; run.probe_off = -1;
member = 0;
if (run.probe_has == 2 && run.probe_mem && run.probe_mem[0] == run.TY_STRUCT) member = run.probe_mem[2];