Commit graph

10 commits

Author SHA1 Message Date
Graeme Geldenhuys 1ef226369d fix(semantic): accept empty open-array literal [] as an open-array argument
An empty bracket literal [] passed to a plain open-array parameter
(`array of T`) failed overload resolution with "No matching overload" on both
backends. A non-empty literal works because AnalyseArrayLiteralExpr infers the
element type and types it `array of <elem>`; an empty [] has nothing to infer
from and was left untyped (nil), so it matched neither the open-array param (nil
arg type) nor the existing set / array-of-const special cases.

Two changes in uSemantic:
* ArgMatchScore now scores an empty TArrayLiteralExpr as an exact (2) match
  against any tyOpenArray parameter — an empty open array is valid for any
  element type — placed before the nil-arg bail so overload selection accepts it.
* RetypeSetLiteralArgs pins the empty []'s ResolvedType to the chosen formal's
  open-array type, so codegen emits a zero-length open array (data=nil, high=-1)
  of the right element type.

Overload disambiguation is preserved ([] picks the open-array overload; a scalar
argument still picks the scalar overload), and two equally-matching open-array
overloads still raise a clean "ambiguous overload" error. Works for
`array of string`, `array of Integer`, and `array of const`.

This was the last open item in native-testrunner-investigation.txt; the native
TestRunner now passes the full suite unfiltered. Adds dual-backend e2e tests.
All three fixpoints green; 3501 tests pass.
2026-06-18 11:53:51 +01:00
Graeme Geldenhuys 267c825237 fix(codegen): accept dynamic array as open-array argument
A dynamic-array variable passed where an open-array parameter was
expected was rejected with "No matching overload", and even once the
semantic check accepted it the codegen emitted the wrong (data, high)
pair: it loaded a `<name>_high` slot that only exists for static-array
open-array temporaries.

Semantic pass: CheckTypesMatch and ArgMatchScore now treat tyDynArray
as assignment-compatible with a tyOpenArray parameter when the element
types match.

Codegen (both backends): when a tyDynArray argument is coerced to an
open-array parameter, pass the data pointer plus (runtime length - 1)
as the high index, where the length comes from _DynArrayLength at run
time rather than a compile-time static bound. QBE: OpenArrayArgFragment
gains a dynarray case (using distinct temps for the w-length and the
l-high computation to keep the IR well-typed). Native: the three
open-array argument emission paths (EmitMethodArgPush plus the two
call-site push/slot handlers) each gain a tyDynArray case.

Adds five dual-backend e2e tests in cp.test.e2e.openarray.pas covering
sum, High/Length, empty array, array-of-string, and pass-to-nested.
2026-06-16 11:56:36 +01:00
Graeme Geldenhuys dbf2e3c879 fix(qbe): open-array args on method and constructor calls dropped the high
Open-array arguments were lowered correctly only at standalone
procedure/function call sites.  Method calls (statement and expression
paths, static and virtual) and constructor calls emitted just the data
pointer — the callee read its (data, high) pair shifted, so High(A) and
the elements were garbage (F.Sum([10, 20, 30]) printed junk; the
statement form printed a wrong count).

New OpenArrayArgFragment helper emits the 'l data, l high' pair for
inline array literals, static-array coercions, and open-array parameter
forwarding; the four method/constructor argument loops now use it.
The native backend already handled all these shapes.

Test: TE2EOpenArrayTests.TestRun_OpenArray_MethodAndCtorParams —
constructor, function and procedure (statement) open-array params on a
class, both backends.  Suite: 2942 OK; FIXPOINT_OK; NATIVE_FIXPOINT_OK.
2026-06-11 11:30:42 +01:00
Graeme Geldenhuys 00596b2ca6 fix(lang): add mandatory () to all bare zero-arg calls, add semantic diagnostic
The mandatory-() migration (commit 57c0660) missed ~1000 bare zero-arg
function and method calls across the compiler, stdlib, and test suite.
Without (), these were silently treated as variable reads, producing
broken QBE IR (%_var_ temporaries instead of call instructions).

Added semantic error diagnostics in uSemantic.pas to catch bare references
to functions/procedures that require () for a call. This prevents silent
miscompilation and gives users a clear error message.

Fixed all bare calls across 69 files: compiler pipeline (uParser,
uSemantic, uCodeGenQBE, uLexer, uPasTokeniser, etc.), stdlib (classes),
and the full test suite (inline test programs and test framework code).

FIXPOINT_OK at 262,220 lines. 2627 tests pass. Rolling bootstrap from
v0.10.0 verified.
2026-06-07 05:46:48 +01:00
Graeme Geldenhuys 57c0660a37 refactor(lang): remove IsNoArgFuncCall dead code, fix remaining bare calls
With mandatory () on all zero-argument calls (51ebf23), the
IsNoArgFuncCall/NoArgFuncDecl fields on TIdentExpr and the
synthesised TFuncCallExpr codegen path are dead code. Remove them.

This exposed ~300 bare function calls missed by the original
migration script across compiler, runtime, stdlib, tests, and
embedded Blaise source strings. Fix all of them.

Add IsProcFieldCall support to TMethodCallExpr so that
H.Handler() works for procedure-type fields — the parser creates
TMethodCallExpr for Obj.Name(), and the semantic pass now detects
when 'Name' is a procedural-typed field rather than a method,
routing through the indirect-call codegen path.

Update fixpoint.sh to fall back to an existing blaise_rtl.a when
the release binary is too old to build the runtime.

2627 tests pass, FIXPOINT_OK.
2026-06-06 20:28:13 +01:00
Graeme Geldenhuys 51ebf2350a feat(lang): require mandatory () on all zero-argument calls
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).
2026-06-06 19:14:47 +01:00
Graeme Geldenhuys 8b524340ce fix(codegen): storel for proc-pointer static-array slots; add Expr()() postfix call
Two related bugs found while testing procedural types as open-array elements:

1. Static-array element stores for tyProcedural used 'storew' (32-bit) instead
   of 'storel' (64-bit), truncating the function pointer and causing a segfault
   at the indirect call site.  Fixed by adding tyProcedural to the storel branch
   in the static-array element-store path in EmitArraySubscriptStmt.

2. Calling through an array subscript expression (Fns[I]()) was rejected by the
   parser with "Expected 'end' but got '('".  The postfix chaining loop only
   handled '.', '[', and '^'; it did not recognise '(' as a postfix call on a
   non-identifier expression.

   Fixed by introducing TIndirectFuncCallExpr (callee is an arbitrary TASTExpr),
   extending the postfix loop in ParseFactor to emit it when '(' follows any
   expression, and adding the corresponding semantic analysis and codegen paths.
   The codegen uses the callee value directly as the call target — no extra loadl,
   since the subscript load already yields the function pointer value.

Adds E2E test TestRun_OpenArray_ProcType_CallEach covering a static array of
TIntFn passed as an open-array parameter and called element-by-element via the
direct Fns[I]() syntax.
2026-05-22 17:10:02 +01:00
Graeme Geldenhuys 96245f8ba0 feat(testing): run [Threaded] E2E suites as parallel subprocesses
Mark all 26 E2E test classes with the [Threaded] attribute. The test
runner now launches each [Threaded] suite as an independent subprocess
in parallel, then collects and merges results after in-process tests
finish. Wall-clock test time drops from ~15s to ~3s.

Changes:
- blaise.testing: add ThreadedAttribute, TTestResult.MergeFrom
- blaise.testing.runner.text: launch all [Threaded] suites via TProcess
  up front, run in-process tests, then collect subprocess output and
  parse verbose results back into the main TTestResult
- cp.test.e2e.*.pas: add [Threaded] annotation to all 26 E2E classes
2026-05-21 01:13:08 +01:00
Graeme Geldenhuys 923b94c541 refactor: split rtl/ into runtime/ + stdlib/, rename bcl.testing to blaise.testing
Separate always-linked runtime code (system.pas, ARC, strings, platform
abstraction) from opt-in standard library units (sysutils, classes, math,
dateutils, generics, etc.).  This mirrors the Go runtime/ vs stdlib, Rust
core vs std, and Swift SwiftRuntime vs SwiftCore patterns.

- runtime/ contains code linked into every binary + C shims
- stdlib/ contains units imported explicitly via uses clause
- Single platform abstraction layer (rtl.platform.*) in runtime/,
  shared by both runtime/ and stdlib/ units
- bcl.testing renamed to blaise.testing across all 95+ test files
- Updated PasBuild project.xml, fixpoint.sh, README, unit search paths
- All 1931 tests pass, fixpoint OK (stage-3/stage-4)
2026-05-16 00:51:18 +01:00
Graeme Geldenhuys dd987f97f9 feat(openarray): coerce static-array variables to open-array parameters
Passing a named static-array variable (array[lo..hi] of T) to a procedure
expecting an open-array parameter (array of T) previously failed with 'No
matching overload' because ArgMatchScore and IsSubtypeOf had no rule for this
coercion.  Inline array literals worked because they resolve to tyOpenArray
directly; named variables do not.

Fix: add a tyStaticArray→tyOpenArray widening rule (score 1) in both
ArgMatchScore and IsSubtypeOf when element types match.  In codegen, add a
third branch in all four open-array argument-emission sites: when the arg is
a tyStaticArray, emit the base pointer plus (HighBound - LowBound) as the
compile-time high index instead of loading a runtime _high slot.

Tests: 5 new IR/semantic tests in cp.test.openarray.pas.  New dedicated e2e
unit cp.test.e2e.openarray.pas with 8 tests (3 moved from the monolithic e2e
unit + 5 new static-array coercion tests covering Length, Sum, non-zero base,
and nested forwarding).  Fixpoint verified at stage-3/stage-4.
2026-05-13 16:57:00 +01:00