mirror of
https://github.com/Stone-Red-Code/YesNt-Interpreter.git
synced 2026-09-04 00:56:31 +02:00
Rename return to end_func and add proper return statment
This commit is contained in:
@@ -43,12 +43,11 @@ YesNt is intentionally minimal and is well suited for:
|
||||
func greet:
|
||||
var name = %in
|
||||
print_line Hello, ${name}!
|
||||
return
|
||||
end_func
|
||||
|
||||
func add:
|
||||
var result = %in + %in calc
|
||||
push_out ${result}
|
||||
return
|
||||
return ${result}
|
||||
|
||||
call greet with Alice
|
||||
call greet with Bob
|
||||
|
||||
+5
-2
@@ -26,7 +26,7 @@ var name = world
|
||||
func greet:
|
||||
print_line "Hello world"
|
||||
print_line Hello ${name}
|
||||
return
|
||||
end_func
|
||||
call greet
|
||||
```
|
||||
|
||||
@@ -87,7 +87,8 @@ print_line ${value}
|
||||
| Functions | `put value` | `push_out value` | Push out-arg in function. |
|
||||
| Functions | `%out` | `%out` | Keep token name for familiarity. |
|
||||
| Functions | `%iso` | `%has_out` | Inline token, bool if out arg exists. |
|
||||
| Functions | `ret` | `return` | Return from function. |
|
||||
| Functions | `ret` | `end_func` | Return from function. |
|
||||
| Functions | `return value` | `return value` | Return from function, optionally pushing a value to the out stack. |
|
||||
| Functions | `ccs` | `clear_call_stack` | Clear call stack. |
|
||||
| Condition-call | `cif name \| cond` | `if cond call name` | Conditional function call. |
|
||||
| Termination | `end` | `exit` | Planned termination. |
|
||||
@@ -113,4 +114,6 @@ print_line ${value}
|
||||
|
||||
- `%out` is intentionally kept as `%out`.
|
||||
- Postfix operations are `calc`, `eval`, and `task`.
|
||||
- `return` exits the function early (optionally with a value via `return <value>`);
|
||||
`end_func` is the explicit end-of-function marker. Both terminate the current function call.
|
||||
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ print_line Hello, ${name}!
|
||||
func greet:
|
||||
var msg = Hello, ${name}!
|
||||
print_line ${msg}
|
||||
return
|
||||
end_func
|
||||
|
||||
var name = Bob
|
||||
call greet
|
||||
|
||||
+1
-1
@@ -47,6 +47,6 @@ 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_if`, and `end_while`.
|
||||
- Dedents on `return`, `end_func`, `end_if`, and `end_while`.
|
||||
- `exit` / `throw` / `error` close active non-function blocks for following lines.
|
||||
- Comment lines (`# ...`) are kept unindented.
|
||||
|
||||
@@ -356,18 +356,18 @@ if ${debug} == True call dump_state
|
||||
```
|
||||
func <name>:
|
||||
<body>
|
||||
return
|
||||
end_func
|
||||
```
|
||||
|
||||
A function declaration registers the function name and the line it starts on.
|
||||
The body runs until `return` is reached.
|
||||
The body runs until `end_func` (or an early `return`) is reached.
|
||||
**Nested function declarations are not allowed.**
|
||||
|
||||
```ynt
|
||||
func add:
|
||||
var result = %in + %in calc
|
||||
push_out ${result}
|
||||
return
|
||||
return ${result}
|
||||
end_func
|
||||
```
|
||||
|
||||
### Calling a function - `call`
|
||||
@@ -410,7 +410,7 @@ popped from the argument stack.
|
||||
func greet:
|
||||
var name = %in
|
||||
print_line Hello, ${name}!
|
||||
return
|
||||
end_func
|
||||
```
|
||||
|
||||
#### Check if input argument exists - `%has_in`
|
||||
@@ -421,7 +421,7 @@ Only valid inside a function.
|
||||
```ynt
|
||||
func greet:
|
||||
if %has_in call do_greet
|
||||
return
|
||||
end_func
|
||||
```
|
||||
|
||||
### Output values
|
||||
@@ -462,6 +462,34 @@ clear_call_stack
|
||||
|
||||
Discards all frames on the function call stack. Useful for error recovery.
|
||||
|
||||
### Return from a function - `end_func` and `return`
|
||||
|
||||
```
|
||||
end_func
|
||||
return
|
||||
return <value>
|
||||
```
|
||||
|
||||
`end_func` and a bare `return` end the current function call and hand control back to the caller.
|
||||
`return <value>` does the same but first pushes `<value>` onto the output stack
|
||||
(it is equivalent to `push_out <value>` followed by `end_func`), so the caller can read it with `%out`.
|
||||
`return` may be used anywhere in the body to exit a function early.
|
||||
|
||||
```ynt
|
||||
func add:
|
||||
var a = %in
|
||||
var b = %in
|
||||
if ${a} == 0:
|
||||
return 0
|
||||
end_if
|
||||
return ${a} + ${b} calc
|
||||
|
||||
call add with 0, 5
|
||||
var total = %out
|
||||
print_line ${total}
|
||||
```
|
||||
|
||||
Only valid inside a function; otherwise the script terminates with an error.
|
||||
---
|
||||
|
||||
## Lists
|
||||
@@ -741,7 +769,7 @@ if ${x} < 0 call validate_fail
|
||||
|
||||
func validate_fail:
|
||||
throw x must not be negative
|
||||
return
|
||||
end_func
|
||||
```
|
||||
|
||||
### Non-fatal error - `error`
|
||||
@@ -778,7 +806,8 @@ Like `throw` but does **not** cancel background tasks.
|
||||
| `if … call` | `if cond call name` | Conditional function call |
|
||||
| `push_in` | `push_in value` | Push input argument |
|
||||
| `push_out` | `push_out value` | Push output value (inside function) |
|
||||
| `return` | `return` | Return from function |
|
||||
| `end_func` | `end_func` | End current function |
|
||||
| `return` | `return value` | Return from function (optional value via output stack) |
|
||||
| `clear_call_stack` | `clear_call_stack` | Clear call stack |
|
||||
| `list … new` | `list name new` | Create/reset list |
|
||||
| `list … add` | `list name add value` | Append to list |
|
||||
|
||||
@@ -261,7 +261,7 @@ internal class TextEditor
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (trimmed == "return")
|
||||
else if (trimmed == "return" || trimmed == "end_func" || trimmed.StartsWith("return ", StringComparison.Ordinal))
|
||||
{
|
||||
for (int j = blockStack.Count - 1; j >= 0; j--)
|
||||
{
|
||||
|
||||
@@ -223,4 +223,101 @@ public class FunctionStatementsTests
|
||||
|
||||
YesNtAssert.IsLastLineEqual(lines, "outer_val");
|
||||
}
|
||||
|
||||
// --- end_func / return value tests ---
|
||||
|
||||
[TestMethod]
|
||||
public void EndFuncReturnsToCallerTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"goto main",
|
||||
"func greet:",
|
||||
"global result = done",
|
||||
"end_func",
|
||||
"label main:",
|
||||
"call greet",
|
||||
"${result}"
|
||||
];
|
||||
|
||||
YesNtAssert.IsLastLineEqual(lines, "done");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReturnWithValueTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"goto main",
|
||||
"func add:",
|
||||
"var a = %in",
|
||||
"var b = %in",
|
||||
"var sum = ${a} + ${b} calc",
|
||||
"return ${sum}",
|
||||
"label main:",
|
||||
"call add with 3, 4",
|
||||
"var total = %out",
|
||||
"${total}"
|
||||
];
|
||||
|
||||
YesNtAssert.IsLastLineEqual(lines, "7");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReturnWithLiteralValueTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"goto main",
|
||||
"func make:",
|
||||
"return out_value",
|
||||
"label main:",
|
||||
"call make",
|
||||
"var value = %out",
|
||||
"${value}"
|
||||
];
|
||||
|
||||
YesNtAssert.IsLastLineEqual(lines, "out_value");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReturnEarlyExitSkipsRestOfFunctionTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"goto main",
|
||||
"func probe:",
|
||||
"push_out should_not_escape",
|
||||
"return",
|
||||
"push_out should_never_run",
|
||||
"label main:",
|
||||
"call probe",
|
||||
"var value = %out",
|
||||
"${value}"
|
||||
];
|
||||
|
||||
YesNtAssert.IsLastLineEqual(lines, "should_not_escape");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReturnWithValueOutsideFunctionFailsTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"return 42"
|
||||
];
|
||||
|
||||
YesNtAssert.ContainsTerminationMessage(lines, "Statement not allowed outside of function");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EndFuncOutsideFunctionFailsTest()
|
||||
{
|
||||
List<string> lines =
|
||||
[
|
||||
"end_func"
|
||||
];
|
||||
|
||||
YesNtAssert.ContainsTerminationMessage(lines, "Statement not allowed outside of function");
|
||||
}
|
||||
}
|
||||
@@ -133,8 +133,25 @@ internal class FunctionStatements : StatementRuntimeInformation
|
||||
RuntimeInfo.FunctionCallStack.Peek().Results.Push(args);
|
||||
}
|
||||
|
||||
[Statement("end_func", SearchMode.Exact, SpaceAround.None, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)]
|
||||
public void EndFunction(string _)
|
||||
{
|
||||
HandleReturn(string.Empty);
|
||||
}
|
||||
|
||||
[Statement("return", SearchMode.Exact, SpaceAround.None, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)]
|
||||
public void Return(string _)
|
||||
{
|
||||
HandleReturn(string.Empty);
|
||||
}
|
||||
|
||||
[Statement("return", SearchMode.StartOfLine, SpaceAround.End, ConsoleColor.DarkYellow, ExecuteInSearchMode = true)]
|
||||
public void ReturnWithValue(string args)
|
||||
{
|
||||
HandleReturn(args.Trim());
|
||||
}
|
||||
|
||||
private void HandleReturn(string value)
|
||||
{
|
||||
if (!RuntimeInfo.IsInFunction)
|
||||
{
|
||||
@@ -153,10 +170,14 @@ internal class FunctionStatements : StatementRuntimeInformation
|
||||
return;
|
||||
}
|
||||
|
||||
RuntimeInfo.IsInFunction = false;
|
||||
|
||||
if (RuntimeInfo.FunctionCallStack.Count > 0)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
RuntimeInfo.FunctionCallStack.Peek().Results.Push(value);
|
||||
}
|
||||
|
||||
RuntimeInfo.IsInFunction = false;
|
||||
FunctionScope functionScope = RuntimeInfo.FunctionCallStack.Pop();
|
||||
|
||||
RuntimeInfo.OutParametersStack = new Stack<string>(functionScope.Results);
|
||||
|
||||
Reference in New Issue
Block a user