aboutsummaryrefslogtreecommitdiff
path: root/tests/drivers/code_emission_growth_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/drivers/code_emission_growth_test.py')
-rw-r--r--tests/drivers/code_emission_growth_test.py40
1 files changed, 40 insertions, 0 deletions
diff --git a/tests/drivers/code_emission_growth_test.py b/tests/drivers/code_emission_growth_test.py
new file mode 100644
index 0000000..f13c141
--- /dev/null
+++ b/tests/drivers/code_emission_growth_test.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+# emitted code and global data keep their addresses when the program area fills.
+import argparse
+import subprocess
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--length', type=int, default=600000)
+parser.add_argument('command', nargs=argparse.REMAINDER)
+options = parser.parse_args()
+source = 'int earlier() { return 7; }\n'
+source += f'let storage[{options.length}];\n'
+source += 'let text = "' + 's' * 3500 + '";\n'
+source += 'int later(int n) { return earlier() + n; }\n'
+source += '''fn main() {
+ storage[len(storage) - 1] = 9;
+ gc(); put_n(later(3)); put_c(32); put_n(storage[len(storage) - 1]); put_c(32);
+ put_n(len_w(text)); put_c(32); put_n(code_blocks != 0); put_c(32);
+ let quoted = quote { return 5; };
+ put_n(eval(quoted)); put_c(32);
+ let f = fn(float x) { return x + 1.5; }; put_n((f(2.0) as word) == 0x400c000000000000); put_c(10);
+ return 0;
+}
+'''
+result = subprocess.run(options.command, input=source, text=True, capture_output=True, timeout=40)
+assert result.returncode == 0 and result.stdout == '10 9 3500 1 5 1\n', (result.returncode, result.stdout, result.stderr)
+print('ok linked code segments preserve functions, globals, strings, quotes, and float payloads')
+
+# force the next float opcode and its payload to need a new segment.
+source = 'immediate fn force_edge() { next(); hlimit = here + 3; return 0; }\n'
+source += 'fn main() { force_edge let value = 1.5; gc(); put_n((value as word) == 0x3ff8000000000000); put_c(10); return 0; }\n'
+result = subprocess.run(options.command, input=source, text=True, capture_output=True, timeout=20)
+assert result.returncode == 0 and result.stdout == '1\n', (result.returncode, result.stdout, result.stderr)
+print('ok a float opcode and its payload remain adjacent at a segment boundary')
+source = 'immediate fn force_edge() { next(); hlimit = here + 3; return 0; }\n'
+source += 'force_edge\nenhance cube(x) vm { 0 $ 0 $ * * };\n'
+source += 'enhance sum(a, b) micro "a = add a b";\n'
+source += 'fn main() { gc(); put_n(cube(7)); put_c(32); put_n(sum(3, 4)); put_c(10); return 0; }\n'
+result = subprocess.run(options.command, input=source, text=True, capture_output=True, timeout=20)
+assert result.returncode == 0 and result.stdout == '343 7\n', (result.returncode, result.stdout, result.stderr)
+print('ok vm and micro recipes remain contiguous after a code reservation')