aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compile.c10
-rw-r--r--tests/check.py8
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)