From c3490a37aed000bd0522096f56b656900dc60f64 Mon Sep 17 00:00:00 2001 From: IgorCielniak Date: Fri, 9 Jan 2026 12:22:00 +0100 Subject: [PATCH] added compile time intrinsics that allow for modification of the prelude and bss section --- main.py | 57 +++++++++++++++++++++++++++++++++++-- tests/bss_override.expected | 1 + tests/bss_override.sl | 38 +++++++++++++++++++++++++ tests/bss_override.test | 1 + 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 tests/bss_override.expected create mode 100644 tests/bss_override.sl create mode 100644 tests/bss_override.test diff --git a/main.py b/main.py index 625b2e6..8513fdb 100644 --- a/main.py +++ b/main.py @@ -217,6 +217,8 @@ class AsmDefinition: class Module: forms: List[Any] variables: Dict[str, str] = field(default_factory=dict) + prelude: Optional[List[str]] = None + bss: Optional[List[str]] = None @dataclass @@ -351,6 +353,8 @@ class Parser: self.variable_words: Dict[str, str] = {} self.file_spans: List[FileSpan] = [] self.compile_time_vm = CompileTimeVM(self) + self.custom_prelude: Optional[List[str]] = None + self.custom_bss: Optional[List[str]] = None def location_for_token(self, token: Token) -> Tuple[str, int, int]: for span in self.file_spans: @@ -440,6 +444,8 @@ class Parser: self.label_counter = 0 self.token_hook = None self._last_token = None + self.custom_prelude = None + self.custom_bss = None while not self._eof(): token = self._consume() @@ -505,6 +511,8 @@ class Parser: if not isinstance(module, Module): # pragma: no cover - defensive raise ParseError("internal parser state corrupt") module.variables = dict(self.variable_labels) + module.prelude = self.custom_prelude + module.bss = self.custom_bss return module def _handle_list_begin(self) -> None: @@ -1602,7 +1610,8 @@ class Assembler: def emit(self, module: Module) -> Emission: emission = Emission() self._emit_externs(emission.text) - emission.text.extend(self._runtime_prelude()) + prelude_lines = module.prelude if module.prelude is not None else self._runtime_prelude() + emission.text.extend(prelude_lines) self._string_literals = {} self._float_literals = {} self._data_section = emission.data @@ -1636,7 +1645,8 @@ class Assembler: self._data_section.append("data_start:") if not self._data_section or self._data_section[-1] != "data_end:": self._data_section.append("data_end:") - emission.bss.extend(self._bss_layout()) + bss_lines = module.bss if module.bss is not None else self._bss_layout() + emission.bss.extend(bss_lines) self._data_section = None return emission @@ -2432,6 +2442,42 @@ def _ct_list_push_front(vm: CompileTimeVM) -> None: vm.push(lst) +def _ct_prelude_clear(vm: CompileTimeVM) -> None: + vm.parser.custom_prelude = [] + + +def _ct_prelude_append(vm: CompileTimeVM) -> None: + line = vm.pop_str() + if vm.parser.custom_prelude is None: + vm.parser.custom_prelude = [] + vm.parser.custom_prelude.append(line) + + +def _ct_prelude_set(vm: CompileTimeVM) -> None: + lines = _ensure_list(vm.pop()) + if not all(isinstance(item, str) for item in lines): + raise ParseError("prelude-set expects list of strings") + vm.parser.custom_prelude = list(lines) + + +def _ct_bss_clear(vm: CompileTimeVM) -> None: + vm.parser.custom_bss = [] + + +def _ct_bss_append(vm: CompileTimeVM) -> None: + line = vm.pop_str() + if vm.parser.custom_bss is None: + vm.parser.custom_bss = [] + vm.parser.custom_bss.append(line) + + +def _ct_bss_set(vm: CompileTimeVM) -> None: + lines = _ensure_list(vm.pop()) + if not all(isinstance(item, str) for item in lines): + raise ParseError("bss-set expects list of strings") + vm.parser.custom_bss = list(lines) + + def _ct_list_reverse(vm: CompileTimeVM) -> None: lst = _ensure_list(vm.pop()) lst.reverse() @@ -2774,6 +2820,13 @@ def _register_compile_time_primitives(dictionary: Dictionary) -> None: register("list-last", _ct_list_last, compile_only=True) register("i", _ct_loop_index, compile_only=True) + register("prelude-clear", _ct_prelude_clear, compile_only=True) + register("prelude-append", _ct_prelude_append, compile_only=True) + register("prelude-set", _ct_prelude_set, compile_only=True) + register("bss-clear", _ct_bss_clear, compile_only=True) + register("bss-append", _ct_bss_append, compile_only=True) + register("bss-set", _ct_bss_set, compile_only=True) + register("map-new", _ct_map_new, compile_only=True) register("map-set", _ct_map_set, compile_only=True) register("map-get", _ct_map_get, compile_only=True) diff --git a/tests/bss_override.expected b/tests/bss_override.expected new file mode 100644 index 0000000..9183bf0 --- /dev/null +++ b/tests/bss_override.expected @@ -0,0 +1 @@ +256 diff --git a/tests/bss_override.sl b/tests/bss_override.sl new file mode 100644 index 0000000..ea5f952 --- /dev/null +++ b/tests/bss_override.sl @@ -0,0 +1,38 @@ +import stdlib/stdlib.sl +import stdlib/io.sl + +:asm persistent-size { + lea rax, [rel persistent_end] + lea rbx, [rel persistent] + sub rax, rbx + sub r12, 8 + mov [r12], rax +} +; + +word ss + # Override BSS to grow the persistent buffer. + bss-clear + "align 16" bss-append + "dstack: resb DSTK_BYTES" bss-append + "dstack_top:" bss-append + "align 16" bss-append + "rstack: resb RSTK_BYTES" bss-append + "rstack_top:" bss-append + "align 16" bss-append + "print_buf: resb PRINT_BUF_BYTES" bss-append + "print_buf_end:" bss-append + "align 16" bss-append + "persistent: resb 256" bss-append + "persistent_end:" bss-append + "align 16" bss-append + "list_capture_sp: resq 1" bss-append + "list_capture_tmp: resq 1" bss-append + "list_capture_stack: resq 1024" bss-append +end + +word main + persistent-size + print +end +compile-time ss \ No newline at end of file diff --git a/tests/bss_override.test b/tests/bss_override.test new file mode 100644 index 0000000..e906d2a --- /dev/null +++ b/tests/bss_override.test @@ -0,0 +1 @@ +python main.py tests/bss_override.sl -o /tmp/bss_override > /dev/null && /tmp/bss_override \ No newline at end of file