Skip to content

Comments

[Beam] Improve test coverage and fix runtime bugs (2022→2086)#4347

Merged
dbrattli merged 15 commits intomainfrom
dbrattli/beam-improvements
Feb 18, 2026
Merged

[Beam] Improve test coverage and fix runtime bugs (2022→2086)#4347
dbrattli merged 15 commits intomainfrom
dbrattli/beam-improvements

Conversation

@dbrattli
Copy link
Collaborator

@dbrattli dbrattli commented Feb 18, 2026

Summary

  • Add FSharp.Reflection support: GetRecordFields, IsRecord, IsUnion, GetUnionCases, MakeRecord, MakeUnion, GetUnionFields with 24 new tests
  • Port 13 async tests with runtime fixes for error wrapping and OperationCanceledException
  • Fix nested option wrapping to use runtime fable_option:some/1 instead of literal tuples (matching Python approach)
  • Fix String.Format with ParamArray forwarding single array arguments
  • Enable lazy sequence tests (Seq.forall, Seq.tryHead with options, Seq.initInfinite)
  • Add Util2/Util3 helpers and port 6 misc tests (type abbreviations, multiple namespaces, inline extensions)

dbrattli and others added 13 commits February 18, 2026 08:56
…tion in loops (2022→2025)

- Add missing NumberValue.BigInt handler in Fable2Beam.fs (was emitting todo_ placeholder)
- Add rangeBigInt to Range.fs and BigInt arm to op_Range in Replacements.fs
- Add fable_list:take/2 that throws on insufficient elements (replaces lists:sublist)
- Add ForLoop/WhileLoop/TryCatch arms to containsIdentRef and isCapturedInClosure
  so array mutations inside loops are detected for ref-wrapping

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…2030)

Fix delegate Invoke for custom and System delegates by adding runtime arity
check via erlang:fun_info/2. This is needed because Delegate AST nodes may
have arity 0 (unit stripped by discardUnitArg) or arity 1 (unit kept), and
Erlang enforces exact arity. Python avoids this by adding default __unit
params; Erlang has no default params so runtime detection is required.

Also enable Dictionary.Values iteration by routing KeyCollection/ValueCollection
GetEnumerator through fable_utils:get_enumerator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s (2030→2031)

Enable ResizeArray casting to seq test which now passes. Clean up stale
comments: remove duplicate array pattern matching test (already enabled
elsewhere), update TryParse TODOs with precise diagnosis (byref method
reference unwraps ref.contents instead of passing ref), update applicative
arity test TODO (uncurrying naming collision generates fun(X, X)).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… Dictionary folding (2031→2038)

- Add named capture group support to fable_regex.erl: extract_group_names
  parses pattern to build name-to-index mapping, stored in match result
  and exposed via tagged {group_collection, Items, Names} tuple from
  get_groups, with get_item handling both string and integer indexing
- Fix string interpolation with typed format specifiers (e.g. %.8f):
  fable_string.erl interpolate_loop now parses multi-character format
  specs before %P() placeholders, and unwraps ref-wrapped value arrays
- Fix Dictionary folding via Seq.fold: seqModule catch-all in
  Replacements.fs now unwraps Dictionary-typed args (looking through
  TypeCast wrappers) to maps:to_list(erlang:get($0))
- Add group_collection tuple handling to fable_utils:get_enumerator

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add FSharp.UMX package reference and test verifying units of measure
extensions work on Beam (tagged string/int types with % operator and
UMX.untag). Reflection test skipped as FSharpType.GetRecordFields is
not supported by Fable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…IsUnion, GetUnionCases (2039→2040)

Extend Beam type info generation to include record field info and union
case info in the TypeInfo map. DeclaredType records now emit a `fields`
key with [{Name, TypeInfo}] tuples; unions emit a `cases` key.

- Fable2Beam.Reflection.fs: detect IsFSharpRecord/IsFSharpUnion in
  DeclaredType handler, emit fields/cases metadata
- fable_reflection.erl: add get_record_elements, get_union_cases,
  is_record, is_union functions
- Replacements.fs: route FSharpType.GetRecordFields/GetUnionCases/
  IsRecord/IsUnion to fable_reflection, wrap results as array refs
- Enable FSharp.UMX reflection info test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…(2040→2064)

Add FSharpType functions (IsTuple, GetTupleElements, IsFunction,
GetFunctionElements, MakeTupleType), FSharpValue functions (GetRecordFields,
GetRecordField, MakeRecord, GetTupleFields, GetTupleField, MakeTuple,
GetUnionFields, MakeUnion), PropertyInfo/UnionCaseInfo property handlers,
typedefof support, and Type.Name/GetGenericTypeDefinition/GetElementType.

Restructured type info representation to use maps for PropertyInfo and
CaseInfo (with integer tags matching Beam union representation), and added
fable_reflection.erl runtime functions for all reflection operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…eledException (2064→2077)

Fix catch_async to use integer tags matching Beam union representation
instead of atom tags. Fix try_finally to call compensation with arity 1
(ok) instead of arity 0. Fix try_with to wrap raw binary errors from
failwith as exception maps so .Message accessor works. Add wrap_error
helper to fable_async for consistent exception representation.

Add OperationCanceledException to supported exception types. Port async
tests: while/for binding, exception handling, StartWithContinuations,
Async.Catch, FromContinuations, deep recursion, nested failure
propagation, try/finally, and Async.Bind exception propagation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ing.Format (2077→2083)

Add Misc/Util2.fs (Helper.Format with ParamArray, Helper3 type alias, StartsWithIgnoreCase
extension) and Misc/Util3.fs (multiple namespaces in single file) to the Beam test project.

Port 6 tests from Python TestMisc: type abbreviation in namespace, multiple namespaces,
inline extension methods from other files, calls to core lib subfolder, assignment block
optimization, and assignment blocks inside try/with.

Fix String.Format ParamArray handling: when a single array argument is passed (e.g. from
a ParamArray forwarding), pass it directly to fable_string:format/2 instead of wrapping
it in an additional list. Update FABLE-BEAM.md with current test counts and new features.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use runtime fable_option:some/1 smart constructor for all option wrapping
contexts in NewOption, instead of literal {some, V} tuples. This aligns
Beam with Python's approach: both compiler-generated values and library-
produced values (e.g. from Seq.tryHead) go through the same code path,
ensuring consistent representation for nested options like Option<Option<T>>.

Enable "Seq.tryHead with option works" (including .Value.Value accessor)
and "Seq.forall is lazy" tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Seq.initInfinite now works thanks to lazy sequences via compiled seq.erl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dbrattli and others added 2 commits February 18, 2026 19:32
@dbrattli dbrattli merged commit e9bae17 into main Feb 18, 2026
23 checks passed
@dbrattli dbrattli deleted the dbrattli/beam-improvements branch February 18, 2026 18:49
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