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)
|
## Formatter behavior (quick summary)
|
||||||
|
|
||||||
- Indents `func`, `if`, `else`, and `while` blocks.
|
- 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.
|
- `exit` / `throw` / `error` close active non-function blocks for following lines.
|
||||||
- Comment lines (`# ...`) are kept unindented.
|
- 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(blockStack.Count - 1);
|
||||||
{
|
|
||||||
blockStack.RemoveAt(j);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public class CodeFlowTests
|
|||||||
"func yes:",
|
"func yes:",
|
||||||
"global result = 1",
|
"global result = 1",
|
||||||
"return",
|
"return",
|
||||||
|
"end_func",
|
||||||
"${result}"
|
"${result}"
|
||||||
];
|
];
|
||||||
YesNtAssert.IsLastLineEqual(lines, "1");
|
YesNtAssert.IsLastLineEqual(lines, "1");
|
||||||
@@ -193,6 +194,7 @@ public class CodeFlowTests
|
|||||||
"func set_result:",
|
"func set_result:",
|
||||||
"global result = ok",
|
"global result = ok",
|
||||||
"return",
|
"return",
|
||||||
|
"end_func",
|
||||||
"if 1 == 1 call set_result",
|
"if 1 == 1 call set_result",
|
||||||
"${result}"
|
"${result}"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -124,9 +124,13 @@ public class FunctionStatementsTests
|
|||||||
{
|
{
|
||||||
List<string> lines =
|
List<string> lines =
|
||||||
[
|
[
|
||||||
|
"goto main",
|
||||||
"func outer:",
|
"func outer:",
|
||||||
"func inner:",
|
"func inner:",
|
||||||
"return"
|
"return",
|
||||||
|
"end_func",
|
||||||
|
"label main:",
|
||||||
|
"call outer"
|
||||||
];
|
];
|
||||||
|
|
||||||
YesNtAssert.ContainsTerminationMessage(lines, "Nested functions are not allowed");
|
YesNtAssert.ContainsTerminationMessage(lines, "Nested functions are not allowed");
|
||||||
@@ -414,10 +418,64 @@ public class FunctionStatementsTests
|
|||||||
"call add with 3, 4",
|
"call add with 3, 4",
|
||||||
"func add: a, b",
|
"func add: a, b",
|
||||||
"return ${a} + ${b} calc",
|
"return ${a} + ${b} calc",
|
||||||
|
"end_func",
|
||||||
"var total = %out",
|
"var total = %out",
|
||||||
"${total}"
|
"${total}"
|
||||||
];
|
];
|
||||||
|
|
||||||
YesNtAssert.IsLastLineEqual(lines, "7");
|
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";
|
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)
|
internal static string VariableNotFound(string variable)
|
||||||
{
|
{
|
||||||
return $"Variable \"{variable}\" not found";
|
return $"Variable \"{variable}\" not found";
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace YesNt.Interpreter.Statements;
|
|||||||
|
|
||||||
internal class FunctionStatements : StatementRuntimeInformation
|
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)
|
public void FindFunction(string args)
|
||||||
{
|
{
|
||||||
if (RuntimeInfo.InternalIsInFunction)
|
if (RuntimeInfo.InternalIsInFunction)
|
||||||
@@ -32,7 +32,26 @@ internal class FunctionStatements : StatementRuntimeInformation
|
|||||||
RuntimeInfo.SearchFunction = string.Empty;
|
RuntimeInfo.SearchFunction = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeInfo.IsInFunction = true;
|
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)]
|
[Statement("push_in", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.Yellow)]
|
||||||
@@ -126,7 +145,7 @@ internal class FunctionStatements : StatementRuntimeInformation
|
|||||||
RuntimeInfo.FunctionCallStack.Peek().Results.Push(args);
|
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 _)
|
public void EndFunction(string _)
|
||||||
{
|
{
|
||||||
HandleReturn(string.Empty);
|
HandleReturn(string.Empty);
|
||||||
|
|||||||
Reference in New Issue
Block a user