Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/OneScript.Native/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,20 @@ protected override void VisitGlobalFunctionCall(CallNode node)
_statementBuildParts.Push(expression);
}

private static bool InjectedProcessNeeded(MethodInfo methodInfo)
{
if (methodInfo is ContextMethodInfo { InjectsProcess: true })
{
return true;
}
var p = methodInfo.GetParameters();
if (p.Length > 0 && p[0].ParameterType == typeof(IBslProcess))
{
return true;
}
return false;
}
Comment on lines +1095 to +1107
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle process-only methods in the arity logic.

Once this helper starts treating explicit IBslProcess-first methods as injected, calls to a method whose reflected signature is only (IBslProcess process) can hit declaredParameters[1] inside PrepareCallArguments when the script passes any extra argument. That turns a normal “too many actual parameters” error into an exception/generic compile failure.

Please update PrepareCallArguments so injected parameters are excluded from the remaining-count/indexing math before reading declaredParameters[decl]. A case like Список.СортироватьПоЗначению(1) should be reported as an arity error, not crash the compiler.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/OneScript.Native/Compiler/MethodCompiler.cs` around lines 1095 - 1107,
PrepareCallArguments currently miscomputes parameter indexes for methods where
InjectedProcessNeeded(MethodInfo) is true (explicit IBslProcess first
parameter), causing declaredParameters[decl] to be accessed incorrectly; modify
PrepareCallArguments to detect injected parameters via
InjectedProcessNeeded(methodInfo) and exclude that injected parameter from the
"remaining count" and any indexing math: treat the declared parameter list as
starting at index 1 when injected (or equivalently subtract 1 from declared
parameter count and shift declared index access by +1 when reading
declaredParameters[decl]) so arity checks and error messages count only
script-visible parameters and attempts to read declaredParameters use the
adjusted index (references: PrepareCallArguments, InjectedProcessNeeded,
declaredParameters, decl, IBslProcess).


protected override void VisitObjectProcedureCall(BslSyntaxNode node)
{
var target = _statementBuildParts.Pop();
Expand All @@ -1102,7 +1116,8 @@ protected override void VisitObjectProcedureCall(BslSyntaxNode node)
if (targetType.IsObjectValue())
{
var methodInfo = FindMethodOfType(node, targetType, name);
var args = PrepareCallArguments(call.ArgumentList, methodInfo.GetParameters(), methodInfo is ContextMethodInfo { InjectsProcess: true });
var injectProcess = InjectedProcessNeeded(methodInfo);
var args = PrepareCallArguments(call.ArgumentList, methodInfo.GetParameters(), injectProcess);

_blocks.Add(Expression.Call(target, methodInfo, args));
}
Expand Down Expand Up @@ -1168,8 +1183,8 @@ protected override void VisitObjectFunctionCall(BslSyntaxNode node)
$"Метод {targetType}.{name} не является функцией",
$"Method {targetType}.{name} is not a function"), ToCodePosition(node.Location));
}
var args = PrepareCallArguments(call.ArgumentList, methodInfo.GetParameters(), methodInfo is ContextMethodInfo { InjectsProcess: true });

var args = PrepareCallArguments(call.ArgumentList, methodInfo.GetParameters(), InjectedProcessNeeded(methodInfo));
_statementBuildParts.Push(Expression.Call(target, methodInfo, args));
}
else if (targetType.IsContext())
Expand Down Expand Up @@ -1266,7 +1281,7 @@ private Expression CreateMethodCall(CallNode node)
}

var symbol = Symbols.GetScope(binding.ScopeNumber).Methods[binding.MemberNumber];
var args = PrepareCallArguments(node.ArgumentList, symbol.Method.GetParameters(), symbol.Method is ContextMethodInfo { InjectsProcess: true });
var args = PrepareCallArguments(node.ArgumentList, symbol.Method.GetParameters(), InjectedProcessNeeded(symbol.Method));

var methodInfo = symbol.Method;
if (methodInfo is ContextMethodInfo contextMethod)
Expand Down
39 changes: 38 additions & 1 deletion src/Tests/OneScript.Core.Tests/NativeCompilerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,44 @@ public void Can_Call_Member_Procedures()

array.Should().HaveCount(2);
}


[Fact]
public void Can_Call_Member_ProceduresWithBslProcess()
{
var tm = new DefaultTypeManager();
var testType = tm.RegisterClass(typeof(ValueListImpl));

var block = new CompiledBlock(default);
block.Parameters.Insert("Список", new BslTypeValue(testType));
// в методе SortByValue первым параметром идет IBslProcess process
block.CodeBlock = "Список.СортироватьПоЗначению();";

var method = block.CreateDelegate<Func<ValueListImpl, BslValue>>();
var testValue = new ValueListImpl();
method(testValue);

}

[Fact]
public void Can_Call_Member_FunctionsWithBslProcess()
{
var tm = new DefaultTypeManager();
var targetTestType = tm.RegisterClass(typeof(ArrayImpl));
var testType = tm.RegisterClass(typeof(ReflectorContext));

var block = new CompiledBlock(default);
block.Parameters.Insert("Рефлектор", new BslTypeValue(testType));
block.Parameters.Insert("Массив", new BslTypeValue(targetTestType));
// в методе CallMethod первым параметром идет IBslProcess process
block.CodeBlock = "Результат = Рефлектор.ВызватьМетод(Массив, \"Количество\");";

var method = block.CreateDelegate<Func<ReflectorContext, ArrayImpl, BslValue>>();
var reflector = ReflectorContext.CreateNew(new TypeActivationContext() { TypeManager = tm});
var array = new ArrayImpl();
method(reflector, array);

}

[Fact]
public void Can_Call_Member_Procedures_On_Dynamics()
{
Expand Down
Loading