Skip to content

Language hardening#58

Merged
cs01 merged 4 commits intomainfrom
language-hardening
Feb 24, 2026
Merged

Language hardening#58
cs01 merged 4 commits intomainfrom
language-hardening

Conversation

@cs01
Copy link
Owner

@cs01 cs01 commented Feb 24, 2026

Language hardening: closures, computed writes, type safety

Fixes several crash-inducing codegen issues and adds compile-time guardrails for unsafe type patterns.

Unsafe union type rejection

The semantic analyzer now rejects union types where members have incompatible memory layouts (e.g. string | number) in variable declarations and class fields. Nullable unions (string | null) remain allowed since null shares the pointer representation. This prevents silent memory corruption at runtime.

Interface field checking is intentionally omitted — the native compiler can't handle the iface.fields[i].name array-of-objects access pattern during self-hosting.

Inline lambda captures in array methods

arr.map(x => x + captured), arr.filter(...), and arr.forEach(...) now correctly capture outer variables. Previously, inline lambdas passed to array methods lost their closure environment, causing undefined values or segfaults.

The fix uses a struct-of-arrays pattern (getLastCaptureNames()/getLastCaptureTypes()) instead of array-of-objects to remain self-hosting compatible. The orchestrator allocates the env struct immediately after generating the arrow function, so array iteration codegen can pass it as the first argument.

Computed property write (obj[key] = value)

Extends computed property access (read) with write support. Uses the same strcmp chain over known object keys, but emits store instead of load. Both string and numeric field values are handled, with type matching to skip incompatible branches.

Type assertion field order fix

const typed = obj as { age: number; name: string } where the asserted type reorders fields relative to the object literal now works correctly. Previously, the GEP indices followed the assertion's field order instead of the actual struct layout, reading wrong fields and causing segfaults.

The fix records the source variable name during type assertion codegen (setLastTypeAssertionSourceVar) so that allocateDeclaredInterface can inherit the original field order.

Changes

  • src/analysis/semantic-analyzer.ts — union type checks for variable decls and class fields
  • src/codegen/expressions/access/index.tsgenerateDynamicObjectAssignment for obj[key] = value
  • src/codegen/expressions/arrow-functions.ts — struct-of-arrays capture info accessors
  • src/codegen/expressions/orchestrator.ts — env struct allocation for inline lambdas; type assertion source tracking
  • src/codegen/infrastructure/ — new context methods for env ptr and assertion source var
  • src/codegen/types/collections/array/ — pass closure env through iteration/search/sort codegen
  • src/codegen/llvm-generator.ts — plumb new context methods
  • docs/language/limitations.md — updated for computed property write, closures, union restrictions
  • 6 new test fixtures (closures, computed writes, type assertions)
  • New unit tests for SemanticAnalyzer unsafe union rejection

Test plan

  • npm test — all unit and compiler tests pass
  • npm run verify — full 3-stage self-hosting succeeds

@cs01 cs01 merged commit 5bd698c into main Feb 24, 2026
17 of 18 checks passed
@cs01 cs01 deleted the language-hardening branch February 24, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant