added goto
This commit is contained in:
36
main.py
36
main.py
@@ -2080,6 +2080,40 @@ def macro_inline(ctx: MacroContext) -> Optional[List[Op]]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _require_definition_context(parser: "Parser", word_name: str) -> Definition:
|
||||||
|
if not parser.context_stack or not isinstance(parser.context_stack[-1], Definition):
|
||||||
|
raise ParseError(f"'{word_name}' can only appear inside a definition")
|
||||||
|
return parser.context_stack[-1]
|
||||||
|
|
||||||
|
|
||||||
|
def macro_label(ctx: MacroContext) -> Optional[List[Op]]:
|
||||||
|
parser = ctx.parser
|
||||||
|
if parser._eof():
|
||||||
|
raise ParseError("label name missing after 'label'")
|
||||||
|
tok = parser.next_token()
|
||||||
|
name = tok.lexeme
|
||||||
|
if not _is_identifier(name):
|
||||||
|
raise ParseError(f"invalid label name '{name}'")
|
||||||
|
definition = _require_definition_context(parser, "label")
|
||||||
|
if any(node.op == "label" and node.data == name for node in definition.body):
|
||||||
|
raise ParseError(f"duplicate label '{name}' in definition '{definition.name}'")
|
||||||
|
parser.emit_node(Op(op="label", data=name))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def macro_goto(ctx: MacroContext) -> Optional[List[Op]]:
|
||||||
|
parser = ctx.parser
|
||||||
|
if parser._eof():
|
||||||
|
raise ParseError("label name missing after 'goto'")
|
||||||
|
tok = parser.next_token()
|
||||||
|
name = tok.lexeme
|
||||||
|
if not _is_identifier(name):
|
||||||
|
raise ParseError(f"invalid label name '{name}'")
|
||||||
|
_require_definition_context(parser, "goto")
|
||||||
|
parser.emit_node(Op(op="jump", data=name))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def macro_compile_time(ctx: MacroContext) -> Optional[List[Op]]:
|
def macro_compile_time(ctx: MacroContext) -> Optional[List[Op]]:
|
||||||
"""Run the next word at compile time and still emit it for runtime."""
|
"""Run the next word at compile time and still emit it for runtime."""
|
||||||
parser = ctx.parser
|
parser = ctx.parser
|
||||||
@@ -2864,6 +2898,8 @@ def bootstrap_dictionary() -> Dictionary:
|
|||||||
dictionary.register(Word(name="immediate", immediate=True, macro=macro_immediate))
|
dictionary.register(Word(name="immediate", immediate=True, macro=macro_immediate))
|
||||||
dictionary.register(Word(name="compile-only", immediate=True, macro=macro_compile_only))
|
dictionary.register(Word(name="compile-only", immediate=True, macro=macro_compile_only))
|
||||||
dictionary.register(Word(name="inline", immediate=True, macro=macro_inline))
|
dictionary.register(Word(name="inline", immediate=True, macro=macro_inline))
|
||||||
|
dictionary.register(Word(name="label", immediate=True, macro=macro_label))
|
||||||
|
dictionary.register(Word(name="goto", immediate=True, macro=macro_goto))
|
||||||
dictionary.register(Word(name="compile-time", immediate=True, macro=macro_compile_time))
|
dictionary.register(Word(name="compile-time", immediate=True, macro=macro_compile_time))
|
||||||
dictionary.register(Word(name="here", immediate=True, macro=macro_here))
|
dictionary.register(Word(name="here", immediate=True, macro=macro_here))
|
||||||
dictionary.register(Word(name="with", immediate=True, macro=macro_with))
|
dictionary.register(Word(name="with", immediate=True, macro=macro_with))
|
||||||
|
|||||||
3
tests/goto.expected
Normal file
3
tests/goto.expected
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
12
tests/goto.sl
Normal file
12
tests/goto.sl
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import stdlib/stdlib.sl
|
||||||
|
import stdlib/io.sl
|
||||||
|
|
||||||
|
word main
|
||||||
|
3
|
||||||
|
label loop
|
||||||
|
dup puti cr
|
||||||
|
1 -
|
||||||
|
dup 0 >
|
||||||
|
if goto loop end
|
||||||
|
drop
|
||||||
|
end
|
||||||
1
tests/goto.test
Normal file
1
tests/goto.test
Normal file
@@ -0,0 +1 @@
|
|||||||
|
python main.py tests/goto.sl -o /tmp/goto > /dev/null && /tmp/goto
|
||||||
Reference in New Issue
Block a user