diff options
| author | eunhhu <[email protected]> | 2026-09-26 18:10:52 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-26 18:10:52 +0100 |
| commit | 8a3c59d61a61055b4d93838eff6fbb89b5b91e9a (patch) | |
| tree | e2bd85f493efeb9d1ddf4bba5c369515177eae72 | |
| parent | cebb5a73d3d8436c72839117d1c92b7228d4c866 (diff) | |
| download | aup-8a3c59d61a61055b4d93838eff6fbb89b5b91e9a.tar.gz aup-8a3c59d61a61055b4d93838eff6fbb89b5b91e9a.zip | |
Raise the program limits to Pure's: 65,535 instructions, 4,096 strings
The limit's diagnostic now comes from fns that double what they inline,
and a module of some 12,000 instructions (200 KB) must compile and run.
| -rw-r--r-- | src/compile.c | 10 | ||||
| -rw-r--r-- | tests/check.py | 8 |
2 files changed, 11 insertions, 7 deletions
diff --git a/src/compile.c b/src/compile.c index e9ce67a..27176a1 100644 --- a/src/compile.c +++ b/src/compile.c @@ -8,8 +8,8 @@ #include <string.h> /* Limits and opcodes of Pure module format v5. */ -enum { STATES = 32, INPUTS = 32, VIEWS = 64, HANDLERS = 64, CODE = 512, STACK = 64, NAME = 32, JOINS = 8, - DEPTH = 64, FIELDS = 32, COLLECTIONS = 1, CONSTANTS = 64, CONSTANT_BYTES = 8192, +enum { STATES = 32, INPUTS = 32, VIEWS = 64, HANDLERS = 64, CODE = 65535, STACK = 64, NAME = 32, JOINS = 8, + DEPTH = 64, FIELDS = 32, COLLECTIONS = 1, CONSTANTS = 4096, CONSTANT_BYTES = 1 << 20, RECORDS = 8, RECORD_FIELDS = 64, FIELDS_PER_RECORD = 16, FNS = 64, PARAMS = 8, MODULES = 9 }; enum { CONST, LOAD, DT, ADD, SUB, MUL, DIV, NEG, LT, LE, GT, GE, EQ, NE, AND, OR, NOT, MIN, MAX, CLAMP, STORE, JZ, JMP, FIELD, DOC, DOC_SIZE, LEN, REPLACE, REPLY, REQUIRE, @@ -1344,7 +1344,7 @@ static void declaration(Compiler *c) { /* ---- Checks and code generation ------------------------------------- */ static void emit(Compiler *c, int line, int column, uint8_t op, uint32_t arg, double value) { - if (c->code_count == CODE) fail_at(c, line, column, "program exceeds 512 instructions"); + if (c->code_count == CODE) fail_at(c, line, column, "program exceeds 65535 instructions"); c->code[c->code_count].op = op; c->code[c->code_count].arg = arg; c->code[c->code_count++].value = value; @@ -1359,8 +1359,8 @@ static uint32_t constant(Compiler *c, const Expr *e) { for (unsigned i = 0; i < c->constants; ++i) if (c->constant_length[i] == e->size && (!e->size || !memcmp(c->constant_data + c->constant_offset[i], e->bytes, e->size))) return i; - if (c->constants == CONSTANTS) fail_at(c, e->line, e->column, "at most 64 distinct strings are allowed"); - if (e->size > CONSTANT_BYTES - c->constant_used) fail_at(c, e->line, e->column, "strings exceed 8192 bytes"); + if (c->constants == CONSTANTS) fail_at(c, e->line, e->column, "at most 4096 distinct strings are allowed"); + if (e->size > CONSTANT_BYTES - c->constant_used) fail_at(c, e->line, e->column, "strings exceed 1 MiB"); if (e->size) memcpy(c->constant_data + c->constant_used, e->bytes, e->size); c->constant_offset[c->constants] = (uint32_t)c->constant_used; c->constant_length[c->constants] = (uint32_t)e->size; diff --git a/tests/check.py b/tests/check.py index 5c151dd..e7b7c8b 100644 --- a/tests/check.py +++ b/tests/check.py @@ -73,7 +73,9 @@ DIAGNOSTICS = [ ('view v = 1 +\n', '1:13', 'expected a number, state, or expression'), ('state a = 0\non frame {\n a = 1 a\n}\n', '3:9', 'expected newline or semicolon'), ('state a = 0\non frame {\n if a {\n a = 1\n } els {\n }\n}\n', '5:5', 'expected newline or semicolon'), - ('view v = ' + '+'.join(['1'] * 300) + '\n', '1:', 'program exceeds 512 instructions'), + # Each fn doubles what it inlines: f14 is past Pure's 65,535 instructions. + ('\n'.join(['fn f0(x) = x + 1'] + [f'fn f{i}(x) = f{i - 1}(f{i - 1}(x))' for i in range(1, 15)] + ['view v = f14(1)']) + '\n', + '1:14', "program exceeds 65535 instructions (in fn 'f0' called at 2:15)"), ('view v = ' + '(' * 70 + '1' + ')' * 70 + '\n', '1:', 'expression nesting exceeds 64'), ('state s = 0\n' * 1 + ''.join(f'state s{i} = 0\n' for i in range(32)), '33:7', 'at most 32 states are allowed'), # v0b: messages, keyed documents and types @@ -266,6 +268,8 @@ ACCEPTED = [ # A timer, now, floor and %. 'state last = 0\ninput tick = every 500 ms\ninput slow = every 2 hours\non tick { last = floor(now / 1000) % 60 }\n' 'on slow { last = -7 % 3 }\nview v = last % 7\n', + # A module of some 12,000 instructions (200 KB): hosts read it whole. + '\n'.join(['fn f0(x) = x + 1'] + [f'fn f{i}(x) = f{i - 1}(f{i - 1}(x))' for i in range(1, 12)] + ['view v = f11(1)']) + '\n', ] @@ -390,7 +394,7 @@ def properties(aup, pure_run, work, rounds): path, module = work / 'generated.aup', work / 'generated.pmod' path.write_text(source) result = run(aup, 'build', path, '-o', module, check=False) - if result.returncode == 1 and 'program exceeds 512 instructions' in result.stderr: + if result.returncode == 1 and 'program exceeds 65535 instructions' in result.stderr: over_limit += 1 # well formed but longer than a module may be continue assert result.returncode == 0, (source, result.stderr) |
