Make parentheses mandatory on every function, procedure, method, and
constructor call — even those with zero arguments. A bare identifier
or field access is now unambiguously a variable/field/property read;
appending () makes it a call.
Mechanically migrated all 144 source files (compiler, runtime, stdlib,
tests, kanban tool). Fixed several latent bugs exposed by the AST node
transition from TFieldAccessExpr.IsMethodCall to TMethodCallExpr:
- IsBuiltinToString applied to record methods (added tyClass guard)
- IsVarParam not set for value record/static-array parameters in
AnalyseMethodCallExpr (extended to check skParameter + aggregate type)
- Native backend used movq (pointer load) for record receivers instead
of leaq (address-of) in EmitMethodCallExpr
- ResolveDiamond now handles TMethodCallExpr for diamond-operator
constructor calls
Updated grammar.ebnf (MethodCall, ProcCall, Factor rules) and
language-rationale.adoc with the design decision. Marked the
future-improvements.adoc entry as implemented.
All 2627 tests pass. Fixpoint verified (FIXPOINT_OK).
Add file-change monitoring to the kanban TUI so that tasks added via CLI
(or any external process) while the TUI is running are automatically
merged into the live view instead of being silently overwritten on save.
The implementation has three layers:
1. New FileAge built-in (compiler + runtime): returns the file's mtime as
Int64 via stat(), or -1 if the file does not exist. Follows the same
pattern as FileExists — symbol table registration, semantic analysis,
codegen, and POSIX ABI stub.
2. Merge-aware TBoard (kanban.data): tracks last-known mtime, deleted IDs
(so re-reads don't resurrect user-deleted tasks), and provides
HasExternalChanges/MergeFromDisk. Save() now auto-merges before
writing. ID conflicts (same ID, different task) are resolved by
reassigning the in-memory task to a fresh ID.
3. Idle polling in TKanbanUI.Run: every ~2 seconds (20 idle ReadKey
cycles at VTIME=1), checks HasExternalChanges and merges new tasks
with a status bar notification.
The kanban board is now a proper tool alongside migration-analyser.
Adds tools/kanban/project.xml (blaise-kanban module) and registers
it in the root aggregator. Removes the standalone build.sh script
since PasBuild handles compilation.
The compiler has been self-hosting since v0.7.0 and FPC is no longer
part of the toolchain. Remove the last FPC-conditional code paths:
- Blaise.pas: drop CacheKeyForFile, LoadCachedIR, StoreCachedIR and
both {$IFDEF FPC} whole-program IR cache blocks; remove --cache-dir
flag and CacheDir/UnitIR/UnitName/UnitPath locals; collapse the
ReadProcessChunk FPC/Blaise fork to the Blaise implementation only;
drop the poUsePipes/poStderrToOutPut Options block.
- tools/migrate_full.py: deleted — the Python migration analyser is no
longer needed now that the toolchain is fully Blaise-native.
Adopts the Swift/LLVM model: Apache License 2.0 with the Runtime Library
Exception text used verbatim by the Swift project. SPDX identifier:
Apache-2.0 WITH Swift-exception.
Apache 2.0 brings an explicit patent grant and patent-retaliation clause
that BSD-3 lacks. The Runtime Library Exception ensures binaries
produced by the Blaise compiler do not inherit attribution obligations
from the linked-in RTL.
* LICENSE — full Apache 2.0 + RLE text (replaces the deleted LICENCE).
* NOTICE — project header plus QBE attribution (MIT, vendored).
* docs/language-rationale.adoc — new Project Governance section
capturing the decision, alternatives considered, and rationale.
* SPDX headers updated across all .pas, .pp, .inc, .c source files,
build scripts, PasBuild plugins, and the Makefile.
* project.xml license field updated.
* tools/migrate_full.py HEADER template updated so generated
self-hosting source carries the new licence.
The blaise compiler now compiles its own source (tests/blaise-compiler.pas)
into a second-stage binary that successfully compiles and runs a hello-world
program. All 834 compiler tests still pass.
Codegen and RTL fixes that unblocked self-hosting:
- String literal interning (uCodeGenQBE): set FStrLits.CaseSensitive := True.
FPC's TStringList.IndexOf is case-insensitive by default, so distinct
literals like 'WRITELN' and 'WriteLn' collapsed to the same label.
- ARC on implicit Self.Field assignments (uCodeGenQBE): EmitAssignment's
implicit-Self branch did a raw storel for class/string fields. Fresh
_ClassAlloc'ed objects start at refcnt 0, so without the addref they were
freed by later local releases. Now addrefs new value and releases old.
- #nn character literals (uLexer): UnescapeString handled only 'text'.
Extended to decode #nn decimal literals and concatenated forms like
'abc'#13#10'def'. Local OrdAt helper lets the body parse under FPC and
the self-hosted compiler.
- Chr() builtin: registered in uSymbolTable, handled in uSemantic, emitted
in uCodeGenQBE as _Chr, implemented in rtl/blaise_str.c.
- LF line separator (Classes.pas): TStringList.GetText used #13#10; QBE
rejects CR in its input. Changed to #10.
Self-hosting source (tests/blaise-compiler.pas) — needs a virtual Destroy
on TASTNode and Exception (post-TObject-stripping they became root classes
without a vtable, breaking `is` checks and exception message layout).
TAST* descendants chain `override`.
Migration tooling: add tools/migrate_full.py — the script that generates
tests/blaise-compiler.pas by flattening the eight compiler units and RTL
Classes unit into a single self-contained Pascal source. The postprocess()
step injects virtual Destroy on TASTNode / TTypeDesc and strips `override`
from non-vtable root classes.