mirror of
https://github.com/Stone-Red-Code/YesNt-Interpreter.git
synced 2026-09-07 23:43:07 +02:00
Add named function parameters
This commit is contained in:
@@ -27,6 +27,7 @@ internal sealed class RuntimeInformation : IStatementContext
|
||||
|
||||
public Dictionary<string, string> GlobalVariables { get; set; } = [];
|
||||
public Dictionary<string, int> Functions { get; } = [];
|
||||
public Dictionary<string, List<string>> FunctionParameters { get; } = [];
|
||||
public Dictionary<int, int> BlockBoundaries { get; } = [];
|
||||
internal Action PreScanLinesAction { get; set; }
|
||||
public Stack<FunctionScope> FunctionCallStack { get; } = new();
|
||||
@@ -176,6 +177,7 @@ internal sealed class RuntimeInformation : IStatementContext
|
||||
GlobalVariables.Clear();
|
||||
Labels.Clear();
|
||||
Functions.Clear();
|
||||
FunctionParameters.Clear();
|
||||
BlockBoundaries.Clear();
|
||||
FunctionCallStack.Clear();
|
||||
InParametersStack.Clear();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
namespace YesNt.Interpreter.Runtime;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all classes that host statement handler methods.
|
||||
/// Subclasses declare methods decorated with <see cref="Attributes.StatementAttribute"/> or
|
||||
@@ -21,4 +24,78 @@ internal abstract class StatementRuntimeInformation
|
||||
{
|
||||
return value.Trim().TrimEnd(':').Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a function declaration (the text after the <c>func</c> keyword), extracting the
|
||||
/// function name and its optional comma-separated named parameters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the declaration is well formed; otherwise <see langword="false"/>.
|
||||
/// </returns>
|
||||
internal static bool TryParseFunctionSignature(string declaration, out string name, out List<string> parameters)
|
||||
{
|
||||
name = string.Empty;
|
||||
parameters = [];
|
||||
|
||||
string trimmed = declaration.Trim();
|
||||
int colonIndex = trimmed.IndexOf(':');
|
||||
if (colonIndex < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
name = NormalizeBlockName(trimmed[..colonIndex]);
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string parameterSection = trimmed[(colonIndex + 1)..].Trim();
|
||||
if (string.IsNullOrWhiteSpace(parameterSection))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (string rawParameter in parameterSection.Split(','))
|
||||
{
|
||||
string parameter = rawParameter.Trim();
|
||||
if (string.IsNullOrWhiteSpace(parameter) || parameter.Contains(' '))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
parameters.Add(parameter);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binds a function's named parameters to local variables by popping values from the
|
||||
/// current call scope's argument stack, mirroring <c>var p = %in</c> for each parameter.
|
||||
/// </summary>
|
||||
protected void BindNamedParameters(string functionKey)
|
||||
{
|
||||
if (!RuntimeInfo.FunctionParameters.TryGetValue(functionKey, out List<string> parameters) || parameters.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (RuntimeInfo.FunctionCallStack.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FunctionScope scope = RuntimeInfo.FunctionCallStack.Peek();
|
||||
foreach (string parameter in parameters)
|
||||
{
|
||||
if (scope.Arguments.Count == 0)
|
||||
{
|
||||
RuntimeInfo.Exit(ExitMessages.NoInArgumentInStack, true);
|
||||
return;
|
||||
}
|
||||
|
||||
scope.Variables[parameter] = scope.Arguments.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -597,6 +597,7 @@ public class YesNtInterpreter
|
||||
internal void PreScanLines()
|
||||
{
|
||||
runtimeInfo.BlockBoundaries.Clear();
|
||||
runtimeInfo.FunctionParameters.Clear();
|
||||
lineMatchingHandlers = new List<List<StatementHandler>>(runtimeInfo.Lines.Count);
|
||||
|
||||
// Dictionary to track open blocks by their expected end statement name
|
||||
@@ -615,6 +616,12 @@ public class YesNtInterpreter
|
||||
{
|
||||
matchingHandlers.Add(handler);
|
||||
|
||||
if (handler.Attribute.Name == "func"
|
||||
&& StatementRuntimeInformation.TryParseFunctionSignature(content["func ".Length..], out string functionName, out List<string> functionParameters))
|
||||
{
|
||||
runtimeInfo.FunctionParameters[functionName] = functionParameters;
|
||||
}
|
||||
|
||||
// Track block starts (skip intermediates — they are handled separately below)
|
||||
string blockPair = handler.Attribute.BlockPair;
|
||||
if (!string.IsNullOrEmpty(blockPair) && !handler.Attribute.IsBlockIntermediate)
|
||||
|
||||
@@ -248,6 +248,7 @@ internal class CodeFlowStatements : StatementRuntimeInformation
|
||||
{
|
||||
RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack<string>(RuntimeInfo.InParametersStack)));
|
||||
RuntimeInfo.InParametersStack.Clear();
|
||||
BindNamedParameters(key);
|
||||
|
||||
if (RuntimeInfo.Functions.TryGetValue(key, out int value))
|
||||
{
|
||||
|
||||
@@ -19,17 +19,9 @@ internal class FunctionStatements : StatementRuntimeInformation
|
||||
return;
|
||||
}
|
||||
|
||||
string functionDeclaration = args.Trim();
|
||||
if (!functionDeclaration.EndsWith(':'))
|
||||
if (!TryParseFunctionSignature(args, out string key, out _))
|
||||
{
|
||||
RuntimeInfo.Exit(ExitMessages.InvalidSyntaxColonRequired, true);
|
||||
return;
|
||||
}
|
||||
|
||||
string key = NormalizeBlockName(functionDeclaration);
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
RuntimeInfo.Exit(ExitMessages.InvalidSyntax, true);
|
||||
RuntimeInfo.Exit(args.Trim().Contains(':') ? ExitMessages.InvalidSyntax : ExitMessages.InvalidSyntaxColonRequired, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -83,6 +75,7 @@ internal class FunctionStatements : StatementRuntimeInformation
|
||||
|
||||
RuntimeInfo.FunctionCallStack.Push(new FunctionScope(RuntimeInfo.LineNumber, new Stack<string>(RuntimeInfo.InParametersStack)));
|
||||
RuntimeInfo.InParametersStack.Clear();
|
||||
BindNamedParameters(key);
|
||||
RuntimeInfo.CurrentLine = string.Empty;
|
||||
|
||||
if (RuntimeInfo.Functions.TryGetValue(key, out int value))
|
||||
|
||||
Reference in New Issue
Block a user