mirror of
https://github.com/Stone-Red-Code/YesNt-Interpreter.git
synced 2026-09-04 00:56:31 +02:00
Make end_func the only func ending block
This commit is contained in:
+2
-1
@@ -47,6 +47,7 @@ If you pass a file path, it is loaded on startup.
|
||||
## Formatter behavior (quick summary)
|
||||
|
||||
- Indents `func`, `if`, `else`, and `while` blocks.
|
||||
- Dedents on `return`, `end_func`, `end_if`, and `end_while`.
|
||||
- Dedents on `end_func`, `end_if`, and `end_while`.
|
||||
- `return` / `return <value>` are regular body statements and stay indented with the block they are in.
|
||||
- `exit` / `throw` / `error` close active non-function blocks for following lines.
|
||||
- Comment lines (`# ...`) are kept unindented.
|
||||
|
||||
@@ -261,15 +261,11 @@ internal class TextEditor
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (trimmed == "return" || trimmed == "end_func" || trimmed.StartsWith("return ", StringComparison.Ordinal))
|
||||
else if (trimmed == "end_func")
|
||||
{
|
||||
for (int j = blockStack.Count - 1; j >= 0; j--)
|
||||
if (blockStack.Count > 0 && blockStack[^1] == "func")
|
||||
{
|
||||
if (blockStack[j] == "func")
|
||||
{
|
||||
blockStack.RemoveAt(j);
|
||||
break;
|
||||
}
|
||||
blockStack.RemoveAt(blockStack.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ public class CodeFlowTests
|
||||
"func yes:",
|
||||
"global result = 1",
|
||||
"return",
|
||||
"end_func",
|
||||
"${result}"
|
||||
];
|
||||
YesNtAssert.IsLastLineEqual(lines, "1");
|
||||
@@ -193,6 +194,7 @@ public class CodeFlowTests
|
||||
"func set_result:",
|
||||
"global result = ok",
|
||||
"return",
|
||||
"end_func",
|
||||
"if 1 == 1 call set_result",
|
||||
"${result}"
|
||||
];
|
||||
|
||||
@@ -124,9 +124,13 @@ public class FunctionStatementsTests
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"goto main",
|
||||
"func outer:",
|
||||
"func inner:",
|
||||
"return"
|
||||
"return",
|
||||
"end_func",
|
||||
"label main:",
|
||||
"call outer"
|
||||
];
|
||||
|
||||
YesNtAssert.ContainsTerminationMessage(lines, "Nested functions are not allowed");
|
||||
@@ -414,10 +418,64 @@ public class FunctionStatementsTests
|
||||
"call add with 3, 4",
|
||||
"func add: a, b",
|
||||
"return ${a} + ${b} calc",
|
||||
"end_func",
|
||||
"var total = %out",
|
||||
"${total}"
|
||||
];
|
||||
|
||||
YesNtAssert.IsLastLineEqual(lines, "7");
|
||||
}
|
||||
|
||||
// --- Top-down function body skip tests ---
|
||||
|
||||
[TestMethod]
|
||||
public void FunctionDeclaredFirstThenCalledTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"func add: a, b",
|
||||
"return ${a} + ${b} calc",
|
||||
"end_func",
|
||||
"call add with 3, 7",
|
||||
"var total = %out",
|
||||
"${total}"
|
||||
];
|
||||
|
||||
YesNtAssert.IsLastLineEqual(lines, "10");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FunctionBodyWithNestedReturnSkippedTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"func test: a, b",
|
||||
"if ${a} == ${b}:",
|
||||
"print_line %in",
|
||||
"return 999",
|
||||
"end_if",
|
||||
"return ${a} + ${b} calc",
|
||||
"end_func",
|
||||
"call test with 1, 2, 4",
|
||||
"var value = %out",
|
||||
"${value}"
|
||||
];
|
||||
|
||||
YesNtAssert.IsLastLineEqual(lines, "3");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FunctionWithoutEndFuncFailsTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"func answer:",
|
||||
"return 42",
|
||||
"call answer",
|
||||
"var value = %out",
|
||||
"${value}"
|
||||
];
|
||||
|
||||
YesNtAssert.ContainsTerminationMessage(lines, "no matching \"end_func\"");
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,11 @@ internal static class ExitMessages
|
||||
return $"Function \"{function}\" not found";
|
||||
}
|
||||
|
||||
internal static string FunctionWithoutEndFunc(string function)
|
||||
{
|
||||
return $"Function \"{function}\" has no matching \"end_func\"";
|
||||
}
|
||||
|
||||
internal static string VariableNotFound(string variable)
|
||||
{
|
||||
return $"Variable \"{variable}\" not found";
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace YesNt.Interpreter.Statements;
|
||||
|
||||
internal class FunctionStatements : StatementRuntimeInformation
|
||||
{
|
||||
[Statement("func", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, ExecuteInSearchMode = true, Separator = ":")]
|
||||
[Statement("func", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, ExecuteInSearchMode = true, Separator = ":", BlockPair = "end_func")]
|
||||
public void FindFunction(string args)
|
||||
{
|
||||
if (RuntimeInfo.InternalIsInFunction)
|
||||
@@ -32,8 +32,27 @@ internal class FunctionStatements : StatementRuntimeInformation
|
||||
RuntimeInfo.SearchFunction = string.Empty;
|
||||
}
|
||||
|
||||
bool isDefinitionScan = RuntimeInfo.FunctionCallStack.Count == 0
|
||||
&& string.IsNullOrEmpty(RuntimeInfo.SearchFunction)
|
||||
&& string.IsNullOrEmpty(RuntimeInfo.SearchLabel);
|
||||
|
||||
if (isDefinitionScan)
|
||||
{
|
||||
if (RuntimeInfo.BlockBoundaries.TryGetValue(RuntimeInfo.LineNumber, out int endLine) && endLine > RuntimeInfo.LineNumber)
|
||||
{
|
||||
RuntimeInfo.IsInFunction = false;
|
||||
RuntimeInfo.LineNumber = endLine;
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.Exit(ExitMessages.FunctionWithoutEndFunc(key), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeInfo.IsInFunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Statement("push_in", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)]
|
||||
public void AddInParameter(string args)
|
||||
@@ -126,7 +145,7 @@ internal class FunctionStatements : StatementRuntimeInformation
|
||||
RuntimeInfo.FunctionCallStack.Peek().Results.Push(args);
|
||||
}
|
||||
|
||||
[Statement("end_func", SearchMode.Exact, SpaceAround.None, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)]
|
||||
[Statement("end_func", SearchMode.Exact, SpaceAround.None, ConsoleColor.DarkYellow, ExecuteInSearchMode = true, IsBlockEnd = true)]
|
||||
public void EndFunction(string _)
|
||||
{
|
||||
HandleReturn(string.Empty);
|
||||
|
||||
Reference in New Issue
Block a user