aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--docs/SPEC.md2
-rwxr-xr-xsrc/baremetal/run.sh4
-rw-r--r--src/compiler/decl.zc2
-rw-r--r--src/lsp/server.zc16
-rwxr-xr-xsrc/tools/parity.sh2
-rwxr-xr-xsrc/tools/zcc2
-rw-r--r--tests/bench/bench_bytes.sh2
-rw-r--r--tests/bench/bench_share.sh2
-rw-r--r--tests/bench/bench_strings.sh2
-rw-r--r--tests/drivers/imagekit.py2
-rwxr-xr-xtests/test.sh10
-rw-r--r--tests/xref.baseline8
13 files changed, 37 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index ceed9be..ff9e9d0 100644
--- a/Makefile
+++ b/Makefile
@@ -58,7 +58,7 @@ WEB := $(B)/web
MAP := $(B)/core/map
# hand-written core headers, the generated map, and where #embed finds the genome image
COREINC := -Isrc/core -I$(MAP) --embed-dir=$(B)/core
-CORE_H := src/core/genome.h src/core/fops.h src/core/bops.h src/core/stack.h $(MAP)/memmap.h
+CORE_H := src/core/genome.h src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h $(MAP)/memmap.h
# the sources the compiler genome is built from, and the files it embeds
# the compiler is the files named in src/compiler/parts, in that order
ZC_PARTS := $(addprefix src/compiler/,$(shell cat src/compiler/parts))
diff --git a/docs/SPEC.md b/docs/SPEC.md
index a4f8397..7dd1247 100644
--- a/docs/SPEC.md
+++ b/docs/SPEC.md
@@ -823,7 +823,7 @@ hold {
```
`hold` followed by `{` at the top level starts a hold block; elsewhere `hold` and `shared` are ordinary names. a hold block contains shared variable declarations, functions, and any other top-level items. hold blocks don't nest (error: hold blocks don't nest). each block has a rank, its position among the unit's hold blocks, from 1.
-5.16.2 a shared variable is a global with one value for the whole program, seen by every actor (docs/ACTOR.md); every other global is each actor's own copy. its type is a number type or a fixed array of one. a pointer, string, struct, growable array or function type is error: x: is shared, so it holds numbers: no pointers, strings or structs (each actor has its own heap). an initializer is a constant, as for any global.
+5.16.2 a shared variable is a global with one value for the whole program, seen by every actor (docs/ACTOR.md); every other global is each actor's own copy. its type is a number type or a fixed array of one. a pointer, string, struct, growable array or function type is error: x: is shared, so it holds numbers: no pointers, strings or structs (each worker has its own heap). an initializer is a constant, as for any global.
5.16.3 only the functions written in the block can name its shared variables. a use anywhere else, including in another hold block, is error: x: is shared in a hold block; only the functions written inside that block can use it (they hold its lock). a use in a closure, even one written inside the block, is error: x: is shared; a closure can't use it, because it may run after the hold block's lock is released. a function of a hold block can't be `o3` (error: f: is in a hold block and can't be o3).
diff --git a/src/baremetal/run.sh b/src/baremetal/run.sh
index 43f8a4c..5f812fa 100755
--- a/src/baremetal/run.sh
+++ b/src/baremetal/run.sh
@@ -69,7 +69,7 @@ if [ "$mode" = run ] || [ "$mode" = io ]; then
# the map is sized to the program, so a bigger runtime or program just gets a bigger board
${CC:-$(sh src/tools/findcc.sh)} -O2 -w src/tools/genmap.c -o "$D/genmap"
GENMAP="$D/genmap" bash src/tools/automap.sh run "$D/img" src/runtime/run.zc "$src" >"$D/genmap.log" 2>&1 || { cat "$D/genmap.log" >&2; exit 1; }
- cp src/micro/micro.c src/micro/micro_port.h src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h "$D/img/"
+ cp src/micro/micro.c src/micro/micro_port.h src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h "$D/img/"
"$cc" $common $def -I"$D/img" -c "$D/img/micro.c" -o "$D/micro.o"
if [ "$mode" = io ]; then
"$cc" $common $def -DBARE_INPUT=1 -I"$D/img" -c src/baremetal/port.c -o "$D/port.o"
@@ -80,7 +80,7 @@ if [ "$mode" = run ] || [ "$mode" = io ]; then
fi
elif [ "$mode" = compile ]; then
[ -f build/core/genome.bin ] || { echo "baremetal: no build/core/genome.bin; run make genome first" >&2; exit 1; }
- cp src/micro/micro.c src/micro/micro_port.h build/core/map/memmap.h build/core/genome.bin src/core/genome.h src/core/fops.h src/core/bops.h src/core/stack.h "$D/"
+ cp src/micro/micro.c src/micro/micro_port.h build/core/map/memmap.h build/core/genome.bin src/core/genome.h src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h "$D/"
"$cc" $common $def -I"$D" -c "$D/micro.c" -o "$D/micro.o"
"$cc" $common $def -DBARE_INPUT=1 -I"$D" -c src/baremetal/port.c -o "$D/port.o"
timeout=90
diff --git a/src/compiler/decl.zc b/src/compiler/decl.zc
index fed7b8d..55e23a7 100644
--- a/src/compiler/decl.zc
+++ b/src/compiler/decl.zc
@@ -264,7 +264,7 @@ int kw_hold() {
if (skind[s] == K_GVAR || skind[s] == K_GARR) {
t = stype[s]; w = 1;
if (skind[s] == K_GARR) { w = tsz(t); if (t[0] == TY_ARR) t = t[1]; }
- if (t && (isptr(t) || isagg(t) || t == tbstr || t[0] == TY_DYN || t[0] == TY_FN)) serrn(sname[s], "is shared, so it holds numbers: no pointers, strings or structs (each actor has its own heap)");
+ if (t && (isptr(t) || isagg(t) || t == tbstr || t[0] == TY_DYN || t[0] == TY_FN)) serrn(sname[s], "is shared, so it holds numbers: no pointers, strings or structs (each worker has its own heap)");
sflag[s] = sflag[s] | F_SHARED | rank * F_SHARED_RANK;
if (hold_nshared >= 64) serr("too many shared variables in one hold block (64)");
else { hold_tab[hold_nshared * 2] = sval[s]; hold_tab[hold_nshared * 2 + 1] = w; hold_nshared++; }
diff --git a/src/lsp/server.zc b/src/lsp/server.zc
index d776b1d..85f3ea5 100644
--- a/src/lsp/server.zc
+++ b/src/lsp/server.zc
@@ -3100,6 +3100,18 @@ int cp_score(char* name) {
if (exact) { if (n == i) return 0; return 10 + n - i; }
return 100 + score + n - i;
}
+// a label already offered (a symbol named like a keyword wins over the keyword)
+int cp_has(char* name) {
+ int k = 0, i;
+ while (k < cp_n) {
+ i = 0;
+ while (name[i] && cp_name[k][i] == name[i]) i++;
+ if (!name[i] && !cp_name[k][i]) return 1;
+ k++;
+ }
+ return 0;
+}
+
int cp_add(char* name, int kind, int dead, int relevance) {
int score = cp_score(name);
if (score < 0) return 0;
@@ -3270,8 +3282,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"); }
+ if (cp_score("hold") >= 0 && !cp_has("hold")) { 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 && !cp_has("shared")) { 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];
diff --git a/src/tools/parity.sh b/src/tools/parity.sh
index 2d2086d..1b90885 100755
--- a/src/tools/parity.sh
+++ b/src/tools/parity.sh
@@ -71,7 +71,7 @@ SRCS="src/runtime/rt.zc src/core/core.zc src/runtime/run.zc"
if cmp -s "$W/prefix.new" "$W/prefix.zc"; then rm "$W/prefix.new"; else mv "$W/prefix.new" "$W/prefix.zc"; fi
nprefix=$(wc -l < "$W/prefix.zc")
# what the compiled image depends on besides the program
-DEPS="$ZC0 $MKG $W/prefix.zc src/micro/micro.c src/micro/port_linux.c src/micro/micro_port.h src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h build/core/map/memmap.h"
+DEPS="$ZC0 $MKG $W/prefix.zc src/micro/micro.c src/micro/port_linux.c src/micro/micro_port.h src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h build/core/map/memmap.h"
# one line of a program's output: newlines as /, control bytes as ?, cut to 60 columns
short() {
diff --git a/src/tools/zcc b/src/tools/zcc
index ba38e97..a53fe01 100755
--- a/src/tools/zcc
+++ b/src/tools/zcc
@@ -41,7 +41,7 @@ trap cleanup EXIT
# the map and the genome for this program only
( cd "$here" && bash src/tools/automap.sh run "$work/run" src/runtime/run.zc "$abs" ) >/dev/null
cp "$here/src/micro/micro.c" "$here/src/micro/micro_port.h" "$here/src/micro/port_linux.c" \
- "$here/src/core/fops.h" "$here/src/core/bops.h" "$here/src/core/stack.h" "$here/src/core/genome.h" "$work/run/"
+ "$here/src/core/fops.h" "$here/src/core/bops.h" "$here/src/core/stack.h" "$here/src/core/hold.h" "$here/src/core/genome.h" "$work/run/"
# static where the toolchain allows it; a plain link otherwise, with a note
static=-static
diff --git a/tests/bench/bench_bytes.sh b/tests/bench/bench_bytes.sh
index 775b71d..c509da4 100644
--- a/tests/bench/bench_bytes.sh
+++ b/tests/bench/bench_bytes.sh
@@ -10,7 +10,7 @@ T=$(mktemp -d)
trap 'rm -rf "$T"' EXIT
$CC -O2 -w src/tools/genmap.c -o "$T/genmap" || exit 1
GENMAP="$T/genmap" bash src/tools/automap.sh run "$T/run" src/runtime/run.zc tests/programs/bench_bytes.zc >/dev/null || exit 1
-cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h "$T/run/"
+cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h "$T/run/"
$CC -O2 -w -DJTYPE=int "$T/run/core.c" "$T/run/io_linux.c" -o "$T/zy" || exit 1
$CC -O2 -w "$T/run/micro.c" "$T/run/port_linux.c" -o "$T/zym" || exit 1
vms=("$T/zy" "$T/zym"); names=("interp" "micro")
diff --git a/tests/bench/bench_share.sh b/tests/bench/bench_share.sh
index 5cb1bfd..c47f5f5 100644
--- a/tests/bench/bench_share.sh
+++ b/tests/bench/bench_share.sh
@@ -8,7 +8,7 @@ T=$(mktemp -d)
trap 'rm -rf "$T"' EXIT
$CC -O2 -w src/tools/genmap.c -o "$T/genmap" || exit 1
"$T/genmap" --preset run -o "$T/run" >/dev/null || exit 1
-cp src/tools/zc0.c src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h "$T/run/"
+cp src/tools/zc0.c src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h "$T/run/"
$CC -O1 -w "$T/run/zc0.c" -o "$T/zc0" || exit 1
cat "$T/run/rt.zc" src/core/core.zc src/runtime/run.zc tests/programs/bench_share.zc | "$T/zc0" > "$T/run/genome.bin" || exit 1
$CC -O2 -w -DJTYPE=int "$T/run/core.c" "$T/run/io_linux.c" -o "$T/zy" || exit 1
diff --git a/tests/bench/bench_strings.sh b/tests/bench/bench_strings.sh
index b14bf57..8bf3b77 100644
--- a/tests/bench/bench_strings.sh
+++ b/tests/bench/bench_strings.sh
@@ -8,7 +8,7 @@ T=$(mktemp -d)
trap 'rm -rf "$T"' EXIT
$CC -O2 -w src/tools/genmap.c -o "$T/genmap" || exit 1
"$T/genmap" --preset run -o "$T/run" >/dev/null || exit 1
-cp src/tools/zc0.c src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h "$T/run/"
+cp src/tools/zc0.c src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h "$T/run/"
$CC -O1 -w "$T/run/zc0.c" -o "$T/zc0" || exit 1
cat "$T/run/rt.zc" src/core/core.zc src/runtime/run.zc tests/programs/bench_strings.zc | "$T/zc0" > "$T/run/genome.bin" || exit 1
$CC -O2 -w -DJTYPE=int "$T/run/core.c" "$T/run/io_linux.c" -o "$T/zy" || exit 1
diff --git a/tests/drivers/imagekit.py b/tests/drivers/imagekit.py
index 6cc083f..5df4810 100644
--- a/tests/drivers/imagekit.py
+++ b/tests/drivers/imagekit.py
@@ -9,7 +9,7 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
DEFAULT_MAP = ROOT / 'build' / 'core' / 'map' / 'memmap.h'
MICRO_SOURCES = ['src/micro/micro.c', 'src/micro/micro_port.h', 'src/micro/port_linux.c',
- 'src/core/fops.h', 'src/core/bops.h', 'src/core/stack.h', 'src/core/genome.h']
+ 'src/core/fops.h', 'src/core/bops.h', 'src/core/stack.h', 'src/core/hold.h', 'src/core/genome.h']
def compiler():
diff --git a/tests/test.sh b/tests/test.sh
index 90599ed..c31cfb7 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -337,10 +337,10 @@ s_small() {
cmp -s $T/small/memmap.h $T/small-flags/memmap.h && cmp -s $T/small/rt.zc $T/small-flags/rt.zc \
&& cmp -s $T/small/compiler.zc $T/small-flags/compiler.zc && cmp -s $T/small/map.txt $T/small-flags/map.txt \
&& chk 1 1 "compiler flags reproduce the small map" || chk 0 1 "compiler flags reproduce the small map"
- cp src/tools/zc0.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h $T/small/
+ cp src/tools/zc0.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h $T/small/
$CC -O1 -w -fwrapv $T/small/zc0.c -o $T/zc0s || exit 1
cat $T/small/rt.zc src/core/core.zc $T/small/compiler.zc | $T/zc0s > $T/small/genome.bin || exit 1
- cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h $T/small/
+ cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/core.c src/core/io_linux.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h $T/small/
$CC -pthread -DZY_THREADS -O2 -w -fwrapv $T/small/micro.c $T/small/port_linux.c -o $T/zyms || exit 1
$CC -pthread -O2 -w -fwrapv -DJTYPE=int $T/small/core.c $T/small/io_linux.c -o $T/zys || exit 1
$CC -ffreestanding -w -c $T/small/micro.c -o $T/micro_s.o && $CC -ffreestanding -w -c $T/small/port_stub.c -o $T/stub_s.o && chk 1 1 "small microcore compiles freestanding" || chk 0 1 "small microcore compiles freestanding"
@@ -381,14 +381,14 @@ s_runonly() {
# its own run map: the run-only image is built against this one, and the
# small-machine section lays out its own rather than sharing this
$T/genmap --preset run -o $T/run || exit 1
- cp src/tools/zc0.c src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h $T/run/
+ cp src/tools/zc0.c src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h $T/run/
$CC -O1 -w -fwrapv $T/run/zc0.c -o $T/zc0r || exit 1
runonly() { # $1 label, $2 source. the program is already in the image, so it reads no source.
# the map is sized to the program: src/tools/automap.sh lays it out for the image's own length
local a b d=$T/run-$1 input=$2
if [ "$1" = gc ]; then input=$T/collector-progress.zc; sed -E 's/f >= [0-9]+/f > 0/' "$2" > "$input"; fi
GENMAP=$T/genmap bash src/tools/automap.sh run $d src/runtime/run.zc "$input" >/dev/null || { chk 0 1 "run $1 builds"; return; }
- cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h $d/
+ cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h $d/
$CC -pthread -DZY_THREADS -O2 -w -fwrapv $d/micro.c $d/port_linux.c -o $T/zymr || { chk 0 1 "run $1 links"; return; }
a=$($T/zy < "$input" 2>&1 | sed "s#<stdin>#$input#g" | tr '\n' '/')
b=$($T/zymr </dev/null 2>&1 | tr '\n' '/')
@@ -413,7 +413,7 @@ s_runonly() {
runonly zc0bstr tests/programs/zc0bstr.zc
runonly zc0umd tests/programs/zc0umd.zc
runonly wiring examples/wiring.zc
- d=$T/run-echo; GENMAP=$T/genmap bash src/tools/automap.sh run $d src/runtime/run.zc examples/echo.zc >/dev/null && cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/genome.h $d/ \
+ d=$T/run-echo; GENMAP=$T/genmap bash src/tools/automap.sh run $d src/runtime/run.zc examples/echo.zc >/dev/null && cp src/micro/micro.c src/micro/micro_port.h src/micro/port_linux.c src/micro/port_stub.c src/core/fops.h src/core/bops.h src/core/stack.h src/core/hold.h src/core/genome.h $d/ \
&& $CC -pthread -DZY_THREADS -O2 -w -fwrapv $d/micro.c $d/port_linux.c -o $T/zymr \
&& chk "$(printf 'abc\n' | $T/zymr | tr '\n' '/')" "$( (cat examples/echo.zc; printf '`abc\n') | $T/zy | tr '\n' '/')" "run echo" \
|| chk 0 1 "run echo"
diff --git a/tests/xref.baseline b/tests/xref.baseline
index 26b6931..79e948b 100644
--- a/tests/xref.baseline
+++ b/tests/xref.baseline
@@ -161,6 +161,7 @@ fbnd chk_reset closure ctx_pop fn_begin kw_unbounded
fchk chk_reset ctx_pop defer_one fn_begin kw_unchecked
fdepth block blockexpr casebody chk_reset ctx_pop fn_begin kw_for kw_switch substmt
fframe chk_reset ctx_pop prologue
+fhold fndef
fieldcap field_note
fieldn field_note types_init
fieldnames field_note
@@ -236,6 +237,11 @@ hl_lev hint_set
hl_n chk_unit hint_set
hl_off hint_set
hlimit build_image_grow chk_unit reserve_code start syntax_resident
+hold_count kw_hold
+hold_cur kw_hold
+hold_desc kw_hold
+hold_nshared kw_hold
+hold_tab kw_hold
ht_end ht_note
ht_n ht_note
ht_start ht_note
@@ -630,7 +636,7 @@ sdsrc addsym def_note reserve_symbols
send_check args field
seqtop seqasm zc_init
sfix addsym enhdef fndef fnref reserve_symbols
-sflag add_kw addsym blob_load call enhdef fndef fndone fwdfn_at ginstance kw_extern kw_struct methcall methdecl prescan_fn reserve_symbols retcheck
+sflag add_kw addsym blob_load call enhdef fndef fndone fwdfn_at ginstance kw_extern kw_hold kw_struct methcall methdecl prescan_fn reserve_symbols retcheck
sgb sig_attach
sgb_initial
sigcap sig_attach