← Commit history

refactor(kiln): consume shared hearth/front lexer and pipeline; drop old lexer and @import support

lennoxrose committed on Oct 18, 2026 at 00:38 UTC

8f85ee4parentdb1d620

67 files changed+148−948

hearth/kiln/Makefilemodified

+10−7
@@ -1,21 +1,17 @@
11 CC = gcc
22 .DEFAULT_GOAL := all
33 KILN_RPATH_LIST = $(abspath ../../bin/extensions/pyre):/usr/local/lib/kiln
4-CFLAGS = -Wall -Wextra -std=c11 -O2 -Isrc -DKILN_RPATH='"$(KILN_RPATH_LIST)"'
5-LDFLAGS =
4+CFLAGS = -Wall -Wextra -std=c11 -O2 -Isrc -I../front/src -DKILN_RPATH='"$(KILN_RPATH_LIST)"'
5+LDFLAGS = ../../bin/libashfront.a
66
77 KILN_SRC = \
88 src/app/C/main.c \
99 src/app/C/target.c \
10- src/lexer/C/lexer.c \
11- src/lexer/C/lexer_import.c \
1210 src/parser/C/core/parser.c \
1311 src/parser/C/declarations/constants.c \
1412 src/parser/C/declarations/functions.c \
1513 src/parser/C/declarations/module_state.c \
1614 src/parser/C/declarations/vars.c \
17- src/parser/C/imports/import_paths.c \
18- src/parser/C/imports/imports.c \
1915 src/parser/C/statements/each_loop.c \
2016 src/parser/C/statements/loop_stack.c \
2117 src/parser/C/statements/parser_control.c \
@@ -108,7 +104,14 @@ BIN = ../../bin/kiln
108104
109105 all: $(BIN)
110106
111-$(BIN): $(KILN_OBJ)
107+# The shared front end (lexer, parser, type checker, lowering) is the only frontend kiln has;
108+# front's own Makefile decides whether the library is up to date.
109+../../bin/libashfront.a: FORCE
110+ $(MAKE) -C ../front
111+
112+FORCE:
113+
114+$(BIN): $(KILN_OBJ) ../../bin/libashfront.a
112115 mkdir -p ../../bin
113116 $(CC) $(CFLAGS) -o $(BIN) $(KILN_OBJ) $(LDFLAGS)
114117

hearth/kiln/src/app/C/main.cmodified

