Skip to content

MacroCompiler: AEval()/AEvalA() with a codeblock literal (implicit reference conversion to interfaces) - #2114

Merged
RobertvanderHulst merged 2 commits into
X-Sharp:devfrom
ecosSystem:homebase/macro-aeval-overload
Oct 23, 2026
Merged

RobertvanderHulst merged 2 commits into
X-Sharp:devfrom
ecosSystem:homebase/macro-aeval-overload

Conversation

@ecosSystem

Copy link
Copy Markdown
Contributor

Problem

AEval() and AEvalA() can't be called from a macro or script with a codeblock literal:

local a := {1,2}
aeval(a, {|x| x})    // error XM0205: No suitable overload of 'XSharp.RT.Functions.AEval()'

This also fails with the optional start/count arguments, and for a plain macro aeval({1,2}, {|x| x}). Passing a USUAL that holds a codeblock works, and so does AScan(), because its parameter is a USUAL.

Cause

The codeblock literal has the type XSharp.Codeblock, and the parameter has the type ICodeblock. In Binder.Conversion(), the reference conversion check uses Type.IsSubclassOf(). That method only looks at base classes and never at implemented interfaces. So no conversion was found, and every non-generic overload was rejected. The generic AEval<T> overloads are rejected anyway by the open-generic check.

Change

Binder.Conversion.cs: use IsAssignableFrom() instead of IsSubclassOf():

  • for the implicit reference conversion (source type to base type or interface)
  • for the reverse explicit conversion

For class to class conversions this gives the same result as before. The identity case is handled earlier by TypesMatch().

Tests

  • ScriptTests.prg: four new tests:
    • aeval through Compile and through CompileCodeblock
    • aeval with start/count
    • aevala
  • Harness: I also checked with a C# harness, in the VO and Core dialects, through both Compile and CompileCodeblock. All cases failed with XM0205 before the change and pass after it.
  • MacroCompiler.Example run: I ran it with and without the change. The only difference in the results is the four new tests.
    • I couldn't build XSharp.VO/VFP/Rdd locally, so I commented out the few VO/VFP-only lines in VoTests.
    • The test run stops at DbCreate in the UDC tests in both runs, so the tests after that point did not run.
  • Real application: the change was also tried in a real application that runs scripts through GetScriptCompiler() + CompileCodeblock(), together with MacroCompiler: nested codeblocks can use LOCALs of the enclosing script/codeblock #2113.

Relation to #2113

This fixes the AEval() side note in #2113. The two PRs are independent. Together, a script can use aeval(a, {|x| nSum += x}) with a LOCAL nSum. Both PRs add tests at the same place in ScriptTests.prg, so whichever one is merged second will have a trivial conflict there: keep both test blocks.

🤖 Generated with Claude Code

ecosSystem and others added 2 commits October 23, 2026 08:17
Calling AEval()/AEvalA() with a codeblock literal from a macro or script
always failed with "error XM0205: No suitable overload". The literal has
type XSharp.Codeblock and the parameter is ICodeblock, but the reference
conversion check used Type.IsSubclassOf(), which only looks at base
classes and never at implemented interfaces. Use IsAssignableFrom() for
the implicit (and the reverse explicit) reference conversion instead.

Added AEval/AEvalA tests to the script tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@RobertvanderHulst
RobertvanderHulst merged commit 1123fbc into X-Sharp:dev Oct 23, 2026
@RobertvanderHulst
RobertvanderHulst self-requested a review October 23, 2026 16:42
@RobertvanderHulst RobertvanderHulst moved this to Done in XSharp 3.1 Oct 23, 2026
@RobertvanderHulst RobertvanderHulst added this to the X# 3.1 milestone Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants