#!/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')