+10−20
@@ -9,23 +9,11 @@
99 #include "pe/H/pe_writer.h"
1010 #include "pe/H/pe_dll_writer.h"
1111 #include "diagnostics/H/diagnostics.h"
12+#include "jdriver/H/jdriver.h"
1213 #include "app/H/target.h"
1314
14-static char *read_file(const char *path) {
15- FILE *file = fopen(path, "rb");
16- if (!file) { fprintf(stderr, "kiln: could not open file: %s\n", path); exit(1); }
17- fseek(file, 0L, SEEK_END);
18- long size = ftell(file);
19- rewind(file);
20- char *buffer = malloc((size_t)size + 1);
21- fread(buffer, 1, (size_t)size, file);
22- buffer[size] = '\0';
23- fclose(file);
24- return buffer;
25-}
26-
2715 static void usage(const char *prog) {
28- fprintf(stderr, "usage: %s <file.ash> -o <output> [--target=linux|windows] [--link=static|shared]\n", prog);
16+ fprintf(stderr, "usage: %s <file.ash> -o <output> [--target=linux|windows] [--link=static|shared] [--wrap-int]\n", prog);
2917 fprintf(stderr, " %s --emit-runtime -o <libkilnrt.so|libkilnrt.dll> [--target=linux|windows]\n", prog);
3018 exit(1);
3119 }
@@ -65,14 +53,16 @@ int main(int argc, char *argv[]) {
6553 : elf_write_shared_runtime(argv[3]);
6654 }
6755
68- if (argc < 4 || argc > 6) usage(argv[0]);
56+ if (argc < 4 || argc > 7) usage(argv[0]);
6957 if (strcmp(argv[2], "-o") != 0) usage(argv[0]);
7058
7159 const char *input_path = argv[1];
7260 const char *output_path = argv[3];
7361
62+ int wrap_int = 0;
7463 for (int i = 4; i < argc; i++) {
75- if (strncmp(argv[i], "--target=", 9) == 0) kiln_set_target(parse_target(argv[i], argv[0]));
64+ if (strcmp(argv[i], "--wrap-int") == 0) wrap_int = 1;
65+ else if (strncmp(argv[i], "--target=", 9) == 0) kiln_set_target(parse_target(argv[i], argv[0]));
7666 else if (strncmp(argv[i], "--link=", 7) == 0) kiln_set_link_mode(parse_link(argv[i], argv[0]));
7767 else usage(argv[0]);
7868 }
@@ -92,12 +82,12 @@ int main(int argc, char *argv[]) {
9282 }
9383 }
9484
95- char *source = read_file(input_path);
96- diagnostics_set_source(source, input_path);
85+ char *ir = jdriver_compile_file(input_path, wrap_int);
86+ if (!ir) return 1;
87+ diagnostics_set_source(ir, "<internal ir>");
9788
9889 CodeBuf machine_code;
99- compile_program(source, input_path, &machine_code);
100- free(source);
90+ compile_program(ir, &machine_code);
10191
10292 int status;
10393 if (kiln_get_target() == KILN_TARGET_WINDOWS) {

hearth/kiln/src/app/D/main.dmodified

+7−5
@@ -1,14 +1,15 @@
11 src/app/O/main.o: src/app/C/main.c src/parser/H/core/parser.h \
2- src/lexer/H/lexer.h src/codegen/H/emit/emit.h src/elf/H/elf_writer.h \
3- src/codegen/H/emit/runtime_layout.h src/elf/H/elf_dynamic.h \
4- src/codegen/H/emit/runtime_import_enum.h \
2+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
3+ src/elf/H/elf_writer.h src/codegen/H/emit/runtime_layout.h \
4+ src/elf/H/elf_dynamic.h src/codegen/H/emit/runtime_import_enum.h \
55 src/codegen/H/emit/runtime_exports.def \
66 src/codegen/H/emit/ash_gpu_import_enum.h \
77 src/codegen/H/emit/ash_gpu_exports.def src/elf/H/elf_so_writer.h \
88 src/pe/H/pe_writer.h src/pe/H/pe_imports.def src/pe/H/pe_dll_writer.h \
9- src/diagnostics/H/diagnostics.h src/app/H/target.h
9+ src/diagnostics/H/diagnostics.h ../front/src/jdriver/H/jdriver.h \
10+ src/app/H/target.h
1011 src/parser/H/core/parser.h:
11-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1213 src/codegen/H/emit/emit.h:
1314 src/elf/H/elf_writer.h:
1415 src/codegen/H/emit/runtime_layout.h:
@@ -22,4 +23,5 @@ src/pe/H/pe_writer.h:
2223 src/pe/H/pe_imports.def:
2324 src/pe/H/pe_dll_writer.h:
2425 src/diagnostics/H/diagnostics.h:
26+../front/src/jdriver/H/jdriver.h:
2527 src/app/H/target.h:

hearth/kiln/src/codegen/D/builtins/builtins.dmodified

+2−2
@@ -1,6 +1,6 @@
11 src/codegen/O/builtins/builtins.o: src/codegen/C/builtins/builtins.c \
22 src/codegen/H/builtins/builtins.h src/codegen/H/expressions/expr.h \
3- src/lexer/H/lexer.h src/codegen/H/collections/arrays.h \
3+ ../front/src/ir/H/ir_lex.h src/codegen/H/collections/arrays.h \
44 src/codegen/H/collections/maps.h src/codegen/H/collections/matrix_mul.h \
55 src/codegen/H/builtins/math_builtins.h \
66 src/codegen/H/builtins/convert_builtins.h \
@@ -13,7 +13,7 @@ src/codegen/O/builtins/builtins.o: src/codegen/C/builtins/builtins.c \
1313 src/codegen/H/emit/emit.h
1414 src/codegen/H/builtins/builtins.h:
1515 src/codegen/H/expressions/expr.h:
16-src/lexer/H/lexer.h:
16+../front/src/ir/H/ir_lex.h:
1717 src/codegen/H/collections/arrays.h:
1818 src/codegen/H/collections/maps.h:
1919 src/codegen/H/collections/matrix_mul.h:

hearth/kiln/src/codegen/D/builtins/exit_builtin.dmodified

+2−2
@@ -1,15 +1,15 @@
11 src/codegen/O/builtins/exit_builtin.o: \
22 src/codegen/C/builtins/exit_builtin.c \
33 src/codegen/H/builtins/exit_builtin.h src/codegen/H/expressions/expr.h \
4- src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
55 src/codegen/H/emit/emit_sse.h src/codegen/H/platform/win_call.h \
66 src/pe/H/pe_writer.h src/codegen/H/emit/runtime_layout.h \
77 src/codegen/H/emit/runtime_import_enum.h \
88 src/codegen/H/emit/runtime_exports.def src/pe/H/pe_imports.def \
99 src/app/H/target.h src/parser/H/core/parser.h
1010 src/codegen/H/builtins/exit_builtin.h:
1111 src/codegen/H/expressions/expr.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1313 src/codegen/H/emit/emit.h:
1414 src/codegen/H/emit/emit_sse.h:
1515 src/codegen/H/platform/win_call.h:

hearth/kiln/src/codegen/D/builtins/filter_builtin.dmodified

+2−2
@@ -1,14 +1,14 @@
11 src/codegen/O/builtins/filter_builtin.o: \
22 src/codegen/C/builtins/filter_builtin.c \
33 src/codegen/H/builtins/higher_order.h src/codegen/H/expressions/expr.h \
4- src/lexer/H/lexer.h src/codegen/H/functions/closures.h \
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/functions/closures.h \
55 src/parser/H/declarations/functions.h src/codegen/H/emit/emit.h \
66 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/value.h \
77 src/codegen/H/runtime/heap.h src/parser/H/core/parser.h \
88 src/parser/H/declarations/vars.h
99 src/codegen/H/builtins/higher_order.h:
1010 src/codegen/H/expressions/expr.h:
11-src/lexer/H/lexer.h:
11+../front/src/ir/H/ir_lex.h:
1212 src/codegen/H/functions/closures.h:
1313 src/parser/H/declarations/functions.h:
1414 src/codegen/H/emit/emit.h:

hearth/kiln/src/codegen/D/builtins/map_builtin.dmodified

+2−2
@@ -1,13 +1,13 @@
11 src/codegen/O/builtins/map_builtin.o: \
22 src/codegen/C/builtins/map_builtin.c \
33 src/codegen/H/builtins/higher_order.h src/codegen/H/expressions/expr.h \
4- src/lexer/H/lexer.h src/codegen/H/functions/closures.h \
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/functions/closures.h \
55 src/parser/H/declarations/functions.h src/codegen/H/emit/emit.h \
66 src/codegen/H/emit/value.h src/codegen/H/runtime/heap.h \
77 src/parser/H/core/parser.h src/parser/H/declarations/vars.h
88 src/codegen/H/builtins/higher_order.h:
99 src/codegen/H/expressions/expr.h:
10-src/lexer/H/lexer.h:
10+../front/src/ir/H/ir_lex.h:
1111 src/codegen/H/functions/closures.h:
1212 src/parser/H/declarations/functions.h:
1313 src/codegen/H/emit/emit.h:

hearth/kiln/src/codegen/D/builtins/math_builtins.dmodified

+2−2
@@ -2,10 +2,10 @@ src/codegen/O/builtins/math_builtins.o: \
22 src/codegen/C/builtins/math_builtins.c \
33 src/codegen/H/builtins/math_builtins.h src/codegen/H/emit/emit.h \
44 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/value.h \
5- src/parser/H/core/parser.h src/lexer/H/lexer.h
5+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h
66 src/codegen/H/builtins/math_builtins.h:
77 src/codegen/H/emit/emit.h:
88 src/codegen/H/emit/emit_sse.h:
99 src/codegen/H/emit/value.h:
1010 src/parser/H/core/parser.h:
11-src/lexer/H/lexer.h:
11+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/builtins/num_builtin.dmodified

+2−2
@@ -2,10 +2,10 @@ src/codegen/O/builtins/num_builtin.o: \
22 src/codegen/C/builtins/num_builtin.c \
33 src/codegen/H/builtins/convert_builtins.h src/codegen/H/emit/emit.h \
44 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/value.h \
5- src/parser/H/core/parser.h src/lexer/H/lexer.h
5+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h
66 src/codegen/H/builtins/convert_builtins.h:
77 src/codegen/H/emit/emit.h:
88 src/codegen/H/emit/emit_sse.h:
99 src/codegen/H/emit/value.h:
1010 src/parser/H/core/parser.h:
11-src/lexer/H/lexer.h:
11+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/builtins/reduce_builtin.dmodified

+2−2
@@ -1,12 +1,12 @@
11 src/codegen/O/builtins/reduce_builtin.o: \
22 src/codegen/C/builtins/reduce_builtin.c \
33 src/codegen/H/builtins/higher_order.h src/codegen/H/expressions/expr.h \
4- src/lexer/H/lexer.h src/codegen/H/functions/closures.h \
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/functions/closures.h \
55 src/parser/H/declarations/functions.h src/codegen/H/emit/emit.h \
66 src/parser/H/core/parser.h src/parser/H/declarations/vars.h
77 src/codegen/H/builtins/higher_order.h:
88 src/codegen/H/expressions/expr.h:
9-src/lexer/H/lexer.h:
9+../front/src/ir/H/ir_lex.h:
1010 src/codegen/H/functions/closures.h:
1111 src/parser/H/declarations/functions.h:
1212 src/codegen/H/emit/emit.h:

hearth/kiln/src/codegen/D/builtins/sort_builtin.dmodified

+2−2
@@ -1,14 +1,14 @@
11 src/codegen/O/builtins/sort_builtin.o: \
22 src/codegen/C/builtins/sort_builtin.c \
33 src/codegen/H/builtins/higher_order.h src/codegen/H/expressions/expr.h \
4- src/lexer/H/lexer.h src/codegen/H/functions/closures.h \
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/functions/closures.h \
55 src/parser/H/declarations/functions.h src/codegen/H/strings/strings.h \
66 src/codegen/H/emit/emit.h src/codegen/H/emit/emit_sse.h \
77 src/codegen/H/emit/value.h src/parser/H/core/parser.h \
88 src/parser/H/declarations/vars.h
99 src/codegen/H/builtins/higher_order.h:
1010 src/codegen/H/expressions/expr.h:
11-src/lexer/H/lexer.h:
11+../front/src/ir/H/ir_lex.h:
1212 src/codegen/H/functions/closures.h:
1313 src/parser/H/declarations/functions.h:
1414 src/codegen/H/strings/strings.h:

hearth/kiln/src/codegen/D/builtins/str_builtin.dmodified

+2−2
@@ -5,7 +5,7 @@ src/codegen/O/builtins/str_builtin.o: \
55 src/codegen/H/runtime/heap.h src/codegen/H/runtime/errors.h \
66 src/codegen/H/strings/strings.h src/codegen/H/runtime/number_format.h \
77 src/codegen/H/emit/bytes.h src/parser/H/core/parser.h \
8- src/lexer/H/lexer.h
8+ ../front/src/ir/H/ir_lex.h
99 src/codegen/H/builtins/convert_builtins.h:
1010 src/codegen/H/emit/emit.h:
1111 src/codegen/H/emit/emit_sse.h:
@@ -16,4 +16,4 @@ src/codegen/H/strings/strings.h:
1616 src/codegen/H/runtime/number_format.h:
1717 src/codegen/H/emit/bytes.h:
1818 src/parser/H/core/parser.h:
19-src/lexer/H/lexer.h:
19+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/builtins/type_builtin.dmodified

+2−2
@@ -3,11 +3,11 @@ src/codegen/O/builtins/type_builtin.o: \
33 src/codegen/H/builtins/type_builtin.h src/codegen/H/strings/strings.h \
44 src/codegen/H/emit/emit_internal.h src/codegen/H/emit/emit.h \
55 src/codegen/H/emit/value.h src/parser/H/core/parser.h \
6- src/lexer/H/lexer.h
6+ ../front/src/ir/H/ir_lex.h
77 src/codegen/H/builtins/type_builtin.h:
88 src/codegen/H/strings/strings.h:
99 src/codegen/H/emit/emit_internal.h:
1010 src/codegen/H/emit/emit.h:
1111 src/codegen/H/emit/value.h:
1212 src/parser/H/core/parser.h:
13-src/lexer/H/lexer.h:
13+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/collections/array_mutate.dmodified

+2−2
@@ -4,7 +4,7 @@ src/codegen/O/collections/array_mutate.o: \
44 src/codegen/H/emit/emit.h src/codegen/H/emit/emit_sse.h \
55 src/codegen/H/emit/value.h src/codegen/H/runtime/heap.h \
66 src/codegen/H/runtime/errors.h src/parser/H/core/parser.h \
7- src/lexer/H/lexer.h
7+ ../front/src/ir/H/ir_lex.h
88 src/codegen/H/collections/arrays.h:
99 src/codegen/H/emit/emit_internal.h:
1010 src/codegen/H/emit/emit.h:
@@ -13,4 +13,4 @@ src/codegen/H/emit/value.h:
1313 src/codegen/H/runtime/heap.h:
1414 src/codegen/H/runtime/errors.h:
1515 src/parser/H/core/parser.h:
16-src/lexer/H/lexer.h:
16+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/collections/arrays.dmodified

+2−2
@@ -1,13 +1,13 @@
11 src/codegen/O/collections/arrays.o: src/codegen/C/collections/arrays.c \
22 src/codegen/H/collections/arrays.h src/codegen/H/expressions/expr.h \
3- src/lexer/H/lexer.h src/codegen/H/emit/emit_internal.h \
3+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit_internal.h \
44 src/codegen/H/emit/emit.h src/codegen/H/emit/emit_sse.h \
55 src/codegen/H/emit/value.h src/codegen/H/runtime/heap.h \
66 src/codegen/H/emit/bytes.h src/codegen/H/runtime/errors.h \
77 src/parser/H/core/parser.h
88 src/codegen/H/collections/arrays.h:
99 src/codegen/H/expressions/expr.h:
10-src/lexer/H/lexer.h:
10+../front/src/ir/H/ir_lex.h:
1111 src/codegen/H/emit/emit_internal.h:
1212 src/codegen/H/emit/emit.h:
1313 src/codegen/H/emit/emit_sse.h:

hearth/kiln/src/codegen/D/collections/keys_values.dmodified

+2−2
@@ -2,12 +2,12 @@ src/codegen/O/collections/keys_values.o: \
22 src/codegen/C/collections/keys_values.c \
33 src/codegen/H/collections/keys_values.h src/codegen/H/emit/emit.h \
44 src/codegen/H/emit/value.h src/codegen/H/runtime/heap.h \
5- src/parser/H/core/parser.h src/lexer/H/lexer.h \
5+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h \
66 src/parser/H/declarations/vars.h
77 src/codegen/H/collections/keys_values.h:
88 src/codegen/H/emit/emit.h:
99 src/codegen/H/emit/value.h:
1010 src/codegen/H/runtime/heap.h:
1111 src/parser/H/core/parser.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1313 src/parser/H/declarations/vars.h:

hearth/kiln/src/codegen/D/collections/maps.dmodified

+2−2
@@ -1,15 +1,15 @@
11 src/codegen/O/collections/maps.o: src/codegen/C/collections/maps.c \
22 src/codegen/H/collections/maps.h \
33 src/codegen/H/collections/maps_internal.h \
4- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
4+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
55 src/codegen/H/strings/strings.h src/codegen/H/emit/emit_internal.h \
66 src/codegen/H/emit/emit.h src/codegen/H/emit/value.h \
77 src/codegen/H/runtime/heap.h src/codegen/H/runtime/errors.h \
88 src/parser/H/core/parser.h
99 src/codegen/H/collections/maps.h:
1010 src/codegen/H/collections/maps_internal.h:
1111 src/codegen/H/expressions/expr.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1313 src/codegen/H/strings/strings.h:
1414 src/codegen/H/emit/emit_internal.h:
1515 src/codegen/H/emit/emit.h:

hearth/kiln/src/codegen/D/collections/maps_mutate.dmodified

+2−2
@@ -5,7 +5,7 @@ src/codegen/O/collections/maps_mutate.o: \
55 src/codegen/H/emit/emit_internal.h src/codegen/H/emit/emit.h \
66 src/codegen/H/emit/value.h src/codegen/H/runtime/heap.h \
77 src/codegen/H/emit/bytes.h src/parser/H/core/parser.h \
8- src/lexer/H/lexer.h
8+ ../front/src/ir/H/ir_lex.h
99 src/codegen/H/collections/maps.h:
1010 src/codegen/H/collections/arrays.h:
1111 src/codegen/H/collections/maps_internal.h:
@@ -15,4 +15,4 @@ src/codegen/H/emit/value.h:
1515 src/codegen/H/runtime/heap.h:
1616 src/codegen/H/emit/bytes.h:
1717 src/parser/H/core/parser.h:
18-src/lexer/H/lexer.h:
18+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/collections/matrix_mul.dmodified

+3−2
@@ -9,7 +9,8 @@ src/codegen/O/collections/matrix_mul.o: \
99 src/codegen/H/emit/ash_gpu_exports.def src/elf/H/elf_writer.h \
1010 src/codegen/H/emit/runtime_layout.h src/codegen/H/runtime/heap.h \
1111 src/codegen/H/runtime/errors.h src/parser/H/core/parser.h \
12- src/lexer/H/lexer.h src/parser/H/declarations/vars.h src/app/H/target.h
12+ ../front/src/ir/H/ir_lex.h src/parser/H/declarations/vars.h \
13+ src/app/H/target.h
1314 src/codegen/H/collections/matrix_mul.h:
1415 src/codegen/H/emit/emit.h:
1516 src/codegen/H/emit/value.h:
@@ -25,6 +26,6 @@ src/codegen/H/emit/runtime_layout.h:
2526 src/codegen/H/runtime/heap.h:
2627 src/codegen/H/runtime/errors.h:
2728 src/parser/H/core/parser.h:
28-src/lexer/H/lexer.h:
29+../front/src/ir/H/ir_lex.h:
2930 src/parser/H/declarations/vars.h:
3031 src/app/H/target.h:

hearth/kiln/src/codegen/D/expressions/expr.dmodified

+2−2
@@ -1,5 +1,5 @@
11 src/codegen/O/expressions/expr.o: src/codegen/C/expressions/expr.c \
2- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
2+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
33 src/codegen/H/expressions/expr_internal.h src/codegen/H/emit/emit.h \
44 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/value.h \
55 src/codegen/H/strings/strings.h src/codegen/H/collections/arrays.h \
@@ -10,7 +10,7 @@ src/codegen/O/expressions/expr.o: src/codegen/C/expressions/expr.c \
1010 src/parser/H/declarations/module_state.h \
1111 src/parser/H/declarations/constants.h
1212 src/codegen/H/expressions/expr.h:
13-src/lexer/H/lexer.h:
13+../front/src/ir/H/ir_lex.h:
1414 src/codegen/H/expressions/expr_internal.h:
1515 src/codegen/H/emit/emit.h:
1616 src/codegen/H/emit/emit_sse.h:

hearth/kiln/src/codegen/D/expressions/expr_bool.dmodified

+2−2
@@ -1,11 +1,11 @@
11 src/codegen/O/expressions/expr_bool.o: \
22 src/codegen/C/expressions/expr_bool.c src/codegen/H/expressions/expr.h \
3- src/lexer/H/lexer.h src/codegen/H/expressions/expr_internal.h \
3+ ../front/src/ir/H/ir_lex.h src/codegen/H/expressions/expr_internal.h \
44 src/codegen/H/emit/emit.h src/codegen/H/emit/emit_sse.h \
55 src/codegen/H/emit/value.h src/codegen/H/strings/strings.h \
66 src/codegen/H/runtime/errors.h src/parser/H/core/parser.h
77 src/codegen/H/expressions/expr.h:
8-src/lexer/H/lexer.h:
8+../front/src/ir/H/ir_lex.h:
99 src/codegen/H/expressions/expr_internal.h:
1010 src/codegen/H/emit/emit.h:
1111 src/codegen/H/emit/emit_sse.h:

hearth/kiln/src/codegen/D/expressions/expr_call.dmodified

+2−2
@@ -1,11 +1,11 @@
11 src/codegen/O/expressions/expr_call.o: \
22 src/codegen/C/expressions/expr_call.c src/codegen/H/expressions/expr.h \
3- src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
3+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
44 src/codegen/H/builtins/builtins.h src/codegen/H/functions/closures.h \
55 src/parser/H/declarations/functions.h src/parser/H/core/parser.h \
66 src/parser/H/declarations/vars.h
77 src/codegen/H/expressions/expr.h:
8-src/lexer/H/lexer.h:
8+../front/src/ir/H/ir_lex.h:
99 src/codegen/H/emit/emit.h:
1010 src/codegen/H/builtins/builtins.h:
1111 src/codegen/H/functions/closures.h:

hearth/kiln/src/codegen/D/functions/closures.dmodified

+2−2
@@ -1,7 +1,7 @@
11 src/codegen/O/functions/closures.o: src/codegen/C/functions/closures.c \
22 src/codegen/H/functions/closures.h src/parser/H/declarations/functions.h \
33 src/codegen/H/functions/closures_internal.h src/codegen/H/emit/emit.h \
4- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
4+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
55 src/codegen/H/emit/value.h src/codegen/H/runtime/heap.h \
66 src/codegen/H/emit/layout.h src/parser/H/core/parser.h \
77 src/parser/H/declarations/vars.h
@@ -10,7 +10,7 @@ src/parser/H/declarations/functions.h:
1010 src/codegen/H/functions/closures_internal.h:
1111 src/codegen/H/emit/emit.h:
1212 src/codegen/H/expressions/expr.h:
13-src/lexer/H/lexer.h:
13+../front/src/ir/H/ir_lex.h:
1414 src/codegen/H/emit/value.h:
1515 src/codegen/H/runtime/heap.h:
1616 src/codegen/H/emit/layout.h:

hearth/kiln/src/codegen/D/functions/lambda.dmodified

+2−2
@@ -2,7 +2,7 @@ src/codegen/O/functions/lambda.o: src/codegen/C/functions/lambda.c \
22 src/codegen/H/functions/closures.h src/parser/H/declarations/functions.h \
33 src/codegen/H/functions/closures_internal.h src/codegen/H/emit/emit.h \
44 src/codegen/H/emit/value.h src/codegen/H/expressions/expr.h \
5- src/lexer/H/lexer.h src/codegen/H/emit/layout.h \
5+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/layout.h \
66 src/parser/H/core/parser.h src/parser/H/core/parser_internal.h \
77 src/parser/H/declarations/vars.h src/parser/H/statements/each_loop.h \
88 src/parser/H/statements/loop_stack.h
@@ -12,7 +12,7 @@ src/codegen/H/functions/closures_internal.h:
1212 src/codegen/H/emit/emit.h:
1313 src/codegen/H/emit/value.h:
1414 src/codegen/H/expressions/expr.h:
15-src/lexer/H/lexer.h:
15+../front/src/ir/H/ir_lex.h:
1616 src/codegen/H/emit/layout.h:
1717 src/parser/H/core/parser.h:
1818 src/parser/H/core/parser_internal.h:

hearth/kiln/src/codegen/D/io/argv_builtin.dmodified

+3−2
@@ -4,7 +4,8 @@ src/codegen/O/io/argv_builtin.o: src/codegen/C/io/argv_builtin.c \
44 src/codegen/H/emit/bytes.h src/codegen/H/runtime/heap.h \
55 src/codegen/H/emit/value.h src/elf/H/elf_writer.h \
66 src/codegen/H/emit/runtime_layout.h src/parser/H/core/parser.h \
7- src/lexer/H/lexer.h src/parser/H/declarations/vars.h src/app/H/target.h
7+ ../front/src/ir/H/ir_lex.h src/parser/H/declarations/vars.h \
8+ src/app/H/target.h
89 src/codegen/H/io/argv_builtin.h:
910 src/codegen/H/io/argv_builtin_internal.h:
1011 src/codegen/H/emit/emit.h:
@@ -15,6 +16,6 @@ src/codegen/H/emit/value.h:
1516 src/elf/H/elf_writer.h:
1617 src/codegen/H/emit/runtime_layout.h:
1718 src/parser/H/core/parser.h:
18-src/lexer/H/lexer.h:
19+../front/src/ir/H/ir_lex.h:
1920 src/parser/H/declarations/vars.h:
2021 src/app/H/target.h:

hearth/kiln/src/codegen/D/io/argv_builtin_windows.dmodified

+2−2
@@ -7,7 +7,7 @@ src/codegen/O/io/argv_builtin_windows.o: \
77 src/codegen/H/emit/runtime_layout.h \
88 src/codegen/H/emit/runtime_import_enum.h \
99 src/codegen/H/emit/runtime_exports.def src/pe/H/pe_imports.def \
10- src/parser/H/core/parser.h src/lexer/H/lexer.h \
10+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h \
1111 src/parser/H/declarations/vars.h
1212 src/codegen/H/io/argv_builtin_internal.h:
1313 src/codegen/H/emit/emit.h:
@@ -22,5 +22,5 @@ src/codegen/H/emit/runtime_import_enum.h:
2222 src/codegen/H/emit/runtime_exports.def:
2323 src/pe/H/pe_imports.def:
2424 src/parser/H/core/parser.h:
25-src/lexer/H/lexer.h:
25+../front/src/ir/H/ir_lex.h:
2626 src/parser/H/declarations/vars.h:

hearth/kiln/src/codegen/D/io/fs_builtins.dmodified

+2−2
@@ -1,7 +1,7 @@
11 src/codegen/O/io/fs_builtins.o: src/codegen/C/io/fs_builtins.c \
22 src/codegen/H/io/file_builtins.h src/codegen/H/io/file_path.h \
33 src/codegen/H/emit/emit.h src/codegen/H/expressions/expr.h \
4- src/lexer/H/lexer.h src/codegen/H/emit/emit_sse.h \
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit_sse.h \
55 src/codegen/H/emit/value.h src/codegen/H/emit/bytes.h \
66 src/codegen/H/collections/arrays.h \
77 src/codegen/H/platform/platform_file.h src/codegen/H/runtime/errors.h \
@@ -15,7 +15,7 @@ src/codegen/H/io/file_builtins.h:
1515 src/codegen/H/io/file_path.h:
1616 src/codegen/H/emit/emit.h:
1717 src/codegen/H/expressions/expr.h:
18-src/lexer/H/lexer.h:
18+../front/src/ir/H/ir_lex.h:
1919 src/codegen/H/emit/emit_sse.h:
2020 src/codegen/H/emit/value.h:
2121 src/codegen/H/emit/bytes.h:

hearth/kiln/src/codegen/D/io/input_builtin.dmodified

+2−2
@@ -3,7 +3,7 @@ src/codegen/O/io/input_builtin.o: src/codegen/C/io/input_builtin.c \
33 src/codegen/H/emit/emit.h src/codegen/H/emit/bytes.h \
44 src/codegen/H/runtime/heap.h src/codegen/H/emit/value.h \
55 src/codegen/H/platform/platform_console.h src/parser/H/core/parser.h \
6- src/lexer/H/lexer.h src/parser/H/declarations/vars.h
6+ ../front/src/ir/H/ir_lex.h src/parser/H/declarations/vars.h
77 src/codegen/H/io/input_builtin.h:
88 src/codegen/H/strings/string_alloc.h:
99 src/codegen/H/emit/emit.h:
@@ -12,5 +12,5 @@ src/codegen/H/runtime/heap.h:
1212 src/codegen/H/emit/value.h:
1313 src/codegen/H/platform/platform_console.h:
1414 src/parser/H/core/parser.h:
15-src/lexer/H/lexer.h:
15+../front/src/ir/H/ir_lex.h:
1616 src/parser/H/declarations/vars.h:

hearth/kiln/src/codegen/D/io/read_file_builtin.dmodified

+2−2
@@ -3,7 +3,7 @@ src/codegen/O/io/read_file_builtin.o: \
33 src/codegen/H/io/file_path.h src/codegen/H/emit/emit.h \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/runtime/errors.h \
55 src/codegen/H/emit/value.h src/codegen/H/platform/platform_file.h \
6- src/parser/H/core/parser.h src/lexer/H/lexer.h \
6+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h \
77 src/parser/H/declarations/vars.h
88 src/codegen/H/io/file_builtins.h:
99 src/codegen/H/io/file_path.h:
@@ -13,5 +13,5 @@ src/codegen/H/runtime/errors.h:
1313 src/codegen/H/emit/value.h:
1414 src/codegen/H/platform/platform_file.h:
1515 src/parser/H/core/parser.h:
16-src/lexer/H/lexer.h:
16+../front/src/ir/H/ir_lex.h:
1717 src/parser/H/declarations/vars.h:

hearth/kiln/src/codegen/D/io/write_file_builtins.dmodified

+2−2
@@ -1,15 +1,15 @@
11 src/codegen/O/io/write_file_builtins.o: \
22 src/codegen/C/io/write_file_builtins.c src/codegen/H/io/file_builtins.h \
33 src/codegen/H/io/file_path.h src/codegen/H/emit/emit.h \
4- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
4+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
55 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/value.h \
66 src/codegen/H/platform/platform_file.h src/parser/H/core/parser.h \
77 src/parser/H/declarations/vars.h
88 src/codegen/H/io/file_builtins.h:
99 src/codegen/H/io/file_path.h:
1010 src/codegen/H/emit/emit.h:
1111 src/codegen/H/expressions/expr.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1313 src/codegen/H/emit/emit_sse.h:
1414 src/codegen/H/emit/value.h:
1515 src/codegen/H/platform/platform_file.h:

hearth/kiln/src/codegen/D/strings/affix_builtins.dmodified

+2−2
@@ -2,15 +2,15 @@ src/codegen/O/strings/affix_builtins.o: \
22 src/codegen/C/strings/affix_builtins.c \
33 src/codegen/H/strings/string_builtins.h \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/emit/emit.h \
5- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
5+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
66 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/bytes.h \
77 src/codegen/H/emit/value.h src/codegen/H/runtime/errors.h \
88 src/parser/H/core/parser.h src/parser/H/declarations/vars.h
99 src/codegen/H/strings/string_builtins.h:
1010 src/codegen/H/strings/string_alloc.h:
1111 src/codegen/H/emit/emit.h:
1212 src/codegen/H/expressions/expr.h:
13-src/lexer/H/lexer.h:
13+../front/src/ir/H/ir_lex.h:
1414 src/codegen/H/emit/emit_sse.h:
1515 src/codegen/H/emit/bytes.h:
1616 src/codegen/H/emit/value.h:

hearth/kiln/src/codegen/D/strings/case_builtins.dmodified

+2−2
@@ -3,10 +3,10 @@ src/codegen/O/strings/case_builtins.o: \
33 src/codegen/H/strings/string_builtins.h \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/emit/emit.h \
55 src/codegen/H/emit/value.h src/parser/H/core/parser.h \
6- src/lexer/H/lexer.h
6+ ../front/src/ir/H/ir_lex.h
77 src/codegen/H/strings/string_builtins.h:
88 src/codegen/H/strings/string_alloc.h:
99 src/codegen/H/emit/emit.h:
1010 src/codegen/H/emit/value.h:
1111 src/parser/H/core/parser.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/strings/char_builtins.dmodified

+2−2
@@ -4,7 +4,7 @@ src/codegen/O/strings/char_builtins.o: \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/emit/emit.h \
55 src/codegen/H/runtime/errors.h src/codegen/H/emit/emit_internal.h \
66 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/value.h \
7- src/parser/H/core/parser.h src/lexer/H/lexer.h
7+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h
88 src/codegen/H/strings/string_builtins.h:
99 src/codegen/H/strings/string_alloc.h:
1010 src/codegen/H/emit/emit.h:
@@ -13,4 +13,4 @@ src/codegen/H/emit/emit_internal.h:
1313 src/codegen/H/emit/emit_sse.h:
1414 src/codegen/H/emit/value.h:
1515 src/parser/H/core/parser.h:
16-src/lexer/H/lexer.h:
16+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/strings/indexof_builtin.dmodified

+2−2
@@ -1,12 +1,12 @@
11 src/codegen/O/strings/indexof_builtin.o: \
22 src/codegen/C/strings/indexof_builtin.c \
33 src/codegen/H/strings/string_builtins.h src/codegen/H/expressions/expr.h \
4- src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
55 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/value.h \
66 src/parser/H/core/parser.h src/parser/H/declarations/vars.h
77 src/codegen/H/strings/string_builtins.h:
88 src/codegen/H/expressions/expr.h:
9-src/lexer/H/lexer.h:
9+../front/src/ir/H/ir_lex.h:
1010 src/codegen/H/emit/emit.h:
1111 src/codegen/H/emit/emit_sse.h:
1212 src/codegen/H/emit/value.h:

hearth/kiln/src/codegen/D/strings/join_builtin.dmodified

+2−2
@@ -2,14 +2,14 @@ src/codegen/O/strings/join_builtin.o: \
22 src/codegen/C/strings/join_builtin.c \
33 src/codegen/H/strings/string_builtins.h \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/emit/emit.h \
5- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
5+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
66 src/codegen/H/emit/bytes.h src/codegen/H/emit/value.h \
77 src/parser/H/core/parser.h src/parser/H/declarations/vars.h
88 src/codegen/H/strings/string_builtins.h:
99 src/codegen/H/strings/string_alloc.h:
1010 src/codegen/H/emit/emit.h:
1111 src/codegen/H/expressions/expr.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1313 src/codegen/H/emit/bytes.h:
1414 src/codegen/H/emit/value.h:
1515 src/parser/H/core/parser.h:

hearth/kiln/src/codegen/D/strings/replace_builtin.dmodified

+2−2
@@ -2,14 +2,14 @@ src/codegen/O/strings/replace_builtin.o: \
22 src/codegen/C/strings/replace_builtin.c \
33 src/codegen/H/strings/string_builtins.h \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/emit/emit.h \
5- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
5+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
66 src/codegen/H/emit/bytes.h src/codegen/H/emit/value.h \
77 src/parser/H/core/parser.h src/parser/H/declarations/vars.h
88 src/codegen/H/strings/string_builtins.h:
99 src/codegen/H/strings/string_alloc.h:
1010 src/codegen/H/emit/emit.h:
1111 src/codegen/H/expressions/expr.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1313 src/codegen/H/emit/bytes.h:
1414 src/codegen/H/emit/value.h:
1515 src/parser/H/core/parser.h:

hearth/kiln/src/codegen/D/strings/split_builtin.dmodified

+2−2
@@ -2,15 +2,15 @@ src/codegen/O/strings/split_builtin.o: \
22 src/codegen/C/strings/split_builtin.c \
33 src/codegen/H/strings/string_builtins.h \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/emit/emit.h \
5- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
5+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
66 src/codegen/H/emit/bytes.h src/codegen/H/emit/value.h \
77 src/codegen/H/runtime/heap.h src/parser/H/core/parser.h \
88 src/parser/H/declarations/vars.h
99 src/codegen/H/strings/string_builtins.h:
1010 src/codegen/H/strings/string_alloc.h:
1111 src/codegen/H/emit/emit.h:
1212 src/codegen/H/expressions/expr.h:
13-src/lexer/H/lexer.h:
13+../front/src/ir/H/ir_lex.h:
1414 src/codegen/H/emit/bytes.h:
1515 src/codegen/H/emit/value.h:
1616 src/codegen/H/runtime/heap.h:

hearth/kiln/src/codegen/D/strings/strings.dmodified

+2−2
@@ -4,7 +4,7 @@ src/codegen/O/strings/strings.o: src/codegen/C/strings/strings.c \
44 src/codegen/H/emit/value.h src/codegen/H/runtime/heap.h \
55 src/codegen/H/emit/bytes.h src/codegen/H/strings/string_alloc.h \
66 src/codegen/H/runtime/errors.h src/codegen/H/emit/layout.h \
7- src/parser/H/core/parser.h src/lexer/H/lexer.h
7+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h
88 src/codegen/H/strings/strings.h:
99 src/codegen/H/emit/emit_internal.h:
1010 src/codegen/H/emit/emit.h:
@@ -16,4 +16,4 @@ src/codegen/H/strings/string_alloc.h:
1616 src/codegen/H/runtime/errors.h:
1717 src/codegen/H/emit/layout.h:
1818 src/parser/H/core/parser.h:
19-src/lexer/H/lexer.h:
19+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/D/strings/substring_builtin.dmodified

+2−2
@@ -2,14 +2,14 @@ src/codegen/O/strings/substring_builtin.o: \
22 src/codegen/C/strings/substring_builtin.c \
33 src/codegen/H/strings/string_builtins.h \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/emit/emit.h \
5- src/codegen/H/expressions/expr.h src/lexer/H/lexer.h \
5+ src/codegen/H/expressions/expr.h ../front/src/ir/H/ir_lex.h \
66 src/codegen/H/emit/bytes.h src/codegen/H/emit/emit_sse.h \
77 src/codegen/H/emit/value.h src/parser/H/core/parser.h
88 src/codegen/H/strings/string_builtins.h:
99 src/codegen/H/strings/string_alloc.h:
1010 src/codegen/H/emit/emit.h:
1111 src/codegen/H/expressions/expr.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1313 src/codegen/H/emit/bytes.h:
1414 src/codegen/H/emit/emit_sse.h:
1515 src/codegen/H/emit/value.h:

hearth/kiln/src/codegen/D/strings/trim_builtin.dmodified

+2−2
@@ -3,11 +3,11 @@ src/codegen/O/strings/trim_builtin.o: \
33 src/codegen/H/strings/string_builtins.h \
44 src/codegen/H/strings/string_alloc.h src/codegen/H/emit/emit.h \
55 src/codegen/H/emit/bytes.h src/codegen/H/emit/value.h \
6- src/parser/H/core/parser.h src/lexer/H/lexer.h
6+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h
77 src/codegen/H/strings/string_builtins.h:
88 src/codegen/H/strings/string_alloc.h:
99 src/codegen/H/emit/emit.h:
1010 src/codegen/H/emit/bytes.h:
1111 src/codegen/H/emit/value.h:
1212 src/parser/H/core/parser.h:
13-src/lexer/H/lexer.h:
13+../front/src/ir/H/ir_lex.h:

hearth/kiln/src/codegen/H/expressions/expr.hmodified

+1−1
@@ -1,6 +1,6 @@
11 #ifndef KILN_CODEGEN_EXPR_H
22 #define KILN_CODEGEN_EXPR_H
3-#include "lexer/H/lexer.h"
3+#include "ir/H/ir_lex.h"
44
55 // Parses one expression and emits real x86-64 code for it via the
66 // shared `code` buffer (see parser/H/core/parser.h) -- consumes tokens

hearth/kiln/src/lexer/C/lexer.cremoved

+0−237
@@ -1,237 +0,0 @@
1-#include <string.h>
2-#include <ctype.h>
3-#include "lexer/H/lexer.h"
4-#include "lexer/H/lexer_import.h"
5-
6-// lex_* (not the bare start/current/line these had as file-static
7-// before) -- shared with lexer_import.c now, and a plain `current` would
8-// collide with parser.h's own global `Token current` at link time.
9-const char *lex_start;
10-const char *lex_current;
11-int lex_line;
12-
13-void lexer_init(const char *source) {
14- lex_start = source;
15- lex_current = source;
16- lex_line = 1;
17-}
18-
19-int is_at_end(void) { return *lex_current == '\0'; }
20-char advance(void) { lex_current++; return lex_current[-1]; }
21-char peek(void) { return *lex_current; }
22-static char peek_next(void) { if (is_at_end()) return '\0'; return lex_current[1]; }
23-
24-static int match(char expected) {
25- if (is_at_end()) return 0;
26- if (*lex_current != expected) return 0;
27- lex_current++;
28- return 1;
29-}
30-
31-static void skip_whitespace(void) {
32- for (;;) {
33- char c = peek();
34- switch (c) {
35- case ' ': case '\r': case '\t':
36- advance();
37- break;
38- case '\n':
39- lex_line++;
40- advance();
41- break;
42- case '/':
43- if (peek_next() == '/') {
44- while (peek() != '\n' && !is_at_end()) advance();
45- } else if (peek_next() == '*') {
46- advance(); advance(); // consume "/*"
47- // An unterminated block comment just runs to EOF
48- // rather than producing a lex error -- the same
49- // "good enough, not worth a signature change to
50- // skip_whitespace for" tradeoff line comments
51- // already make (a `//` with no trailing newline).
52- while (!is_at_end() && !(peek() == '*' && peek_next() == '/')) {
53- if (peek() == '\n') lex_line++;
54- advance();
55- }
56- if (!is_at_end()) { advance(); advance(); } // consume "*/"
57- } else {
58- return;
59- }
60- break;
61- default:
62- return;
63- }
64- }
65-}
66-
67-static Token make_token(TokenType type) {
68- Token token;
69- token.type = type;
70- token.start = lex_start;
71- token.length = (int)(lex_current - lex_start);
72- token.line = lex_line;
73- return token;
74-}
75-
76-Token error_token(const char *message) {
77- Token token;
78- token.type = TOKEN_ERROR;
79- token.start = message;
80- token.length = (int)strlen(message);
81- token.line = lex_line;
82- return token;
83-}
84-
85-// The lexer's only job here is to decide the token's BOUNDARIES --
86-// primary()'s strtod() call (real libc, running at compile time on the
87-// host, not codegen) does the actual conversion and natively understands
88-// hex ("0x1A") and scientific notation ("1e10", "1.5e-3") already; the
89-// lexer just has to not stop early and hand back a truncated token.
90-// Underscore digit separators (1_000_000) are the one thing strtod
91-// itself doesn't understand -- primary() strips those out of the token
92-// text before calling strtod, see codegen/C/expressions/expr.c.
93-static Token number(void) {
94- if (lex_start[0] == '0' && (peek() == 'x' || peek() == 'X')) {
95- advance(); // consume 'x'/'X'
96- while (isxdigit(peek()) || peek() == '_') advance();
97- return make_token(TOKEN_NUMBER);
98- }
99- while (isdigit(peek()) || peek() == '_') advance();
100- if (peek() == '.' && isdigit(peek_next())) {
101- advance(); // consume '.'
102- while (isdigit(peek()) || peek() == '_') advance();
103- }
104- if (peek() == 'e' || peek() == 'E') {
105- char after = peek_next();
106- if (isdigit(after) || after == '+' || after == '-') {
107- advance(); // consume 'e'/'E'
108- if (peek() == '+' || peek() == '-') advance();
109- while (isdigit(peek())) advance();
110- }
111- }
112- return make_token(TOKEN_NUMBER);
113-}
114-
115-static Token string_token(void) {
116- const char *content_start = lex_current;
117- while (peek() != '"' && !is_at_end()) {
118- if (peek() == '\\' && peek_next() != '\0') {
119- advance(); // skip the backslash
120- advance(); // skip the escaped character itself, so a \" doesn't end the string early
121- continue;
122- }
123- if (peek() == '\n') lex_line++;
124- advance();
125- }
126- if (is_at_end()) return error_token("unterminated string");
127-
128- int length = (int)(lex_current - content_start);
129- advance();
130-
131- Token token;
132- token.type = TOKEN_STRING;
133- token.start = content_start;
134- token.length = length;
135- token.line = lex_line;
136- return token;
137-}
138-
139-static Token identifier(void) {
140- while (isalnum(peek()) || peek() == '_') advance();
141-
142- int length = (int)(lex_current - lex_start);
143- if (length == 3 && strncmp(lex_start, "say", 3) == 0) return make_token(TOKEN_SAY);
144- if (length == 5 && strncmp(lex_start, "local", 5) == 0) return make_token(TOKEN_LOCAL);
145- if (length == 5 && strncmp(lex_start, "given", 5) == 0) return make_token(TOKEN_GIVEN);
146- if (length == 9 && strncmp(lex_start, "otherwise", 9) == 0) return make_token(TOKEN_OTHERWISE);
147- if (length == 6 && strncmp(lex_start, "during", 6) == 0) return make_token(TOKEN_DURING);
148- if (length == 4 && strncmp(lex_start, "each", 4) == 0) return make_token(TOKEN_EACH);
149- if (length == 2 && strncmp(lex_start, "in", 2) == 0) return make_token(TOKEN_IN);
150- if (length == 5 && strncmp(lex_start, "forge", 5) == 0) return make_token(TOKEN_FORGE);
151- if (length == 5 && strncmp(lex_start, "yield", 5) == 0) return make_token(TOKEN_YIELD);
152- if (length == 7 && strncmp(lex_start, "attempt", 7) == 0) return make_token(TOKEN_ATTEMPT);
153- if (length == 6 && strncmp(lex_start, "handle", 6) == 0) return make_token(TOKEN_HANDLE);
154- if (length == 5 && strncmp(lex_start, "raise", 5) == 0) return make_token(TOKEN_RAISE);
155- if (length == 4 && strncmp(lex_start, "stop", 4) == 0) return make_token(TOKEN_STOP);
156- if (length == 4 && strncmp(lex_start, "next", 4) == 0) return make_token(TOKEN_NEXT);
157- if (length == 3 && strncmp(lex_start, "yes", 3) == 0) return make_token(TOKEN_YES);
158- if (length == 2 && strncmp(lex_start, "no", 2) == 0) return make_token(TOKEN_NO);
159- if (length == 4 && strncmp(lex_start, "none", 4) == 0) return make_token(TOKEN_NONE);
160- if (length == 3 && strncmp(lex_start, "and", 3) == 0) return make_token(TOKEN_AND);
161- if (length == 2 && strncmp(lex_start, "or", 2) == 0) return make_token(TOKEN_OR);
162- // "not" reuses TOKEN_BANG (unary logical negation) -- same meaning as
163- // the symbol it replaces, so unary()'s existing TOKEN_BANG handling in
164- // codegen/C/expressions/expr.c needs no change at all.
165- if (length == 3 && strncmp(lex_start, "not", 3) == 0) return make_token(TOKEN_BANG);
166-
167- return make_token(TOKEN_IDENTIFIER);
168-}
169-
170-Token lexer_next_token(void) {
171- skip_whitespace();
172- lex_start = lex_current;
173-
174- if (is_at_end()) return make_token(TOKEN_EOF);
175-
176- char c = advance();
177-
178- if (isdigit(c)) return number();
179- if (isalpha(c) || c == '_') return identifier();
180- if (c == '"') return string_token();
181-
182- switch (c) {
183- case ';': return make_token(TOKEN_SEMICOLON);
184- case ',': return make_token(TOKEN_COMMA);
185- case ':': return make_token(TOKEN_COLON);
186- case '?': return make_token(TOKEN_QUESTION);
187- case '+':
188- if (match('+')) return make_token(TOKEN_PLUS_PLUS);
189- return make_token(match('=') ? TOKEN_PLUS_EQUAL : TOKEN_PLUS);
190- case '-':
191- if (match('-')) return make_token(TOKEN_MINUS_MINUS);
192- return make_token(match('=') ? TOKEN_MINUS_EQUAL : TOKEN_MINUS);
193- case '*':
194- if (match('*')) return make_token(TOKEN_STAR_STAR);
195- return make_token(match('=') ? TOKEN_STAR_EQUAL : TOKEN_STAR);
196- case '/': return make_token(match('=') ? TOKEN_SLASH_EQUAL : TOKEN_SLASH);
197- case '%': return make_token(TOKEN_PERCENT);
198- case '(': return make_token(TOKEN_LPAREN);
199- case ')': return make_token(TOKEN_RPAREN);
200- case '{': return make_token(TOKEN_LBRACE);
201- case '}': return make_token(TOKEN_RBRACE);
202- case '[': return make_token(TOKEN_LBRACKET);
203- case ']': return make_token(TOKEN_RBRACKET);
204- case '=': return make_token(match('=') ? TOKEN_EQUAL_EQUAL : TOKEN_EQUAL);
205- // Bare '!' is no longer valid on its own -- logical negation is the
206- // 'not' keyword now (see identifier()). '!=' (inequality) stays
207- // symbolic either way.
208- case '!':
209- if (match('=')) return make_token(TOKEN_BANG_EQUAL);
210- return error_token("unexpected character");
211- case '<':
212- if (match('<')) return make_token(TOKEN_SHL);
213- return make_token(match('=') ? TOKEN_LESS_EQUAL : TOKEN_LESS);
214- case '>':
215- if (match('>')) return make_token(TOKEN_SHR);
216- return make_token(match('=') ? TOKEN_GREATER_EQUAL : TOKEN_GREATER);
217- // '&'/'|' are always the bitwise operators now -- 'and'/'or' are
218- // the only way to write the logical versions (see identifier()).
219- // This also means a literal '&&'/'||' in old-syntax source now
220- // lexes as two separate AMP/PIPE tokens rather than one fused one,
221- // consistent with the rest of today's renames replacing their old
222- // symbol outright rather than keeping it as an alias.
223- case '&': return make_token(TOKEN_AMP);
224- case '|': return make_token(TOKEN_PIPE);
225- case '^': return make_token(TOKEN_CARET);
226- case '~': return make_token(TOKEN_TILDE);
227- case '@':
228- if (strncmp(lex_current, "import", 6) == 0 && !(isalnum((unsigned char)lex_current[6]) || lex_current[6] == '_')) {
229- lex_current += 6;
230- return make_token(TOKEN_IMPORT);
231- }
232- return error_token("expected 'import' after '@'");
233- case '.': return make_token(TOKEN_DOT);
234- }
235-
236- return error_token("unexpected character");
237-}

hearth/kiln/src/lexer/C/lexer_import.cremoved

+0−37
@@ -1,37 +0,0 @@
1-#include "lexer/H/lexer_import.h"
2-
3-LexerState lexer_save_state(void) {
4- LexerState state;
5- state.start = lex_start;
6- state.current = lex_current;
7- state.line = lex_line;
8- return state;
9-}
10-
11-void lexer_restore_state(LexerState state) {
12- lex_start = state.start;
13- lex_current = state.current;
14- lex_line = state.line;
15-}
16-
17-// Called with the lexer's internal `current` pointer sitting immediately
18-// after the '<' the parser just confirmed (via current.type==TOKEN_LESS)
19-// WITHOUT calling advance_token() on it -- so `current` here still points
20-// at the first path character, untouched by normal tokenization. Scans
21-// raw bytes up to '>', consuming the '>' too, so the parser's next
22-// advance_token() call correctly picks up whatever follows it (';').
23-Token lexer_scan_import_path(void) {
24- const char *content_start = lex_current;
25- while (peek() != '>' && peek() != '\n' && !is_at_end()) advance();
26- if (peek() != '>') return error_token("unterminated import path (expected '>')");
27-
28- int length = (int)(lex_current - content_start);
29- advance(); // consume '>'
30-
31- Token token;
32- token.type = TOKEN_IMPORT_PATH;
33- token.start = content_start;
34- token.length = length;
35- token.line = lex_line;
36- return token;
37-}

hearth/kiln/src/lexer/D/lexer.dremoved

+0−4
@@ -1,4 +0,0 @@
1-src/lexer/O/lexer.o: src/lexer/C/lexer.c src/lexer/H/lexer.h \
2- src/lexer/H/lexer_import.h
3-src/lexer/H/lexer.h:
4-src/lexer/H/lexer_import.h:

hearth/kiln/src/lexer/D/lexer_import.dremoved

+0−4
@@ -1,4 +0,0 @@
1-src/lexer/O/lexer_import.o: src/lexer/C/lexer_import.c \
2- src/lexer/H/lexer_import.h src/lexer/H/lexer.h
3-src/lexer/H/lexer_import.h:
4-src/lexer/H/lexer.h:

hearth/kiln/src/lexer/H/lexer.hremoved

+0−102
@@ -1,102 +0,0 @@
1-#ifndef LEXER_H
2-#define LEXER_H
3-
4-typedef enum {
5- TOKEN_SAY,
6- TOKEN_LOCAL,
7- TOKEN_GIVEN,
8- TOKEN_OTHERWISE,
9- TOKEN_DURING,
10- TOKEN_EACH,
11- TOKEN_IN,
12- TOKEN_IMPORT,
13- TOKEN_FORGE,
14- TOKEN_YIELD,
15- TOKEN_ATTEMPT,
16- TOKEN_HANDLE,
17- TOKEN_RAISE,
18- TOKEN_STOP,
19- TOKEN_NEXT,
20- TOKEN_YES,
21- TOKEN_NO,
22- TOKEN_NONE,
23- TOKEN_IDENTIFIER,
24- TOKEN_STRING,
25- TOKEN_IMPORT_PATH,
26- TOKEN_EQUAL,
27- TOKEN_EQUAL_EQUAL,
28- TOKEN_BANG_EQUAL,
29- TOKEN_BANG,
30- TOKEN_AND,
31- TOKEN_OR,
32- TOKEN_LESS,
33- TOKEN_LESS_EQUAL,
34- TOKEN_GREATER,
35- TOKEN_GREATER_EQUAL,
36- TOKEN_PLUS,
37- TOKEN_MINUS,
38- TOKEN_STAR,
39- TOKEN_SLASH,
40- TOKEN_PERCENT,
41- TOKEN_LPAREN,
42- TOKEN_RPAREN,
43- TOKEN_LBRACE,
44- TOKEN_RBRACE,
45- TOKEN_LBRACKET,
46- TOKEN_RBRACKET,
47- TOKEN_COMMA,
48- TOKEN_COLON,
49- TOKEN_DOT,
50- TOKEN_QUESTION,
51- TOKEN_AMP,
52- TOKEN_PIPE,
53- TOKEN_CARET,
54- TOKEN_TILDE,
55- TOKEN_SHL,
56- TOKEN_SHR,
57- TOKEN_PLUS_EQUAL,
58- TOKEN_MINUS_EQUAL,
59- TOKEN_STAR_EQUAL,
60- TOKEN_SLASH_EQUAL,
61- TOKEN_PLUS_PLUS,
62- TOKEN_MINUS_MINUS,
63- TOKEN_STAR_STAR,
64- TOKEN_NUMBER,
65- TOKEN_SEMICOLON,
66- TOKEN_EOF,
67- TOKEN_ERROR
68-} TokenType;
69-
70-typedef struct {
71- TokenType type;
72- const char *start;
73- int length;
74- int line;
75-} Token;
76-
77-void lexer_init(const char *source);
78-Token lexer_next_token(void);
79-
80-// Saved lexer cursor position -- used by imports.c to recursively lex a
81-// different source buffer for an imported file, then resume exactly where
82-// the importing file's tokenizer left off (mirrors vars_save/restore's
83-// save-a-struct, recurse, restore pattern).
84-typedef struct {
85- const char *start;
86- const char *current;
87- int line;
88-} LexerState;
89-
90-LexerState lexer_save_state(void);
91-void lexer_restore_state(LexerState state);
92-
93-// Called by imports.c right after the parser has consumed a TOKEN_LESS
94-// that opened an `@import <...>` path. Scans raw characters (not through
95-// the normal keyword/operator rules -- a path like "./foo.ash" contains
96-// '.' and '/' which aren't otherwise valid outside this context) up to
97-// and INCLUDING the closing '>', and returns a token whose start/length
98-// cover just the path text (excluding both brackets). Errors (via the
99-// TOKEN_ERROR convention) on a newline or EOF before '>'.
100-Token lexer_scan_import_path(void);
101-
102-#endif

hearth/kiln/src/lexer/H/lexer_import.hremoved

+0−29
@@ -1,29 +0,0 @@
1-#ifndef KILN_LEXER_IMPORT_H
2-#define KILN_LEXER_IMPORT_H
3-#include "lexer/H/lexer.h"
4-
5-// Cross-file link between lexer.c (the tokenizer's cursor state and its
6-// low-level scan primitives) and lexer_import.c (state save/restore plus
7-// import-path scanning, split out here to keep lexer.c under the
8-// project's ~200-line guideline) -- not part of the public API. The
9-// public entry points the two files implement together
10-// (lexer_save_state/lexer_restore_state/lexer_scan_import_path) stay
11-// declared in lexer.h exactly as before, so callers outside the lexer
12-// directory don't need to change anything. Mirrors parser.c's split
13-// between parser.h (public surface) and parser_internal.h (private,
14-// cross-file plumbing).
15-//
16-// Named lex_* rather than the bare start/current/line: parser.h already
17-// declares its own global `Token current`, and since these now need
18-// external linkage to be shared across the two .c files, a second plain
19-// `current` global here would collide with it at link time.
20-extern const char *lex_start;
21-extern const char *lex_current;
22-extern int lex_line;
23-
24-int is_at_end(void);
25-char advance(void);
26-char peek(void);
27-Token error_token(const char *message);
28-
29-#endif

hearth/kiln/src/lexer/O/.gitkeepremoved

+0−0

No content changes. View the file on GitHub

hearth/kiln/src/parser/C/core/parser.cmodified

+17−13
@@ -7,7 +7,6 @@
77 #include "parser/H/declarations/module_state.h"
88 #include "parser/H/statements/loop_stack.h"
99 #include "parser/H/declarations/functions.h"
10-#include "parser/H/imports/imports.h"
1110 #include "parser/H/declarations/constants.h"
1211 #include "codegen/H/expressions/expr.h"
1312 #include "codegen/H/emit/emit_sse.h"
@@ -40,12 +39,10 @@ void expect(TokenType type, const char *message) {
4039 }
4140
4241 // statement() is shared between top-level parsing (compile_program's own
43-// loop, and imports.c's parse_imported_file_body()) and here, inside a
44-// forge/given/during/each/attempt body -- block_depth distinguishes the
45-// two so the "only forge/local at an imported file's top level" guard in
46-// statement() only fires for genuinely top-level statements, never for an
47-// ordinary `yield`/`given`/etc. nested inside an imported function's own
48-// body.
42+// loop) and here, inside a forge/given/during/each/attempt body --
43+// block_depth distinguishes the two so the "only forge/local at the unit's
44+// top level" guard in statement() only fires for genuinely top-level
45+// statements.
4946 static int block_depth = 0;
5047
5148 void block(void) {
@@ -380,9 +377,6 @@ static void next_statement(void) {
380377 // condition parens -- anything else is a parse error, per the project rule
381378 // that malformed input always fails cleanly)
382379 void statement(void) {
383- if (current.type == TOKEN_IMPORT) { import_statement(); return; }
384- imports_close_block();
385-
386380 const char *ns; int ns_len;
387381 get_import_namespace(&ns, &ns_len);
388382 if (ns_len > 0 && block_depth == 0 && current.type != TOKEN_FORGE && current.type != TOKEN_LOCAL) {
@@ -407,16 +401,22 @@ void statement(void) {
407401 if (current.type == TOKEN_NEXT) { next_statement(); return; }
408402 if (current.type == TOKEN_RAISE) { raise_statement(); return; }
409403 if (current.type == TOKEN_IDENTIFIER) { assignment_statement(); return; }
410- parse_error("expected 'say', 'local', 'given', 'during', 'forge', 'yield', 'attempt', 'each', 'stop', 'next', 'raise', '@import', or an assignment");
404+ parse_error("expected 'say', 'local', 'given', 'during', 'forge', 'yield', 'attempt', 'each', 'stop', 'next', 'raise', or an assignment");
411405 }
412406
413-void compile_program(const char *source, const char *source_path, CodeBuf *out) {
407+// The IR is one unit of top-level `forge` and `local` declarations (see
408+// ir/H/ir_lex.h) that lives in a single module namespace; the program runs
409+// by calling its `start` function. The lowering owns the unit, so there is no
410+// import machinery: only this one namespace exists.
411+#define IR_NAMESPACE "g"
412+
413+void compile_program(const char *source, CodeBuf *out) {
414414 code = out;
415415 code_init(code);
416+ set_import_namespace(IR_NAMESPACE, (int)strlen(IR_NAMESPACE));
416417 prescan_functions(source);
417418 lexer_init(source);
418419 advance_token();
419- imports_init(source_path);
420420
421421 // The kernel hands a freshly-started process RSP pointing at
422422 // [argc, argv[0], ..., NULL, envp...] -- this is the ONLY point in
@@ -450,5 +450,9 @@ void compile_program(const char *source, const char *source_path, CodeBuf *out)
450450
451451 while (current.type != TOKEN_EOF) statement();
452452 check_all_functions_defined();
453+ set_import_namespace(NULL, 0);
454+ KilnFunction *start = resolve_function(IR_NAMESPACE ".start", (int)strlen(IR_NAMESPACE ".start"));
455+ if (start == NULL) parse_error("program has no entry point");
456+ emit_call_back(code, start->code_offset);
453457 codegen_exit0(code);
454458 }

hearth/kiln/src/parser/C/declarations/functions.cmodified

+1−1
@@ -2,7 +2,7 @@
22 #include <stdio.h>
33 #include "parser/H/declarations/functions.h"
44 #include "parser/H/core/parser.h"
5-#include "lexer/H/lexer.h"
5+#include "ir/H/ir_lex.h"
66 #include "codegen/H/emit/emit.h"
77 #include "codegen/H/emit/layout.h"
88

hearth/kiln/src/parser/C/imports/import_paths.cremoved

+0−68
@@ -1,68 +0,0 @@
1-#define _XOPEN_SOURCE 700 // exposes realpath() and PATH_MAX under -std=c11
2-#include <string.h>
3-#include <stdio.h>
4-#include <stdlib.h>
5-#include "parser/H/imports/import_paths.h"
6-
7-void import_path_dirname(const char *path, char *out, int out_size) {
8- const char *slash = strrchr(path, '/');
9- if (!slash) { snprintf(out, (size_t)out_size, "."); return; }
10- int len = (int)(slash - path);
11- if (len >= out_size) len = out_size - 1;
12- memcpy(out, path, (size_t)len);
13- out[len] = '\0';
14-}
15-
16-void import_derive_namespace(const char *canonical_path, char *out, int out_size) {
17- const char *slash = strrchr(canonical_path, '/');
18- const char *base = slash ? slash + 1 : canonical_path;
19- int len = (int)strlen(base);
20- if (len > 4 && strcmp(base + len - 4, ".ash") == 0) len -= 4;
21- if (len >= out_size) len = out_size - 1;
22- memcpy(out, base, (size_t)len);
23- out[len] = '\0';
24-}
25-
26-static int is_relative_prefix(const char *raw, int len) {
27- if (len >= 2 && raw[0] == '.' && raw[1] == '/') return 1;
28- if (len >= 3 && raw[0] == '.' && raw[1] == '.' && raw[2] == '/') return 1;
29- return 0;
30-}
31-
32-int import_resolve_path(const char *raw_path, int raw_len,
33- const char *importing_file_dir,
34- const char *project_root_dir,
35- char *canonical_out,
36- char *message_out, int message_out_size) {
37- char candidate[PATH_MAX];
38-
39- if (is_relative_prefix(raw_path, raw_len)) {
40- if (raw_len < 4 || strncmp(raw_path + raw_len - 4, ".ash", 4) != 0) {
41- snprintf(message_out, (size_t)message_out_size, "relative import path must end in '.ash'");
42- return 0;
43- }
44- snprintf(candidate, sizeof(candidate), "%s/%.*s", importing_file_dir, raw_len, raw_path);
45- } else {
46- for (int i = 0; i < raw_len; i++) {
47- if (raw_path[i] == '.' || raw_path[i] == '/') {
48- snprintf(message_out, (size_t)message_out_size,
49- "library import name must not contain '.' or '/' (did you mean './%.*s'?)", raw_len, raw_path);
50- return 0;
51- }
52- }
53- // ash.libs/ (hand-written local libraries) wins first; a package
54- // installed by forgepack (see ideas/ash_modules.md) only gets
55- // tried if there's no local library shadowing the same name.
56- snprintf(candidate, sizeof(candidate), "%s/ash.libs/%.*s/%.*s.ash",
57- project_root_dir, raw_len, raw_path, raw_len, raw_path);
58- if (realpath(candidate, canonical_out) != NULL) return 1;
59- snprintf(candidate, sizeof(candidate), "%s/@ash-modules/%.*s/%.*s.ash",
60- project_root_dir, raw_len, raw_path, raw_len, raw_path);
61- }
62-
63- if (realpath(candidate, canonical_out) == NULL) {
64- snprintf(message_out, (size_t)message_out_size, "could not resolve '%.*s'", raw_len, raw_path);
65- return 0;
66- }
67- return 1;
68-}

hearth/kiln/src/parser/C/imports/imports.cremoved

+0−234
@@ -1,234 +0,0 @@
1-#define _XOPEN_SOURCE 700 // exposes realpath() and PATH_MAX under -std=c11
2-#include <string.h>
3-#include <stdio.h>
4-#include <stdlib.h>
5-#include <limits.h>
6-#include "parser/H/imports/imports.h"
7-#include "parser/H/imports/import_paths.h"
8-#include "parser/H/core/parser.h"
9-#include "parser/H/core/parser_internal.h"
10-#include "parser/H/declarations/functions.h"
11-#include "lexer/H/lexer.h"
12-#include "diagnostics/H/diagnostics.h"
13-
14-#define MAX_KILN_IMPORTS 16
15-#define MAX_KILN_IMPORT_DEPTH 8
16-
17-typedef struct {
18- char canonical_path[PATH_MAX];
19- char namespace_name[64];
20-} ImportedFile;
21-
22-static ImportedFile imported_files[MAX_KILN_IMPORTS];
23-static int imported_file_count = 0;
24-
25-static char resolving_stack[MAX_KILN_IMPORT_DEPTH][PATH_MAX];
26-static int resolving_depth = 0;
27-
28-static char project_root_dir[PATH_MAX];
29-static char current_file_dir[PATH_MAX];
30-
31-static int import_block_open = 1;
32-
33-void imports_init(const char *entry_file_path) {
34- char resolved[PATH_MAX];
35- if (realpath(entry_file_path, resolved) == NULL) parse_error("could not resolve entry file path");
36- import_path_dirname(resolved, project_root_dir, sizeof(project_root_dir));
37- size_t root_len = strlen(project_root_dir);
38- if (root_len >= sizeof(current_file_dir)) root_len = sizeof(current_file_dir) - 1;
39- memcpy(current_file_dir, project_root_dir, root_len);
40- current_file_dir[root_len] = '\0';
41- import_block_open = 1;
42-}
43-
44-void imports_close_block(void) {
45- import_block_open = 0;
46-}
47-
48-static ImportedFile *registry_find_by_path(const char *canonical) {
49- for (int i = 0; i < imported_file_count; i++) {
50- if (strcmp(imported_files[i].canonical_path, canonical) == 0) return &imported_files[i];
51- }
52- return NULL;
53-}
54-
55-static ImportedFile *registry_find_by_namespace(const char *ns) {
56- for (int i = 0; i < imported_file_count; i++) {
57- if (strcmp(imported_files[i].namespace_name, ns) == 0) return &imported_files[i];
58- }
59- return NULL;
60-}
61-
62-static int resolving_stack_contains(const char *canonical) {
63- for (int i = 0; i < resolving_depth; i++) {
64- if (strcmp(resolving_stack[i], canonical) == 0) return 1;
65- }
66- return 0;
67-}
68-
69-static void report_circular_import(const char *canonical) {
70- char msg[1024];
71- int off = snprintf(msg, sizeof(msg), "circular import detected: ");
72- for (int i = 0; i < resolving_depth; i++) {
73- off += snprintf(msg + off, sizeof(msg) - (size_t)off, "%s -> ", resolving_stack[i]);
74- if (off >= (int)sizeof(msg)) break;
75- }
76- snprintf(msg + off, sizeof(msg) - (size_t)off, "%s", canonical);
77- parse_error(msg);
78-}
79-
80-static char *read_import_file(const char *path) {
81- FILE *file = fopen(path, "rb");
82- if (!file) parse_error("could not open resolved import file");
83- fseek(file, 0L, SEEK_END);
84- long size = ftell(file);
85- rewind(file);
86- // Never freed -- an imported file's source buffer must outlive every
87- // later use site of its constants (see constants.c), which can be
88- // arbitrarily far ahead in the importing program. The compiler is a
89- // one-shot host process; leaking these until it exits is the same
90- // documented, intentional tradeoff kiln's own runtime heap allocator
91- // already makes (see missing.md's GC entry).
92- char *buffer = malloc((size_t)size + 1);
93- fread(buffer, 1, (size_t)size, file);
94- buffer[size] = '\0';
95- fclose(file);
96- return buffer;
97-}
98-
99-// The restricted top-level loop for a recursively-parsed imported file:
100-// identical shape to compile_program's own `while (... ) statement();`
101-// loop. statement() itself (parser.c) enforces the "only fn/let allowed"
102-// restriction by checking get_import_namespace()'s length -- see Task 4
103-// Step 6.
104-static void parse_imported_file_body(void) {
105- // Each imported file gets its OWN fresh import-block window: OPEN
106- // (not closed), so the imported file's own leading @import
107- // statements (if any -- e.g. a diamond-shaped or chained import) are
108- // allowed, exactly like a top-level file's. imports_close_block()
109- // would do the opposite (close it), which is wrong here -- statement()
110- // itself closes the window the moment it dispatches this file's own
111- // first non-import statement, same as it does for the entry file.
112- import_block_open = 1;
113- while (current.type != TOKEN_EOF) statement();
114-}
115-
116-void import_statement(void) {
117- if (!import_block_open) parse_error("@import statements must form a contiguous block at the top of the file");
118- advance_token(); // consume TOKEN_IMPORT ("@import")
119-
120- if (current.type != TOKEN_LESS) parse_error("expected '<' after '@import'");
121- Token path = lexer_scan_import_path();
122- if (path.type == TOKEN_ERROR) parse_error(path.start);
123- advance_token(); // current now holds whatever follows '>' (e.g. ';')
124-
125- char canonical[PATH_MAX];
126- char message[256];
127- if (!import_resolve_path(path.start, path.length, current_file_dir, project_root_dir,
128- canonical, message, sizeof(message))) {
129- parse_error(message);
130- }
131-
132- // Optional `as name`: the namespace this file's functions are called through,
133- // instead of the one derived from its file name.
134- char alias[64];
135- int has_alias = 0;
136- if (current.type == TOKEN_IDENTIFIER && current.length == 2 && strncmp(current.start, "as", 2) == 0) {
137- advance_token();
138- expect(TOKEN_IDENTIFIER, "expected a namespace name after 'as'");
139- if (previous.length >= (int)sizeof(alias)) parse_error("namespace name too long");
140- memcpy(alias, previous.start, (size_t)previous.length);
141- alias[previous.length] = '\0';
142- has_alias = 1;
143- }
144-
145- expect(TOKEN_SEMICOLON, "expected ';' after import path");
146-
147- // Cycle check MUST come before the dedup check: a file already in
148- // imported_files but STILL on resolving_stack is mid-parse (its
149- // registry entry was added before recursing, same as every entry
150- // here) -- that's a genuine cycle, not a finished diamond import.
151- // Checking the registry first would silently treat a still-parsing
152- // file as "already done" and swallow the cycle instead of reporting
153- // it. Only a registry hit with NO matching resolving_stack entry is
154- // a real, already-completed diamond dedup.
155- if (resolving_stack_contains(canonical)) report_circular_import(canonical);
156-
157- ImportedFile *existing = registry_find_by_path(canonical);
158- if (existing != NULL) return; // diamond dedup -- already fully processed, nothing more to do
159-
160- char ns[64];
161- import_derive_namespace(canonical, ns, sizeof(ns));
162- if (has_alias) { memcpy(ns, alias, strlen(alias) + 1); }
163-
164- ImportedFile *collision = registry_find_by_namespace(ns);
165- if (collision != NULL) {
166- // Sized to comfortably fit two PATH_MAX-bounded paths plus the
167- // namespace and surrounding literal text with no truncation, so
168- // GCC's -Wformat-truncation can prove this snprintf never overflows.
169- char msg[2 * PATH_MAX + 128];
170- snprintf(msg, sizeof(msg), "namespace '%s' already used by %s (colliding with %s)",
171- ns, collision->canonical_path, canonical);
172- parse_error(msg);
173- }
174-
175- if (imported_file_count >= MAX_KILN_IMPORTS) parse_error("too many imported files");
176- ImportedFile *entry = &imported_files[imported_file_count++];
177- size_t canonical_len = strlen(canonical);
178- if (canonical_len >= sizeof(entry->canonical_path)) canonical_len = sizeof(entry->canonical_path) - 1;
179- memcpy(entry->canonical_path, canonical, canonical_len);
180- entry->canonical_path[canonical_len] = '\0';
181- size_t ns_len = strlen(ns);
182- if (ns_len >= sizeof(entry->namespace_name)) ns_len = sizeof(entry->namespace_name) - 1;
183- memcpy(entry->namespace_name, ns, ns_len);
184- entry->namespace_name[ns_len] = '\0';
185-
186- if (resolving_depth >= MAX_KILN_IMPORT_DEPTH) parse_error("import nesting too deep");
187- size_t stack_len = strlen(canonical);
188- if (stack_len >= sizeof(resolving_stack[0])) stack_len = sizeof(resolving_stack[0]) - 1;
189- memcpy(resolving_stack[resolving_depth], canonical, stack_len);
190- resolving_stack[resolving_depth][stack_len] = '\0';
191- resolving_depth++;
192-
193- // --- Save everything the recursive parse of the imported file will
194- // clobber, exactly mirroring vars_save/each_depth_save/loop_depth_save's
195- // existing save-recurse-restore pattern (the C call stack gives
196- // correct nesting for free, same as those). ---
197- DiagnosticsSource saved_diag = diagnostics_save_source();
198- LexerState saved_lexer = lexer_save_state();
199- Token saved_current = current;
200- Token saved_previous = previous;
201- char saved_file_dir[PATH_MAX];
202- size_t saved_len = strlen(current_file_dir);
203- if (saved_len >= sizeof(saved_file_dir)) saved_len = sizeof(saved_file_dir) - 1;
204- memcpy(saved_file_dir, current_file_dir, saved_len);
205- saved_file_dir[saved_len] = '\0';
206- const char *saved_ns; int saved_ns_len;
207- get_import_namespace(&saved_ns, &saved_ns_len);
208- int saved_import_block_open = import_block_open;
209-
210- char *imported_source = read_import_file(canonical);
211- diagnostics_set_source(imported_source, canonical);
212- import_path_dirname(canonical, current_file_dir, sizeof(current_file_dir));
213- set_import_namespace(entry->namespace_name, (int)strlen(entry->namespace_name));
214-
215- prescan_functions(imported_source);
216- lexer_init(imported_source);
217- advance_token();
218- parse_imported_file_body();
219-
220- // --- Restore, in the reverse order, so the importing file's parse
221- // resumes exactly as if the @import line had been a no-op cursor-wise. ---
222- set_import_namespace(saved_ns, saved_ns_len);
223- size_t restore_len = strlen(saved_file_dir);
224- if (restore_len >= sizeof(current_file_dir)) restore_len = sizeof(current_file_dir) - 1;
225- memcpy(current_file_dir, saved_file_dir, restore_len);
226- current_file_dir[restore_len] = '\0';
227- lexer_restore_state(saved_lexer);
228- diagnostics_restore_source(saved_diag);
229- current = saved_current;
230- previous = saved_previous;
231- import_block_open = saved_import_block_open;
232-
233- resolving_depth--;
234-}

hearth/kiln/src/parser/D/core/parser.dmodified

+5−5
@@ -1,9 +1,10 @@
11 src/parser/O/core/parser.o: src/parser/C/core/parser.c \
2- src/parser/H/core/parser.h src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
3- src/parser/H/core/parser_internal.h src/parser/H/declarations/vars.h \
2+ src/parser/H/core/parser.h ../front/src/ir/H/ir_lex.h \
3+ src/codegen/H/emit/emit.h src/parser/H/core/parser_internal.h \
4+ src/parser/H/declarations/vars.h \
45 src/parser/H/declarations/module_state.h \
56 src/parser/H/statements/loop_stack.h \
6- src/parser/H/declarations/functions.h src/parser/H/imports/imports.h \
7+ src/parser/H/declarations/functions.h \
78 src/parser/H/declarations/constants.h src/codegen/H/expressions/expr.h \
89 src/codegen/H/emit/emit_sse.h src/codegen/H/emit/value.h \
910 src/codegen/H/runtime/heap.h src/codegen/H/emit/bytes.h \
@@ -13,14 +14,13 @@ src/parser/O/core/parser.o: src/parser/C/core/parser.c \
1314 src/elf/H/elf_writer.h src/codegen/H/emit/runtime_layout.h \
1415 src/app/H/target.h
1516 src/parser/H/core/parser.h:
16-src/lexer/H/lexer.h:
17+../front/src/ir/H/ir_lex.h:
1718 src/codegen/H/emit/emit.h:
1819 src/parser/H/core/parser_internal.h:
1920 src/parser/H/declarations/vars.h:
2021 src/parser/H/declarations/module_state.h:
2122 src/parser/H/statements/loop_stack.h:
2223 src/parser/H/declarations/functions.h:
23-src/parser/H/imports/imports.h:
2424 src/parser/H/declarations/constants.h:
2525 src/codegen/H/expressions/expr.h:
2626 src/codegen/H/emit/emit_sse.h:

hearth/kiln/src/parser/D/declarations/constants.dmodified

+3−3
@@ -1,11 +1,11 @@
11 src/parser/O/declarations/constants.o: \
22 src/parser/C/declarations/constants.c \
33 src/parser/H/declarations/constants.h src/parser/H/core/parser.h \
4- src/lexer/H/lexer.h src/codegen/H/emit/emit.h src/codegen/H/emit/value.h \
5- src/codegen/H/strings/strings.h
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
5+ src/codegen/H/emit/value.h src/codegen/H/strings/strings.h
66 src/parser/H/declarations/constants.h:
77 src/parser/H/core/parser.h:
8-src/lexer/H/lexer.h:
8+../front/src/ir/H/ir_lex.h:
99 src/codegen/H/emit/emit.h:
1010 src/codegen/H/emit/value.h:
1111 src/codegen/H/strings/strings.h:

hearth/kiln/src/parser/D/declarations/functions.dmodified

+2−2
@@ -1,10 +1,10 @@
11 src/parser/O/declarations/functions.o: \
22 src/parser/C/declarations/functions.c \
33 src/parser/H/declarations/functions.h src/parser/H/core/parser.h \
4- src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
55 src/codegen/H/emit/layout.h
66 src/parser/H/declarations/functions.h:
77 src/parser/H/core/parser.h:
8-src/lexer/H/lexer.h:
8+../front/src/ir/H/ir_lex.h:
99 src/codegen/H/emit/emit.h:
1010 src/codegen/H/emit/layout.h:

hearth/kiln/src/parser/D/declarations/module_state.dmodified

+2−2
@@ -3,13 +3,13 @@ src/parser/O/declarations/module_state.o: \
33 src/parser/H/declarations/module_state.h \
44 src/parser/H/declarations/functions.h \
55 src/parser/H/declarations/constants.h src/parser/H/core/parser.h \
6- src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
6+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
77 src/codegen/H/emit/layout.h src/codegen/H/emit/runtime_layout.h
88 src/parser/H/declarations/module_state.h:
99 src/parser/H/declarations/functions.h:
1010 src/parser/H/declarations/constants.h:
1111 src/parser/H/core/parser.h:
12-src/lexer/H/lexer.h:
12+../front/src/ir/H/ir_lex.h:
1313 src/codegen/H/emit/emit.h:
1414 src/codegen/H/emit/layout.h:
1515 src/codegen/H/emit/runtime_layout.h:

hearth/kiln/src/parser/D/declarations/vars.dmodified

+2−2
@@ -1,7 +1,7 @@
11 src/parser/O/declarations/vars.o: src/parser/C/declarations/vars.c \
22 src/parser/H/declarations/vars.h src/parser/H/core/parser.h \
3- src/lexer/H/lexer.h src/codegen/H/emit/emit.h
3+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h
44 src/parser/H/declarations/vars.h:
55 src/parser/H/core/parser.h:
6-src/lexer/H/lexer.h:
6+../front/src/ir/H/ir_lex.h:
77 src/codegen/H/emit/emit.h:

hearth/kiln/src/parser/D/imports/import_paths.dremoved

+0−3
@@ -1,3 +0,0 @@
1-src/parser/O/imports/import_paths.o: src/parser/C/imports/import_paths.c \
2- src/parser/H/imports/import_paths.h
3-src/parser/H/imports/import_paths.h:

hearth/kiln/src/parser/D/imports/imports.dremoved

+0−13
@@ -1,13 +0,0 @@
1-src/parser/O/imports/imports.o: src/parser/C/imports/imports.c \
2- src/parser/H/imports/imports.h src/parser/H/imports/import_paths.h \
3- src/parser/H/core/parser.h src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
4- src/parser/H/core/parser_internal.h \
5- src/parser/H/declarations/functions.h src/diagnostics/H/diagnostics.h
6-src/parser/H/imports/imports.h:
7-src/parser/H/imports/import_paths.h:
8-src/parser/H/core/parser.h:
9-src/lexer/H/lexer.h:
10-src/codegen/H/emit/emit.h:
11-src/parser/H/core/parser_internal.h:
12-src/parser/H/declarations/functions.h:
13-src/diagnostics/H/diagnostics.h:

hearth/kiln/src/parser/D/statements/attempt_handle.dmodified

+2−2
@@ -1,11 +1,11 @@
11 src/parser/O/statements/attempt_handle.o: \
22 src/parser/C/statements/attempt_handle.c src/parser/H/core/parser.h \
3- src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
3+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
44 src/parser/H/core/parser_internal.h src/parser/H/declarations/vars.h \
55 src/parser/H/statements/loop_stack.h src/codegen/H/runtime/errors.h \
66 src/codegen/H/emit/layout.h src/codegen/H/emit/runtime_layout.h
77 src/parser/H/core/parser.h:
8-src/lexer/H/lexer.h:
8+../front/src/ir/H/ir_lex.h:
99 src/codegen/H/emit/emit.h:
1010 src/parser/H/core/parser_internal.h:
1111 src/parser/H/declarations/vars.h:

hearth/kiln/src/parser/D/statements/each_loop.dmodified

+2−2
@@ -1,11 +1,11 @@
11 src/parser/O/statements/each_loop.o: src/parser/C/statements/each_loop.c \
22 src/parser/H/statements/each_loop.h src/parser/H/core/parser.h \
3- src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
3+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
44 src/parser/H/core/parser_internal.h src/parser/H/declarations/vars.h \
55 src/parser/H/statements/loop_stack.h src/codegen/H/expressions/expr.h
66 src/parser/H/statements/each_loop.h:
77 src/parser/H/core/parser.h:
8-src/lexer/H/lexer.h:
8+../front/src/ir/H/ir_lex.h:
99 src/codegen/H/emit/emit.h:
1010 src/parser/H/core/parser_internal.h:
1111 src/parser/H/declarations/vars.h:

hearth/kiln/src/parser/D/statements/loop_stack.dmodified

+2−2
@@ -1,8 +1,8 @@
11 src/parser/O/statements/loop_stack.o: \
22 src/parser/C/statements/loop_stack.c \
33 src/parser/H/statements/loop_stack.h src/parser/H/core/parser.h \
4- src/lexer/H/lexer.h src/codegen/H/emit/emit.h
4+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h
55 src/parser/H/statements/loop_stack.h:
66 src/parser/H/core/parser.h:
7-src/lexer/H/lexer.h:
7+../front/src/ir/H/ir_lex.h:
88 src/codegen/H/emit/emit.h:

hearth/kiln/src/parser/D/statements/parser_control.dmodified

+2−2
@@ -1,13 +1,13 @@
11 src/parser/O/statements/parser_control.o: \
22 src/parser/C/statements/parser_control.c src/parser/H/core/parser.h \
3- src/lexer/H/lexer.h src/codegen/H/emit/emit.h \
3+ ../front/src/ir/H/ir_lex.h src/codegen/H/emit/emit.h \
44 src/parser/H/core/parser_internal.h src/parser/H/declarations/vars.h \
55 src/parser/H/declarations/functions.h \
66 src/parser/H/statements/each_loop.h src/parser/H/statements/loop_stack.h \
77 src/codegen/H/expressions/expr.h src/codegen/H/emit/emit_sse.h \
88 src/codegen/H/emit/value.h
99 src/parser/H/core/parser.h:
10-src/lexer/H/lexer.h:
10+../front/src/ir/H/ir_lex.h:
1111 src/codegen/H/emit/emit.h:
1212 src/parser/H/core/parser_internal.h:
1313 src/parser/H/declarations/vars.h:

hearth/kiln/src/parser/H/core/parser.hmodified

+4−6
@@ -1,6 +1,6 @@
11 #ifndef KILN_PARSER_H
22 #define KILN_PARSER_H
3-#include "lexer/H/lexer.h"
3+#include "ir/H/ir_lex.h"
44 #include "codegen/H/emit/emit.h"
55
66 // Shared parser state, read by codegen/C/expressions/expr.c as well as parser.c --
@@ -14,10 +14,8 @@ void advance_token(void);
1414 void expect(TokenType type, const char *message);
1515 void parse_error(const char *message) __attribute__((noreturn));
1616
17-// Parses the whole program (milestone 1: a sequence of `print <expr>;`
18-// statements) and emits machine code for it into `out`, single-pass --
19-// parsing and codegen happen together, same shape ashvm's compiler uses,
20-// no separate AST.
21-void compile_program(const char *source, const char *source_path, CodeBuf *out);
17+// Compiles the internal IR unit produced by hearth/front (jdriver) and emits machine code for it
18+// into `out`, single-pass -- parsing and codegen happen together, no separate AST.
19+void compile_program(const char *source, CodeBuf *out);
2220
2321 #endif

hearth/kiln/src/parser/H/core/parser_internal.hmodified

+0−6
@@ -12,12 +12,6 @@ void forge_statement(void);
1212 void attempt_statement(void);
1313 void each_statement(void);
1414
15-// statement() itself (parser.c's dispatcher) also needs to be callable
16-// from imports.c's parse_imported_file_body(), which drives the same
17-// top-level "while not EOF, parse a statement" loop for a recursively
18-// parsed imported file -- so it's declared here rather than staying
19-// static to parser.c.
2015 void statement(void);
21-void import_statement(void);
2216
2317 #endif

hearth/kiln/src/parser/H/imports/import_paths.hremoved

+0−39
@@ -1,39 +0,0 @@
1-#ifndef KILN_IMPORT_PATHS_H
2-#define KILN_IMPORT_PATHS_H
3-#include <limits.h>
4-
5-// Resolves the raw text inside `@import <...>` to a canonicalized
6-// (realpath()'d) absolute filesystem path.
7-//
8-// raw_path/raw_len: the text between '<' and '>', exactly as scanned by
9-// lexer_scan_import_path (NOT null-terminated -- callers must use len).
10-// importing_file_dir: directory of the file containing this @import
11-// statement (relative imports resolve against this).
12-// project_root_dir: directory of the entry .ash file passed on the
13-// command line (library imports resolve against this, regardless of
14-// how deeply nested the importing file is).
15-// canonical_out: buffer of at least PATH_MAX bytes.
16-//
17-// Returns 1 and fills canonical_out on success. Returns 0 on failure
18-// (message_out is filled with a short human-readable reason, e.g.
19-// "could not resolve '<path>'" or "library import name must not contain
20-// '.' or '/'" -- callers pass this straight into parse_error).
21-int import_resolve_path(const char *raw_path, int raw_len,
22- const char *importing_file_dir,
23- const char *project_root_dir,
24- char *canonical_out,
25- char *message_out, int message_out_size);
26-
27-// Derives the auto-namespace for a resolved canonical path: the file's
28-// own basename with the trailing ".ash" stripped. Works uniformly for
29-// both relative and library imports because library entry files are
30-// required to be named "<libname>/<libname>.ash" -- the folder name and
31-// the basename-minus-extension are always identical by construction.
32-void import_derive_namespace(const char *canonical_path, char *out, int out_size);
33-
34-// Directory-of-a-path helper (hand-rolled, not libgen.h's dirname(),
35-// which mutates its input and reuses a static buffer across calls --
36-// both a bad fit here). Writes "." if path has no '/'.
37-void import_path_dirname(const char *path, char *out, int out_size);
38-
39-#endif

hearth/kiln/src/parser/H/imports/imports.hremoved

+0−23
@@ -1,23 +0,0 @@
1-#ifndef KILN_IMPORTS_H
2-#define KILN_IMPORTS_H
3-
4-// Called once, at the very start of compile_program, before the main
5-// parse loop -- establishes the entry file's own directory as the
6-// project root that library imports (ash.libs/) resolve against for the
7-// entire compile, no matter how deeply nested a later import is.
8-void imports_init(const char *entry_file_path);
9-
10-// Parses one `@import <path>;` statement. Assumes statement()'s
11-// dispatcher has NOT yet consumed the TOKEN_IMPORT (this function does
12-// that itself, matching local_statement()'s own convention).
13-void import_statement(void);
14-
15-// Called by statement() on every non-import statement dispatch. No-op
16-// after the first call in a given file's top-level parse -- marks that
17-// file's "imports must be a contiguous block at the top" window as
18-// closed, so a later @import in the SAME file is a compile error. Reset
19-// automatically on entry to each recursively-parsed imported file (their
20-// own import block starts fresh).
21-void imports_close_block(void);
22-
23-#endif