aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-14 20:03:35 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-14 20:04:11 +0330
commit70400c5f382f23c1a72e8a948b41d8039e39e94d (patch)
treed824cbe3aada9fb357954c700ebeac985cc59f84 /src
parentexplain-checks: the record writer moves to src/lib/explain.zc, embedded and c... (diff)
detach doc comments on internal bounds helpers (genome size); todo: reuse capture_scan in the body scanner
Diffstat (limited to 'src')
-rw-r--r--src/compiler/analyzer.zc19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/compiler/analyzer.zc b/src/compiler/analyzer.zc
index c2ea867..d1f6f3d 100644
--- a/src/compiler/analyzer.zc
+++ b/src/compiler/analyzer.zc
@@ -533,6 +533,7 @@ int proven_n(int ix, int n) {
// can own a block. then the size a pointer proof read can change. r[56] the
// allocation facts of the locals at the loop entry (lafact_save), which the
// loop top forgets.
+
int body_name(word r, int nm) {
if (r[1] >= 32) { r[0] = 1; return 0; }
r[2 + r[1]] = nm; r[1]++;
@@ -542,6 +543,7 @@ int body_name(word r, int nm) {
// an array local can (an owner frees what it held), and so can one to a name
// the loop declares, unless a number type comes right before it (pk2, pv2: the
// token before the name)
+
int body_mayfree(int nm, int pk2, int pv2) {
int j = findloc(nm); word t;
if (j < 0) return !(pk2 == T_ID && (pv2 == sx_int || pv2 == sx_char || pv2 == sx_bool || pv2 == sx_float));
@@ -552,6 +554,7 @@ int body_mayfree(int nm, int pk2, int pv2) {
// the scan's view of the token before the current one and the one before that
int bs_pk, bs_pv, bs_pk2, bs_pv2;
// note what the current token says about the body, then read the next one
+
int bs_adv(word r) {
int j;
if (is_id(s_fn)) { peek(); if (pk_tk == T_OP && (pk_tv == s_lp || pk_tv == s_colon)) r[0] = 1; }
@@ -564,6 +567,7 @@ int bs_adv(word r) {
return 0;
}
// a bracketed group from the current ( [ or {, through its closer
+
int bs_group(word r) {
int depth = 0;
while (1) {
@@ -577,6 +581,7 @@ int bs_group(word r) {
}
// one statement, read the way the parser will: a block, if/else, a loop or
// switch with its body, do/while, or anything else up to its ; at depth 0
+
int bs_stmt(word r) {
int depth = 0;
if (tk == T_EOF) { r[0] = 1; return 0; }
@@ -619,6 +624,7 @@ int body_scan(word r) {
return 0;
}
// may the loop body behind r change the local named nm?
+
int ldirty(word r, int nm) {
int k = 0;
if (!r || r[0]) return 1;
@@ -627,6 +633,7 @@ int ldirty(word r, int nm) {
}
// a local nothing outside the function's own code can change: no address
// taken, not captured by a closure
+
int lclean(int i) {
if (laaddr[i]) return 0;
if (local_cell && local_cell[i]) return 0;
@@ -634,6 +641,7 @@ int lclean(int i) {
return 1;
}
// a fresh record for the loop at depth k, or 0 past the first LPI_N depths
+
word linfo_new(int k) {
word r;
if (k >= LPI_N) return 0;
@@ -644,6 +652,7 @@ word linfo_new(int k) {
return r;
}
// the record of the live loop at depth k, or 0
+
word linfo(int k) {
word r;
if (k >= LPI_N || !lpinfo) return 0;
@@ -659,6 +668,7 @@ word linfo(int k) {
// iterations that come first; the flag keeps the check where it was. emits
// the load of the flag and the jump over the check; returns the hole to patch
// past it, or -1 when the check cannot be hoisted.
+
int hoist_guard(int ix, int n, int arr) {
int k = lsp, j; word r;
if (ix < 0 || n <= 0) return 0 - 1;
@@ -682,6 +692,7 @@ int hoist_guard(int ix, int n, int arr) {
}
// the loop entry of a loop with hoisted checks: each flag is 1 when ix < 0 or
// bound > n, then on to the test at c0
+
int hoist_stub(word r, int c0) {
int k = 0;
setlit(r[42], here);
@@ -696,6 +707,7 @@ int hoist_stub(word r, int c0) {
}
// i < n for a pointer local arr to a block of n words: a loop test against a
// constant of at most n, in a loop whose body leaves arr alone
+
int proven_p(int ix, int n, int arr) {
int k = lsp, w; word r;
while (k > loopbase) {
@@ -709,6 +721,7 @@ int proven_p(int ix, int n, int arr) {
return 0;
}
// the allocation facts of the function's locals, kept past the loop top that forgets them
+
word lafact_save() {
word b; int i = lbase;
if (dry || nloc <= lbase) return 0;
@@ -718,6 +731,7 @@ word lafact_save() {
}
// after a loop that frees nothing: the locals its body left alone get back the
// allocation facts the loop forgot
+
int lafact_keep(word r, word b) {
int i;
if (!b || dry || r[0] || r[55]) return 0;
@@ -727,6 +741,7 @@ int lafact_keep(word r, word b) {
}
// the allocation fact of the pointer local bl at the entry of the innermost
// loop over ix, or 0
+
word entry_fact(int ix, int bl) {
int k = lsp; word r, b;
if (ix < 0 || bl < 0) return 0;
@@ -743,6 +758,7 @@ word entry_fact(int ix, int bl) {
// the number of elements behind a pointer local: the requested size of the
// block it was set from, when the analyzer knows it (never a rounded block
// size), for one-word elements; -1 when unknown
+
int ptr_elems(word f, word et, int bl) {
word base;
if (bl < 0 || !f || f[1] == 2 || f[0] < 0 || tbytes(et) || tsz(et) != 1) return 0 - 1;
@@ -758,6 +774,7 @@ int ptr_elems(word f, word et, int bl) {
// is in docs/SPEC.md. the reason codes:
const int XC_NOT_LOOP = 1, XC_NOT_INVARIANT = 2, XC_NOT_LEN = 3, XC_SIZE = 4, XC_PACKED = 5, XC_HOISTED = 6, XC_MAYFREE = 7;
// why a check of index ix (a local, or -1) into the array local arr stays
+
int xc_reason(int ix, int arr) {
int k = lsp; word r;
if (ix < 0) return XC_NOT_LOOP;
@@ -774,6 +791,7 @@ int xc_reason(int ix, int arr) {
}
// the record of one kept check: kind 0 index, 1 pointer; the place of its [
// and, as the end, the token just read (its ]). src/lib/explain.zc writes it.
+
int xc_note(int kind, int why, int place) {
int o1, o2, d = 0, k = loopbase, f;
if (!xc_on || dry || cmode || incdepth > 0 || !xc_src || chbase != xc_src || !xc_hook) return 0;
@@ -785,6 +803,7 @@ int xc_note(int kind, int why, int place) {
}
// is argument 1 --explain-checks? the file name for the records is argument 2.
// then src/lib/explain.zc is compiled, and its note becomes the hook.
+
int xc_init() {
int n = rt.syscall(rt.SYS_ARGC, 0, 0, 0), k, s, f; word b;
if (n < 2) return 0;