2026-05-03 21:45:29 +03:00
|
|
|
#
|
|
|
|
|
# Blaise — An Object Pascal Compiler
|
|
|
|
|
# Copyright (c) 2026 Graeme Geldenhuys
|
|
|
|
|
# SPDX-License-Identifier: Apache-2.0 WITH Swift-exception
|
|
|
|
|
# Licensed under the Apache License v2.0 with Runtime Library Exception.
|
|
|
|
|
# See LICENSE file in the project root for full license terms.
|
|
|
|
|
#
|
2026-06-04 01:49:29 +03:00
|
|
|
# Each Pascal unit is compiled directly via Blaise's unit-as-top-level
|
|
|
|
|
# mode (project_unit_as_toplevel, 2026-05-24): a single
|
|
|
|
|
# `blaise --source X.pas --output X.o` invocation runs qbe + cc -c
|
|
|
|
|
# + objcopy-embed in one step. No build-driver shims, no IR-strip
|
|
|
|
|
# sed pipelines, no intermediate .ssa/.s files needed.
|
2026-05-22 17:39:08 +03:00
|
|
|
SHELL = /bin/bash
|
|
|
|
|
|
Add Phase 2: record/class types, ARC strings, RTL stubs, and grammar doc
Symbol table:
- Added tyClass kind and NewClassType factory; TRecordTypeDesc now
accepts an optional kind parameter so records and classes share the
same descriptor with distinct semantics.
Semantic analyser:
- AnalyseTypeDecls runs before PushScope so type symbols land in global
scope and survive PopScope.
- Handles TRecordTypeDef and TClassTypeDef; sets IsConstructorCall on
TypeName.Create expressions and IsClassAccess on class-variable field
access and assignment nodes.
Code generator (QBE IR):
- Class variables: 8-byte pointer slot, zeroed on entry.
- Constructor calls: malloc(sizeof fields), store pointer.
- Class field access/write: load pointer, add field offset, load/store.
- ARC string assignment: AddRef new value, Release old value, then store.
- Block exit: Release every string variable in scope (EmitStringCleanup).
Lexer / Parser / AST:
- Added tkClass keyword and ParseClassDef; FieldDecl parsing refactored
into ParseFieldDecl(AFields) shared by both record and class.
- AST gains TClassTypeDef, and IsConstructorCall/IsClassAccess flags on
TFieldAccessExpr and TFieldAssignment.
RTL:
- blaise_arc.c: Phase 2 no-op stubs for _StringAddRef / _StringRelease.
- rtl/Makefile: builds blaise_rtl.a; `make install` copies it next to
the compiler binary for automatic discovery by FindRTL.
- Blaise.pas driver: FindRTL checks BLAISE_RTL env var then binary dir;
links the RTL archive when present.
Tests:
- 180 unit tests (records ×23, classes ×22, ARC ×9, codegen ×9, …).
- 4 end-to-end integration tests in tests/integration/test_arc_strings.sh
covering string assignment, two-var cleanup, reassignment cycle, and
empty-program linkage.
Docs:
- design.adoc updated with Phase 2 implementation status table.
- docs/grammar.ebnf: new authoritative EBNF grammar for the Blaise
language as implemented, including ARC semantic annotations.
2026-04-20 21:04:12 +03:00
|
|
|
CC = gcc
|
|
|
|
|
CFLAGS = -O2 -Wall -Wextra -std=c11
|
|
|
|
|
|
2026-05-01 16:42:29 +03:00
|
|
|
SRC_DIR = src/main/c
|
|
|
|
|
PAS_SRC_DIR = src/main/pascal
|
refactor(runtime): replace blaise_exc.c with Pascal + x86_64 assembly
Port all exception frame management, type identity, and runtime check
functions from C to pure Pascal (blaise_exc.pas). Replace libc
setjmp/longjmp with a minimal custom implementation in x86_64 assembly
(blaise_setjmp_x86_64.s, ~40 lines) that saves only the 8 callee-saved
registers (64-byte jmp_buf vs libc's 200-byte one).
This eliminates the last C source file from the runtime build. The only
non-Pascal code in the runtime is now the assembly setjmp stub.
Changes:
- runtime/src/main/asm/blaise_setjmp_x86_64.s: _blaise_setjmp/_blaise_longjmp
- runtime/src/main/pascal/blaise_exc.pas: _PushExcFrame, _PopExcFrame,
_Raise, _Reraise, _CurrentException, _CurrentExceptionMessage,
_IsInstance, _ImplementsInterface, _GetItab, _Raise_InvalidCast,
_CheckNil — all ported from blaise_exc.c
- uCodeGenQBE.pas: emit call $_blaise_setjmp instead of call $setjmp
- cp.test.exceptions.pas: IR assertion updated for new symbol name
- runtime/Makefile: assembly rule, Pascal blaise_exc build, C rules removed
- .gitignore: whitelist runtime/src/main/asm/*.s
- runtime/src/main/c/blaise_exc.c: deleted
2083 tests pass, fixpoint verified (stage-3/stage-4).
2026-05-21 03:01:08 +03:00
|
|
|
ASM_DIR = src/main/asm
|
2026-05-01 16:42:29 +03:00
|
|
|
OBJ_DIR = target
|
|
|
|
|
LIB = $(OBJ_DIR)/blaise_rtl.a
|
Add Phase 2: record/class types, ARC strings, RTL stubs, and grammar doc
Symbol table:
- Added tyClass kind and NewClassType factory; TRecordTypeDesc now
accepts an optional kind parameter so records and classes share the
same descriptor with distinct semantics.
Semantic analyser:
- AnalyseTypeDecls runs before PushScope so type symbols land in global
scope and survive PopScope.
- Handles TRecordTypeDef and TClassTypeDef; sets IsConstructorCall on
TypeName.Create expressions and IsClassAccess on class-variable field
access and assignment nodes.
Code generator (QBE IR):
- Class variables: 8-byte pointer slot, zeroed on entry.
- Constructor calls: malloc(sizeof fields), store pointer.
- Class field access/write: load pointer, add field offset, load/store.
- ARC string assignment: AddRef new value, Release old value, then store.
- Block exit: Release every string variable in scope (EmitStringCleanup).
Lexer / Parser / AST:
- Added tkClass keyword and ParseClassDef; FieldDecl parsing refactored
into ParseFieldDecl(AFields) shared by both record and class.
- AST gains TClassTypeDef, and IsConstructorCall/IsClassAccess flags on
TFieldAccessExpr and TFieldAssignment.
RTL:
- blaise_arc.c: Phase 2 no-op stubs for _StringAddRef / _StringRelease.
- rtl/Makefile: builds blaise_rtl.a; `make install` copies it next to
the compiler binary for automatic discovery by FindRTL.
- Blaise.pas driver: FindRTL checks BLAISE_RTL env var then binary dir;
links the RTL archive when present.
Tests:
- 180 unit tests (records ×23, classes ×22, ARC ×9, codegen ×9, …).
- 4 end-to-end integration tests in tests/integration/test_arc_strings.sh
covering string assignment, two-var cleanup, reassignment cycle, and
empty-program linkage.
Docs:
- design.adoc updated with Phase 2 implementation status table.
- docs/grammar.ebnf: new authoritative EBNF grammar for the Blaise
language as implemented, including ARC semantic annotations.
2026-04-20 21:04:12 +03:00
|
|
|
|
|
|
|
|
# Where the compiler binary lives — install copies the RTL there so the
|
|
|
|
|
# driver finds it automatically next to itself.
|
2026-04-24 19:42:54 +03:00
|
|
|
COMPILER_BIN = ../compiler/target
|
2026-05-01 16:42:29 +03:00
|
|
|
BLAISE = $(COMPILER_BIN)/blaise
|
2026-06-20 04:04:58 +03:00
|
|
|
# This Makefile IS a hand-managed separate-compilation system: it compiles each
|
|
|
|
|
# RTL unit to its own object and archives an explicit object list. The
|
|
|
|
|
# compiler's own incremental mode (now the default) would, on top of that, write
|
|
|
|
|
# per-dependency side-effect .o files next to each output and skip inlining a
|
|
|
|
|
# used unit's bodies — but those side-effect objects are not in the archive's
|
|
|
|
|
# object list, so a cross-unit symbol (e.g. typeinfo_TRtlPlatform, referenced by
|
|
|
|
|
# the derived TRtlPlatformPosix in another unit) ends up undefined at link.
|
|
|
|
|
# Force whole-program compilation per unit so every unit object is self-contained.
|
|
|
|
|
BLAISE_FLAGS = --no-incremental
|
Add Phase 2: record/class types, ARC strings, RTL stubs, and grammar doc
Symbol table:
- Added tyClass kind and NewClassType factory; TRecordTypeDesc now
accepts an optional kind parameter so records and classes share the
same descriptor with distinct semantics.
Semantic analyser:
- AnalyseTypeDecls runs before PushScope so type symbols land in global
scope and survive PopScope.
- Handles TRecordTypeDef and TClassTypeDef; sets IsConstructorCall on
TypeName.Create expressions and IsClassAccess on class-variable field
access and assignment nodes.
Code generator (QBE IR):
- Class variables: 8-byte pointer slot, zeroed on entry.
- Constructor calls: malloc(sizeof fields), store pointer.
- Class field access/write: load pointer, add field offset, load/store.
- ARC string assignment: AddRef new value, Release old value, then store.
- Block exit: Release every string variable in scope (EmitStringCleanup).
Lexer / Parser / AST:
- Added tkClass keyword and ParseClassDef; FieldDecl parsing refactored
into ParseFieldDecl(AFields) shared by both record and class.
- AST gains TClassTypeDef, and IsConstructorCall/IsClassAccess flags on
TFieldAccessExpr and TFieldAssignment.
RTL:
- blaise_arc.c: Phase 2 no-op stubs for _StringAddRef / _StringRelease.
- rtl/Makefile: builds blaise_rtl.a; `make install` copies it next to
the compiler binary for automatic discovery by FindRTL.
- Blaise.pas driver: FindRTL checks BLAISE_RTL env var then binary dir;
links the RTL archive when present.
Tests:
- 180 unit tests (records ×23, classes ×22, ARC ×9, codegen ×9, …).
- 4 end-to-end integration tests in tests/integration/test_arc_strings.sh
covering string assignment, two-var cleanup, reassignment cycle, and
empty-program linkage.
Docs:
- design.adoc updated with Phase 2 implementation status table.
- docs/grammar.ebnf: new authoritative EBNF grammar for the Blaise
language as implemented, including ARC semantic annotations.
2026-04-20 21:04:12 +03:00
|
|
|
|
refactor(runtime): replace blaise_exc.c with Pascal + x86_64 assembly
Port all exception frame management, type identity, and runtime check
functions from C to pure Pascal (blaise_exc.pas). Replace libc
setjmp/longjmp with a minimal custom implementation in x86_64 assembly
(blaise_setjmp_x86_64.s, ~40 lines) that saves only the 8 callee-saved
registers (64-byte jmp_buf vs libc's 200-byte one).
This eliminates the last C source file from the runtime build. The only
non-Pascal code in the runtime is now the assembly setjmp stub.
Changes:
- runtime/src/main/asm/blaise_setjmp_x86_64.s: _blaise_setjmp/_blaise_longjmp
- runtime/src/main/pascal/blaise_exc.pas: _PushExcFrame, _PopExcFrame,
_Raise, _Reraise, _CurrentException, _CurrentExceptionMessage,
_IsInstance, _ImplementsInterface, _GetItab, _Raise_InvalidCast,
_CheckNil — all ported from blaise_exc.c
- uCodeGenQBE.pas: emit call $_blaise_setjmp instead of call $setjmp
- cp.test.exceptions.pas: IR assertion updated for new symbol name
- runtime/Makefile: assembly rule, Pascal blaise_exc build, C rules removed
- .gitignore: whitelist runtime/src/main/asm/*.s
- runtime/src/main/c/blaise_exc.c: deleted
2083 tests pass, fixpoint verified (stage-3/stage-4).
2026-05-21 03:01:08 +03:00
|
|
|
# Assembly sources — platform-specific, no C compiler needed.
|
2026-06-06 14:44:53 +03:00
|
|
|
ASM_OBJS = $(OBJ_DIR)/blaise_setjmp_x86_64.o \
|
2026-06-08 01:56:12 +03:00
|
|
|
$(OBJ_DIR)/blaise_atomic_x86_64.o \
|
|
|
|
|
$(OBJ_DIR)/blaise_utf8_x86_64.o
|
2026-05-01 16:42:29 +03:00
|
|
|
|
|
|
|
|
# Pascal RTL units compiled via the Blaise compiler.
|
2026-05-16 03:42:17 +03:00
|
|
|
PAS_OBJS = $(OBJ_DIR)/blaise_mem.o \
|
|
|
|
|
$(OBJ_DIR)/blaise_str.o \
|
feat(sets): jumbo sets — set of enum up to 256 members
Extend set of <enum> from a 64-member cap to 256, Java-EnumSet style. Sets
of 64 members or fewer keep the existing single-register bitmask (QBE w/l);
sets of 65..256 members ('jumbo') become an inline byte-array bitmap of
ceil(N/8) bytes, treated as a value aggregate (passed by reference, returned
via sret, memset/memcpy), with operations performed by new RTL helpers.
Representation (uSymbolTable): TSetTypeDesc.IsJumbo (BitCount > 64) and
RawByteSize; RawSize/ByteSize/AllocAlign sized accordingly. TSymbol gains
ConstSetBytes/ConstSetQbe for jumbo constants (can't fit an Int64 mask).
RTL: new runtime/src/main/pascal/blaise_set.pas — _SetIn/_SetInclude/
_SetExclude/_SetUnion/_SetInter/_SetDiff/_SetEqual/_SetCopy over byte-array
bitmaps (overlap-safe). Wired into runtime/Makefile.
Semantic: the four >64 caps become >256. AnalyseSetConstDecl folds a jumbo
const to a byte array. The anonymous set for 'X in [a,b,c]' is sized to the
largest listed ordinal (when constant), not the full enum — keeping the
common low-ordinal membership test (incl. the compiler's own TokenKind
tests) on the fast register path. This also fixes a latent miscompile: the
old fixed-l representation silently dropped any listed ordinal >= 64.
Codegen (both backends): jumbo branches for literal, in, +/-/*, =/<>,
Include/Exclude, for-in, assignment, params (pmJumboSetValue ABI), and sret
returns. The register 'in' gained a range guard for literal-sized sets.
Native reserves two 32-byte scratch slots per frame (and .bss in main) for
set-op/literal result buffers. QBE adds IsAggregateAddrType so jumbo sets
ride the record/static-array address paths and are never promoted.
OPDF: no format change — recSet SizeInBytes (1 byte) already covers <=32.
Verified: FIXPOINT_OK and NATIVE_FIXPOINT_OK; full suite (3172 tests) green
built by the stage-2 binary, the QBE fixpoint binary, and the native
fixpoint binary; bif-coverage OK. Tests: cp.test.jumboset (12 IR) and
cp.test.e2e.jumboset (6 e2e, both backends via AssertRunsOnAll); the
>256-member rejection test in cp.test.sets updated. Docs: grammar.ebnf and
language-rationale set-type sections updated for the 256 cap and literal
sizing.
Closes the design discussion behind #81.
2026-06-15 01:23:19 +03:00
|
|
|
$(OBJ_DIR)/blaise_set.o \
|
2026-05-01 19:22:07 +03:00
|
|
|
$(OBJ_DIR)/blaise_arc.o \
|
2026-05-20 01:19:52 +03:00
|
|
|
$(OBJ_DIR)/blaise_weak.o \
|
feat(threading): add TThread, TCriticalSection and POSIX thread bindings
Add blaise_thread.pas runtime unit wrapping pthread_create, pthread_join,
pthread_mutex_init/lock/unlock/destroy and sysconf for GetCPUCount.
Implement TThread (Create, Start, Terminate, WaitFor, Execute virtual,
FreeOnTerminate) and TCriticalSection (Enter/Leave) in classes.pas using
ARC-safe ref counting in the thread trampoline.
Fix EmitFieldCleanupFn to walk the parent chain when emitting the Destroy
call — previously a subclass without its own Destroy would generate an
empty cleanup, causing leaked resources from parent destructors.
Link -lpthread in both the compiler driver and E2E test base.
Include 7 E2E tests covering basic execution, WaitFor blocking, Terminate
flag, Finished flag, multiple threads, mutex-protected counter, and
inherited Destroy cleanup.
2026-05-20 10:31:15 +03:00
|
|
|
$(OBJ_DIR)/blaise_float.o \
|
2026-05-20 21:33:56 +03:00
|
|
|
$(OBJ_DIR)/blaise_thread.o \
|
refactor(runtime): replace blaise_exc.c with Pascal + x86_64 assembly
Port all exception frame management, type identity, and runtime check
functions from C to pure Pascal (blaise_exc.pas). Replace libc
setjmp/longjmp with a minimal custom implementation in x86_64 assembly
(blaise_setjmp_x86_64.s, ~40 lines) that saves only the 8 callee-saved
registers (64-byte jmp_buf vs libc's 200-byte one).
This eliminates the last C source file from the runtime build. The only
non-Pascal code in the runtime is now the assembly setjmp stub.
Changes:
- runtime/src/main/asm/blaise_setjmp_x86_64.s: _blaise_setjmp/_blaise_longjmp
- runtime/src/main/pascal/blaise_exc.pas: _PushExcFrame, _PopExcFrame,
_Raise, _Reraise, _CurrentException, _CurrentExceptionMessage,
_IsInstance, _ImplementsInterface, _GetItab, _Raise_InvalidCast,
_CheckNil — all ported from blaise_exc.c
- uCodeGenQBE.pas: emit call $_blaise_setjmp instead of call $setjmp
- cp.test.exceptions.pas: IR assertion updated for new symbol name
- runtime/Makefile: assembly rule, Pascal blaise_exc build, C rules removed
- .gitignore: whitelist runtime/src/main/asm/*.s
- runtime/src/main/c/blaise_exc.c: deleted
2083 tests pass, fixpoint verified (stage-3/stage-4).
2026-05-21 03:01:08 +03:00
|
|
|
$(OBJ_DIR)/blaise_exc.o \
|
2026-05-20 21:33:56 +03:00
|
|
|
$(OBJ_DIR)/rtl_platform_posix.o
|
2026-05-01 16:42:29 +03:00
|
|
|
|
refactor(runtime): replace blaise_exc.c with Pascal + x86_64 assembly
Port all exception frame management, type identity, and runtime check
functions from C to pure Pascal (blaise_exc.pas). Replace libc
setjmp/longjmp with a minimal custom implementation in x86_64 assembly
(blaise_setjmp_x86_64.s, ~40 lines) that saves only the 8 callee-saved
registers (64-byte jmp_buf vs libc's 200-byte one).
This eliminates the last C source file from the runtime build. The only
non-Pascal code in the runtime is now the assembly setjmp stub.
Changes:
- runtime/src/main/asm/blaise_setjmp_x86_64.s: _blaise_setjmp/_blaise_longjmp
- runtime/src/main/pascal/blaise_exc.pas: _PushExcFrame, _PopExcFrame,
_Raise, _Reraise, _CurrentException, _CurrentExceptionMessage,
_IsInstance, _ImplementsInterface, _GetItab, _Raise_InvalidCast,
_CheckNil — all ported from blaise_exc.c
- uCodeGenQBE.pas: emit call $_blaise_setjmp instead of call $setjmp
- cp.test.exceptions.pas: IR assertion updated for new symbol name
- runtime/Makefile: assembly rule, Pascal blaise_exc build, C rules removed
- .gitignore: whitelist runtime/src/main/asm/*.s
- runtime/src/main/c/blaise_exc.c: deleted
2083 tests pass, fixpoint verified (stage-3/stage-4).
2026-05-21 03:01:08 +03:00
|
|
|
OBJS = $(ASM_OBJS) $(PAS_OBJS)
|
Add Phase 2: record/class types, ARC strings, RTL stubs, and grammar doc
Symbol table:
- Added tyClass kind and NewClassType factory; TRecordTypeDesc now
accepts an optional kind parameter so records and classes share the
same descriptor with distinct semantics.
Semantic analyser:
- AnalyseTypeDecls runs before PushScope so type symbols land in global
scope and survive PopScope.
- Handles TRecordTypeDef and TClassTypeDef; sets IsConstructorCall on
TypeName.Create expressions and IsClassAccess on class-variable field
access and assignment nodes.
Code generator (QBE IR):
- Class variables: 8-byte pointer slot, zeroed on entry.
- Constructor calls: malloc(sizeof fields), store pointer.
- Class field access/write: load pointer, add field offset, load/store.
- ARC string assignment: AddRef new value, Release old value, then store.
- Block exit: Release every string variable in scope (EmitStringCleanup).
Lexer / Parser / AST:
- Added tkClass keyword and ParseClassDef; FieldDecl parsing refactored
into ParseFieldDecl(AFields) shared by both record and class.
- AST gains TClassTypeDef, and IsConstructorCall/IsClassAccess flags on
TFieldAccessExpr and TFieldAssignment.
RTL:
- blaise_arc.c: Phase 2 no-op stubs for _StringAddRef / _StringRelease.
- rtl/Makefile: builds blaise_rtl.a; `make install` copies it next to
the compiler binary for automatic discovery by FindRTL.
- Blaise.pas driver: FindRTL checks BLAISE_RTL env var then binary dir;
links the RTL archive when present.
Tests:
- 180 unit tests (records ×23, classes ×22, ARC ×9, codegen ×9, …).
- 4 end-to-end integration tests in tests/integration/test_arc_strings.sh
covering string assignment, two-var cleanup, reassignment cycle, and
empty-program linkage.
Docs:
- design.adoc updated with Phase 2 implementation status table.
- docs/grammar.ebnf: new authoritative EBNF grammar for the Blaise
language as implemented, including ARC semantic annotations.
2026-04-20 21:04:12 +03:00
|
|
|
|
|
|
|
|
.PHONY: all install clean
|
|
|
|
|
|
|
|
|
|
all: $(LIB)
|
|
|
|
|
|
|
|
|
|
$(LIB): $(OBJS)
|
|
|
|
|
ar rcs $@ $^
|
|
|
|
|
|
refactor(runtime): replace blaise_exc.c with Pascal + x86_64 assembly
Port all exception frame management, type identity, and runtime check
functions from C to pure Pascal (blaise_exc.pas). Replace libc
setjmp/longjmp with a minimal custom implementation in x86_64 assembly
(blaise_setjmp_x86_64.s, ~40 lines) that saves only the 8 callee-saved
registers (64-byte jmp_buf vs libc's 200-byte one).
This eliminates the last C source file from the runtime build. The only
non-Pascal code in the runtime is now the assembly setjmp stub.
Changes:
- runtime/src/main/asm/blaise_setjmp_x86_64.s: _blaise_setjmp/_blaise_longjmp
- runtime/src/main/pascal/blaise_exc.pas: _PushExcFrame, _PopExcFrame,
_Raise, _Reraise, _CurrentException, _CurrentExceptionMessage,
_IsInstance, _ImplementsInterface, _GetItab, _Raise_InvalidCast,
_CheckNil — all ported from blaise_exc.c
- uCodeGenQBE.pas: emit call $_blaise_setjmp instead of call $setjmp
- cp.test.exceptions.pas: IR assertion updated for new symbol name
- runtime/Makefile: assembly rule, Pascal blaise_exc build, C rules removed
- .gitignore: whitelist runtime/src/main/asm/*.s
- runtime/src/main/c/blaise_exc.c: deleted
2083 tests pass, fixpoint verified (stage-3/stage-4).
2026-05-21 03:01:08 +03:00
|
|
|
# --- Assembly rules ---
|
|
|
|
|
$(OBJ_DIR)/%.o: $(ASM_DIR)/%.s
|
Add Phase 2: record/class types, ARC strings, RTL stubs, and grammar doc
Symbol table:
- Added tyClass kind and NewClassType factory; TRecordTypeDesc now
accepts an optional kind parameter so records and classes share the
same descriptor with distinct semantics.
Semantic analyser:
- AnalyseTypeDecls runs before PushScope so type symbols land in global
scope and survive PopScope.
- Handles TRecordTypeDef and TClassTypeDef; sets IsConstructorCall on
TypeName.Create expressions and IsClassAccess on class-variable field
access and assignment nodes.
Code generator (QBE IR):
- Class variables: 8-byte pointer slot, zeroed on entry.
- Constructor calls: malloc(sizeof fields), store pointer.
- Class field access/write: load pointer, add field offset, load/store.
- ARC string assignment: AddRef new value, Release old value, then store.
- Block exit: Release every string variable in scope (EmitStringCleanup).
Lexer / Parser / AST:
- Added tkClass keyword and ParseClassDef; FieldDecl parsing refactored
into ParseFieldDecl(AFields) shared by both record and class.
- AST gains TClassTypeDef, and IsConstructorCall/IsClassAccess flags on
TFieldAccessExpr and TFieldAssignment.
RTL:
- blaise_arc.c: Phase 2 no-op stubs for _StringAddRef / _StringRelease.
- rtl/Makefile: builds blaise_rtl.a; `make install` copies it next to
the compiler binary for automatic discovery by FindRTL.
- Blaise.pas driver: FindRTL checks BLAISE_RTL env var then binary dir;
links the RTL archive when present.
Tests:
- 180 unit tests (records ×23, classes ×22, ARC ×9, codegen ×9, …).
- 4 end-to-end integration tests in tests/integration/test_arc_strings.sh
covering string assignment, two-var cleanup, reassignment cycle, and
empty-program linkage.
Docs:
- design.adoc updated with Phase 2 implementation status table.
- docs/grammar.ebnf: new authoritative EBNF grammar for the Blaise
language as implemented, including ARC semantic annotations.
2026-04-20 21:04:12 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
refactor(runtime): replace blaise_exc.c with Pascal + x86_64 assembly
Port all exception frame management, type identity, and runtime check
functions from C to pure Pascal (blaise_exc.pas). Replace libc
setjmp/longjmp with a minimal custom implementation in x86_64 assembly
(blaise_setjmp_x86_64.s, ~40 lines) that saves only the 8 callee-saved
registers (64-byte jmp_buf vs libc's 200-byte one).
This eliminates the last C source file from the runtime build. The only
non-Pascal code in the runtime is now the assembly setjmp stub.
Changes:
- runtime/src/main/asm/blaise_setjmp_x86_64.s: _blaise_setjmp/_blaise_longjmp
- runtime/src/main/pascal/blaise_exc.pas: _PushExcFrame, _PopExcFrame,
_Raise, _Reraise, _CurrentException, _CurrentExceptionMessage,
_IsInstance, _ImplementsInterface, _GetItab, _Raise_InvalidCast,
_CheckNil — all ported from blaise_exc.c
- uCodeGenQBE.pas: emit call $_blaise_setjmp instead of call $setjmp
- cp.test.exceptions.pas: IR assertion updated for new symbol name
- runtime/Makefile: assembly rule, Pascal blaise_exc build, C rules removed
- .gitignore: whitelist runtime/src/main/asm/*.s
- runtime/src/main/c/blaise_exc.c: deleted
2083 tests pass, fixpoint verified (stage-3/stage-4).
2026-05-21 03:01:08 +03:00
|
|
|
$(CC) -c -o $@ $<
|
Add Phase 2: record/class types, ARC strings, RTL stubs, and grammar doc
Symbol table:
- Added tyClass kind and NewClassType factory; TRecordTypeDesc now
accepts an optional kind parameter so records and classes share the
same descriptor with distinct semantics.
Semantic analyser:
- AnalyseTypeDecls runs before PushScope so type symbols land in global
scope and survive PopScope.
- Handles TRecordTypeDef and TClassTypeDef; sets IsConstructorCall on
TypeName.Create expressions and IsClassAccess on class-variable field
access and assignment nodes.
Code generator (QBE IR):
- Class variables: 8-byte pointer slot, zeroed on entry.
- Constructor calls: malloc(sizeof fields), store pointer.
- Class field access/write: load pointer, add field offset, load/store.
- ARC string assignment: AddRef new value, Release old value, then store.
- Block exit: Release every string variable in scope (EmitStringCleanup).
Lexer / Parser / AST:
- Added tkClass keyword and ParseClassDef; FieldDecl parsing refactored
into ParseFieldDecl(AFields) shared by both record and class.
- AST gains TClassTypeDef, and IsConstructorCall/IsClassAccess flags on
TFieldAccessExpr and TFieldAssignment.
RTL:
- blaise_arc.c: Phase 2 no-op stubs for _StringAddRef / _StringRelease.
- rtl/Makefile: builds blaise_rtl.a; `make install` copies it next to
the compiler binary for automatic discovery by FindRTL.
- Blaise.pas driver: FindRTL checks BLAISE_RTL env var then binary dir;
links the RTL archive when present.
Tests:
- 180 unit tests (records ×23, classes ×22, ARC ×9, codegen ×9, …).
- 4 end-to-end integration tests in tests/integration/test_arc_strings.sh
covering string assignment, two-var cleanup, reassignment cycle, and
empty-program linkage.
Docs:
- design.adoc updated with Phase 2 implementation status table.
- docs/grammar.ebnf: new authoritative EBNF grammar for the Blaise
language as implemented, including ARC semantic annotations.
2026-04-20 21:04:12 +03:00
|
|
|
|
2026-06-04 01:49:29 +03:00
|
|
|
# --- Pascal unit rules (unit-as-top-level) ---
|
|
|
|
|
$(OBJ_DIR)/blaise_mem.o: $(PAS_SRC_DIR)/blaise_mem.pas
|
2026-05-16 03:42:17 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
2026-05-16 03:42:17 +03:00
|
|
|
|
2026-06-04 01:49:29 +03:00
|
|
|
$(OBJ_DIR)/blaise_str.o: $(PAS_SRC_DIR)/blaise_str.pas
|
2026-05-01 16:42:29 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
2026-05-01 16:42:29 +03:00
|
|
|
|
feat(sets): jumbo sets — set of enum up to 256 members
Extend set of <enum> from a 64-member cap to 256, Java-EnumSet style. Sets
of 64 members or fewer keep the existing single-register bitmask (QBE w/l);
sets of 65..256 members ('jumbo') become an inline byte-array bitmap of
ceil(N/8) bytes, treated as a value aggregate (passed by reference, returned
via sret, memset/memcpy), with operations performed by new RTL helpers.
Representation (uSymbolTable): TSetTypeDesc.IsJumbo (BitCount > 64) and
RawByteSize; RawSize/ByteSize/AllocAlign sized accordingly. TSymbol gains
ConstSetBytes/ConstSetQbe for jumbo constants (can't fit an Int64 mask).
RTL: new runtime/src/main/pascal/blaise_set.pas — _SetIn/_SetInclude/
_SetExclude/_SetUnion/_SetInter/_SetDiff/_SetEqual/_SetCopy over byte-array
bitmaps (overlap-safe). Wired into runtime/Makefile.
Semantic: the four >64 caps become >256. AnalyseSetConstDecl folds a jumbo
const to a byte array. The anonymous set for 'X in [a,b,c]' is sized to the
largest listed ordinal (when constant), not the full enum — keeping the
common low-ordinal membership test (incl. the compiler's own TokenKind
tests) on the fast register path. This also fixes a latent miscompile: the
old fixed-l representation silently dropped any listed ordinal >= 64.
Codegen (both backends): jumbo branches for literal, in, +/-/*, =/<>,
Include/Exclude, for-in, assignment, params (pmJumboSetValue ABI), and sret
returns. The register 'in' gained a range guard for literal-sized sets.
Native reserves two 32-byte scratch slots per frame (and .bss in main) for
set-op/literal result buffers. QBE adds IsAggregateAddrType so jumbo sets
ride the record/static-array address paths and are never promoted.
OPDF: no format change — recSet SizeInBytes (1 byte) already covers <=32.
Verified: FIXPOINT_OK and NATIVE_FIXPOINT_OK; full suite (3172 tests) green
built by the stage-2 binary, the QBE fixpoint binary, and the native
fixpoint binary; bif-coverage OK. Tests: cp.test.jumboset (12 IR) and
cp.test.e2e.jumboset (6 e2e, both backends via AssertRunsOnAll); the
>256-member rejection test in cp.test.sets updated. Docs: grammar.ebnf and
language-rationale set-type sections updated for the 256 cap and literal
sizing.
Closes the design discussion behind #81.
2026-06-15 01:23:19 +03:00
|
|
|
$(OBJ_DIR)/blaise_set.o: $(PAS_SRC_DIR)/blaise_set.pas
|
|
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
feat(sets): jumbo sets — set of enum up to 256 members
Extend set of <enum> from a 64-member cap to 256, Java-EnumSet style. Sets
of 64 members or fewer keep the existing single-register bitmask (QBE w/l);
sets of 65..256 members ('jumbo') become an inline byte-array bitmap of
ceil(N/8) bytes, treated as a value aggregate (passed by reference, returned
via sret, memset/memcpy), with operations performed by new RTL helpers.
Representation (uSymbolTable): TSetTypeDesc.IsJumbo (BitCount > 64) and
RawByteSize; RawSize/ByteSize/AllocAlign sized accordingly. TSymbol gains
ConstSetBytes/ConstSetQbe for jumbo constants (can't fit an Int64 mask).
RTL: new runtime/src/main/pascal/blaise_set.pas — _SetIn/_SetInclude/
_SetExclude/_SetUnion/_SetInter/_SetDiff/_SetEqual/_SetCopy over byte-array
bitmaps (overlap-safe). Wired into runtime/Makefile.
Semantic: the four >64 caps become >256. AnalyseSetConstDecl folds a jumbo
const to a byte array. The anonymous set for 'X in [a,b,c]' is sized to the
largest listed ordinal (when constant), not the full enum — keeping the
common low-ordinal membership test (incl. the compiler's own TokenKind
tests) on the fast register path. This also fixes a latent miscompile: the
old fixed-l representation silently dropped any listed ordinal >= 64.
Codegen (both backends): jumbo branches for literal, in, +/-/*, =/<>,
Include/Exclude, for-in, assignment, params (pmJumboSetValue ABI), and sret
returns. The register 'in' gained a range guard for literal-sized sets.
Native reserves two 32-byte scratch slots per frame (and .bss in main) for
set-op/literal result buffers. QBE adds IsAggregateAddrType so jumbo sets
ride the record/static-array address paths and are never promoted.
OPDF: no format change — recSet SizeInBytes (1 byte) already covers <=32.
Verified: FIXPOINT_OK and NATIVE_FIXPOINT_OK; full suite (3172 tests) green
built by the stage-2 binary, the QBE fixpoint binary, and the native
fixpoint binary; bif-coverage OK. Tests: cp.test.jumboset (12 IR) and
cp.test.e2e.jumboset (6 e2e, both backends via AssertRunsOnAll); the
>256-member rejection test in cp.test.sets updated. Docs: grammar.ebnf and
language-rationale set-type sections updated for the 256 cap and literal
sizing.
Closes the design discussion behind #81.
2026-06-15 01:23:19 +03:00
|
|
|
|
2026-06-04 01:49:29 +03:00
|
|
|
$(OBJ_DIR)/blaise_arc.o: $(PAS_SRC_DIR)/blaise_arc.pas
|
2026-05-01 18:26:17 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
2026-05-01 18:26:17 +03:00
|
|
|
|
2026-06-04 01:49:29 +03:00
|
|
|
$(OBJ_DIR)/blaise_weak.o: $(PAS_SRC_DIR)/blaise_weak.pas
|
2026-05-01 19:22:07 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
feat(runtime): port blaise_io / blaise_process / blaise_sys / blaise_time to Pascal
Step 13 (partial): replace four C shims with self-hosted Pascal units that
bind directly to libc syscall surfaces. blaise_exc.c, blaise_arc_class.c,
blaise_weak.c, blaise_str_fmt.c, and blaise_float.c remain in C — they
either need setjmp/longjmp, function-pointer fields in records, or
variadic interfaces that QBE / Blaise cannot express today.
Ports:
- blaise_io.c → blaise_io.pas
File I/O, env vars, working directory, ParamStr, mkstemp, sleep,
process ID. Uses libc bindings (open/read/write/stat/...) declared in
the interface section per the migration rule in CLAUDE.md.
- blaise_process.c → blaise_process.pas
fork/exec/pipe/waitpid wrapped as TProcess; same libc-binding pattern.
- blaise_sys_posix.c → folded into blaise_sys.pas
Tiny shim (just _SysWrite + _SysWriteNewline); now writes directly via
posix_write. No separate C file needed.
- blaise_time.c → blaise_time.pas
clock_gettime + date arithmetic. The local typed-array-const Days
triggered the codegen bug fixed in fa69ae1.
Each unit is built via a thin build_driver.pas program (see existing
blaise_str_build_driver.pas pattern): the Makefile compiles the driver,
strips everything from the program section onward, then assembles + links
the unit-only IR into the runtime archive.
Outcome:
- C_SRCS shrinks from 9 → 5 files; runtime archive size unchanged in
spirit but the dependency surface contracts.
- Standalone units, not yet folded into rtl.platform.posix.pas — that
consolidation can happen later when the platform layer matures and a
second backend (windows / darwin) appears to justify the abstraction.
- All 2023 tests pass; fixpoint OK.
2026-05-19 03:04:17 +03:00
|
|
|
|
2026-06-04 01:49:29 +03:00
|
|
|
$(OBJ_DIR)/blaise_float.o: $(PAS_SRC_DIR)/blaise_float.pas
|
2026-05-19 18:11:14 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
2026-05-19 18:11:14 +03:00
|
|
|
|
2026-06-04 01:49:29 +03:00
|
|
|
$(OBJ_DIR)/blaise_thread.o: $(PAS_SRC_DIR)/blaise_thread.pas
|
2026-05-20 01:19:52 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
2026-05-20 01:19:52 +03:00
|
|
|
|
2026-06-04 01:49:29 +03:00
|
|
|
$(OBJ_DIR)/blaise_exc.o: $(PAS_SRC_DIR)/blaise_exc.pas
|
feat(threading): add TThread, TCriticalSection and POSIX thread bindings
Add blaise_thread.pas runtime unit wrapping pthread_create, pthread_join,
pthread_mutex_init/lock/unlock/destroy and sysconf for GetCPUCount.
Implement TThread (Create, Start, Terminate, WaitFor, Execute virtual,
FreeOnTerminate) and TCriticalSection (Enter/Leave) in classes.pas using
ARC-safe ref counting in the thread trampoline.
Fix EmitFieldCleanupFn to walk the parent chain when emitting the Destroy
call — previously a subclass without its own Destroy would generate an
empty cleanup, causing leaked resources from parent destructors.
Link -lpthread in both the compiler driver and E2E test base.
Include 7 E2E tests covering basic execution, WaitFor blocking, Terminate
flag, Finished flag, multiple threads, mutex-protected counter, and
inherited Destroy cleanup.
2026-05-20 10:31:15 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
feat(threading): add TThread, TCriticalSection and POSIX thread bindings
Add blaise_thread.pas runtime unit wrapping pthread_create, pthread_join,
pthread_mutex_init/lock/unlock/destroy and sysconf for GetCPUCount.
Implement TThread (Create, Start, Terminate, WaitFor, Execute virtual,
FreeOnTerminate) and TCriticalSection (Enter/Leave) in classes.pas using
ARC-safe ref counting in the thread trampoline.
Fix EmitFieldCleanupFn to walk the parent chain when emitting the Destroy
call — previously a subclass without its own Destroy would generate an
empty cleanup, causing leaked resources from parent destructors.
Link -lpthread in both the compiler driver and E2E test base.
Include 7 E2E tests covering basic execution, WaitFor blocking, Terminate
flag, Finished flag, multiple threads, mutex-protected counter, and
inherited Destroy cleanup.
2026-05-20 10:31:15 +03:00
|
|
|
|
2026-06-04 01:49:29 +03:00
|
|
|
$(OBJ_DIR)/rtl_platform_posix.o: $(PAS_SRC_DIR)/rtl.platform.posix.pas \
|
|
|
|
|
$(PAS_SRC_DIR)/rtl.platform.pas
|
refactor(runtime): replace blaise_exc.c with Pascal + x86_64 assembly
Port all exception frame management, type identity, and runtime check
functions from C to pure Pascal (blaise_exc.pas). Replace libc
setjmp/longjmp with a minimal custom implementation in x86_64 assembly
(blaise_setjmp_x86_64.s, ~40 lines) that saves only the 8 callee-saved
registers (64-byte jmp_buf vs libc's 200-byte one).
This eliminates the last C source file from the runtime build. The only
non-Pascal code in the runtime is now the assembly setjmp stub.
Changes:
- runtime/src/main/asm/blaise_setjmp_x86_64.s: _blaise_setjmp/_blaise_longjmp
- runtime/src/main/pascal/blaise_exc.pas: _PushExcFrame, _PopExcFrame,
_Raise, _Reraise, _CurrentException, _CurrentExceptionMessage,
_IsInstance, _ImplementsInterface, _GetItab, _Raise_InvalidCast,
_CheckNil — all ported from blaise_exc.c
- uCodeGenQBE.pas: emit call $_blaise_setjmp instead of call $setjmp
- cp.test.exceptions.pas: IR assertion updated for new symbol name
- runtime/Makefile: assembly rule, Pascal blaise_exc build, C rules removed
- .gitignore: whitelist runtime/src/main/asm/*.s
- runtime/src/main/c/blaise_exc.c: deleted
2083 tests pass, fixpoint verified (stage-3/stage-4).
2026-05-21 03:01:08 +03:00
|
|
|
@mkdir -p $(OBJ_DIR)
|
2026-06-19 06:27:41 +03:00
|
|
|
$(BLAISE) $(BLAISE_FLAGS) --source $< --unit-path $(PAS_SRC_DIR) --output $@
|
refactor(runtime): replace blaise_exc.c with Pascal + x86_64 assembly
Port all exception frame management, type identity, and runtime check
functions from C to pure Pascal (blaise_exc.pas). Replace libc
setjmp/longjmp with a minimal custom implementation in x86_64 assembly
(blaise_setjmp_x86_64.s, ~40 lines) that saves only the 8 callee-saved
registers (64-byte jmp_buf vs libc's 200-byte one).
This eliminates the last C source file from the runtime build. The only
non-Pascal code in the runtime is now the assembly setjmp stub.
Changes:
- runtime/src/main/asm/blaise_setjmp_x86_64.s: _blaise_setjmp/_blaise_longjmp
- runtime/src/main/pascal/blaise_exc.pas: _PushExcFrame, _PopExcFrame,
_Raise, _Reraise, _CurrentException, _CurrentExceptionMessage,
_IsInstance, _ImplementsInterface, _GetItab, _Raise_InvalidCast,
_CheckNil — all ported from blaise_exc.c
- uCodeGenQBE.pas: emit call $_blaise_setjmp instead of call $setjmp
- cp.test.exceptions.pas: IR assertion updated for new symbol name
- runtime/Makefile: assembly rule, Pascal blaise_exc build, C rules removed
- .gitignore: whitelist runtime/src/main/asm/*.s
- runtime/src/main/c/blaise_exc.c: deleted
2083 tests pass, fixpoint verified (stage-3/stage-4).
2026-05-21 03:01:08 +03:00
|
|
|
|
Add Phase 2: record/class types, ARC strings, RTL stubs, and grammar doc
Symbol table:
- Added tyClass kind and NewClassType factory; TRecordTypeDesc now
accepts an optional kind parameter so records and classes share the
same descriptor with distinct semantics.
Semantic analyser:
- AnalyseTypeDecls runs before PushScope so type symbols land in global
scope and survive PopScope.
- Handles TRecordTypeDef and TClassTypeDef; sets IsConstructorCall on
TypeName.Create expressions and IsClassAccess on class-variable field
access and assignment nodes.
Code generator (QBE IR):
- Class variables: 8-byte pointer slot, zeroed on entry.
- Constructor calls: malloc(sizeof fields), store pointer.
- Class field access/write: load pointer, add field offset, load/store.
- ARC string assignment: AddRef new value, Release old value, then store.
- Block exit: Release every string variable in scope (EmitStringCleanup).
Lexer / Parser / AST:
- Added tkClass keyword and ParseClassDef; FieldDecl parsing refactored
into ParseFieldDecl(AFields) shared by both record and class.
- AST gains TClassTypeDef, and IsConstructorCall/IsClassAccess flags on
TFieldAccessExpr and TFieldAssignment.
RTL:
- blaise_arc.c: Phase 2 no-op stubs for _StringAddRef / _StringRelease.
- rtl/Makefile: builds blaise_rtl.a; `make install` copies it next to
the compiler binary for automatic discovery by FindRTL.
- Blaise.pas driver: FindRTL checks BLAISE_RTL env var then binary dir;
links the RTL archive when present.
Tests:
- 180 unit tests (records ×23, classes ×22, ARC ×9, codegen ×9, …).
- 4 end-to-end integration tests in tests/integration/test_arc_strings.sh
covering string assignment, two-var cleanup, reassignment cycle, and
empty-program linkage.
Docs:
- design.adoc updated with Phase 2 implementation status table.
- docs/grammar.ebnf: new authoritative EBNF grammar for the Blaise
language as implemented, including ARC semantic annotations.
2026-04-20 21:04:12 +03:00
|
|
|
install: $(LIB)
|
|
|
|
|
@mkdir -p $(COMPILER_BIN)
|
|
|
|
|
cp $(LIB) $(COMPILER_BIN)/blaise_rtl.a
|
|
|
|
|
@echo "Installed blaise_rtl.a → $(COMPILER_BIN)/blaise_rtl.a"
|
|
|
|
|
|
|
|
|
|
clean:
|
2026-05-01 16:42:29 +03:00
|
|
|
rm -f $(OBJ_DIR)/*.o $(OBJ_DIR)/*.s $(OBJ_DIR)/*.ssa $(LIB)
|