Make return a regular statement instead of an expression
This commit is contained in:
parent
18b22cd5d1
commit
f3ed26f131
15
ppp_ast.py
15
ppp_ast.py
@ -202,16 +202,6 @@ class LoopComprehension(Expression):
|
|||||||
|
|
||||||
def precedence(self) -> int: return 13
|
def precedence(self) -> int: return 13
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Return(Expression):
|
|
||||||
expression: Expression
|
|
||||||
|
|
||||||
def represent(self) -> str:
|
|
||||||
# TODO: This will have to be improved
|
|
||||||
return "return "+self.wrap(self.expression)
|
|
||||||
|
|
||||||
def precedence(self) -> int: return 0
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Lambda(Expression):
|
class Lambda(Expression):
|
||||||
parameters: List[TypeDeclaration]
|
parameters: List[TypeDeclaration]
|
||||||
@ -484,7 +474,6 @@ class DoWhileStatement(Statement):
|
|||||||
body: Statement
|
body: Statement
|
||||||
condition: Optional[Expression]
|
condition: Optional[Expression]
|
||||||
|
|
||||||
# TODO: Maybe do something similar to return with these two?
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class BreakStatement(Statement):
|
class BreakStatement(Statement):
|
||||||
pass
|
pass
|
||||||
@ -493,6 +482,10 @@ class BreakStatement(Statement):
|
|||||||
class ContinueStatement(Statement):
|
class ContinueStatement(Statement):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ReturnStatement(Statement):
|
||||||
|
expression: Expression
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class MatchStatement(Statement):
|
class MatchStatement(Statement):
|
||||||
value: Expression
|
value: Expression
|
||||||
|
@ -3,11 +3,11 @@ from typing import Dict, List as List_, Optional, Tuple
|
|||||||
|
|
||||||
from ppp_ast import *
|
from ppp_ast import *
|
||||||
from ppp_lexer import Lexer
|
from ppp_lexer import Lexer
|
||||||
from ppp_object import Bool, EnumValue, Function, Int, Object, Str, Struct, Tuple as TupleObject, List as ListObject, Return as ReturnObject, TypeObject, Void
|
from ppp_object import Bool, EnumValue, Function, Int, Object, Str, Struct, Tuple as TupleObject, List as ListObject, TypeObject, Void
|
||||||
from ppp_parser import is_valid_target, parse_statement
|
from ppp_parser import is_valid_target, parse_statement
|
||||||
from ppp_tokens import EofToken
|
from ppp_tokens import EofToken
|
||||||
from ppp_stdlib import variables
|
from ppp_stdlib import variables
|
||||||
from ppp_types import EnumType, FunctionType, GenericType, Int as IntType, ListType, ReturnType, Str as StrType, StructType, TupleType, Type, TypeType, VariableType, Void as VoidType
|
from ppp_types import EnumType, FunctionType, GenericType, Int as IntType, ListType, Str as StrType, StructType, TupleType, Type, TypeType, VariableType, Void as VoidType
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Declared:
|
class Declared:
|
||||||
@ -218,9 +218,6 @@ def calculate_expression(expression: Expression, program: ProgramState) -> Objec
|
|||||||
case Int(num): return Str(left_value.str % num)
|
case Int(num): return Str(left_value.str % num)
|
||||||
case _: assert False, ("Unimplemented", right_value)
|
case _: assert False, ("Unimplemented", right_value)
|
||||||
assert False, ("Unimplemented", lhs, rhs)
|
assert False, ("Unimplemented", lhs, rhs)
|
||||||
case Return(expression):
|
|
||||||
value = calculate_expression(expression, program)
|
|
||||||
return ReturnObject(ReturnType(value.get_type()), value)
|
|
||||||
case StructInstantiation(struct_, arguments_):
|
case StructInstantiation(struct_, arguments_):
|
||||||
struct = calculate_expression(struct_, program)
|
struct = calculate_expression(struct_, program)
|
||||||
assert isinstance(struct, TypeObject)
|
assert isinstance(struct, TypeObject)
|
||||||
@ -417,8 +414,7 @@ def interpret_statements(statements: List_[Statement], program: ProgramState) ->
|
|||||||
for statement in statements:
|
for statement in statements:
|
||||||
match statement:
|
match statement:
|
||||||
case ExpressionStatement(expression):
|
case ExpressionStatement(expression):
|
||||||
value = calculate_expression(expression, program)
|
calculate_expression(expression, program)
|
||||||
if isinstance(value, ReturnObject): return ReturnResult(value.value)
|
|
||||||
case Assignment(lhs, rhs, type_):
|
case Assignment(lhs, rhs, type_):
|
||||||
assert is_valid_target(lhs)
|
assert is_valid_target(lhs)
|
||||||
match lhs:
|
match lhs:
|
||||||
@ -552,6 +548,8 @@ def interpret_statements(statements: List_[Statement], program: ProgramState) ->
|
|||||||
case _: assert False, ("Unimplemented", return_value)
|
case _: assert False, ("Unimplemented", return_value)
|
||||||
case ContinueStatement(): return ContinueResult()
|
case ContinueStatement(): return ContinueResult()
|
||||||
case BreakStatement(): return BreakResult()
|
case BreakStatement(): return BreakResult()
|
||||||
|
case ReturnStatement(expression=expression):
|
||||||
|
return ReturnResult(calculate_expression(expression, program))
|
||||||
case Import(file):
|
case Import(file):
|
||||||
# TODO: Maybe an inclusion system within a preprocessor maybe
|
# TODO: Maybe an inclusion system within a preprocessor maybe
|
||||||
module = interpret_file(file, program.modules) if file not in program.modules else program.modules[file]
|
module = interpret_file(file, program.modules) if file not in program.modules else program.modules[file]
|
||||||
@ -578,7 +576,7 @@ def interpret_file(file_path: str, modules: Dict[str, Module]) -> Module:
|
|||||||
assert len(program.contexts) == 2
|
assert len(program.contexts) == 2
|
||||||
match return_value:
|
match return_value:
|
||||||
case NothingResult(): pass
|
case NothingResult(): pass
|
||||||
case ReturnObject(_): assert False, "Cannot return from outside a function!"
|
case ReturnResult(_): assert False, "Cannot return from outside a function!"
|
||||||
case ContinueResult(): assert False, "Cannot continue from outside a loop!"
|
case ContinueResult(): assert False, "Cannot continue from outside a loop!"
|
||||||
case BreakResult(): assert False, "Cannot break from outside a loop!"
|
case BreakResult(): assert False, "Cannot break from outside a loop!"
|
||||||
case _: assert False, ("Unimplemented", return_value)
|
case _: assert False, ("Unimplemented", return_value)
|
||||||
|
@ -5,7 +5,7 @@ from dataclasses import dataclass
|
|||||||
from typing import Callable, Dict, List as List_, Tuple as Tuple_
|
from typing import Callable, Dict, List as List_, Tuple as Tuple_
|
||||||
|
|
||||||
from ppp_ast import Statement
|
from ppp_ast import Statement
|
||||||
from ppp_types import ArrayType, EnumType, FunctionType, ListType, ReturnType, StructType, TupleType, Type, Int as IntType, Str as StrType, Bool as BoolType, Void as VoidType, TypeType
|
from ppp_types import ArrayType, EnumType, FunctionType, ListType, StructType, TupleType, Type, Int as IntType, Str as StrType, Bool as BoolType, Void as VoidType, TypeType
|
||||||
|
|
||||||
class Object(ABC):
|
class Object(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@ -68,13 +68,6 @@ class Function(Object):
|
|||||||
|
|
||||||
def get_type(self) -> Type: return self.type
|
def get_type(self) -> Type: return self.type
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Return(Object):
|
|
||||||
type: ReturnType
|
|
||||||
value: Object
|
|
||||||
|
|
||||||
def get_type(self) -> Type: return self.type
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EnumValue(Object):
|
class EnumValue(Object):
|
||||||
type: EnumType
|
type: EnumType
|
||||||
|
@ -173,7 +173,6 @@ def parse_unary(lexer: Lexer) -> Expression:
|
|||||||
if lexer.take_token(SymbolToken(Symbol.Exclamation)): return Not(parse_unary(lexer))
|
if lexer.take_token(SymbolToken(Symbol.Exclamation)): return Not(parse_unary(lexer))
|
||||||
if lexer.take_token(SymbolToken(Symbol.Plus)): return UnaryPlus(parse_unary(lexer))
|
if lexer.take_token(SymbolToken(Symbol.Plus)): return UnaryPlus(parse_unary(lexer))
|
||||||
if lexer.take_token(SymbolToken(Symbol.Dash)): return UnaryMinus(parse_unary(lexer))
|
if lexer.take_token(SymbolToken(Symbol.Dash)): return UnaryMinus(parse_unary(lexer))
|
||||||
if lexer.take_token(KeywordToken(Keyword.Return)): return Return(parse_unary(lexer))
|
|
||||||
return parse_primary(lexer)
|
return parse_primary(lexer)
|
||||||
|
|
||||||
Precedence = Dict[Symbol, Callable[[Expression, Expression], Expression]]
|
Precedence = Dict[Symbol, Callable[[Expression, Expression], Expression]]
|
||||||
@ -209,7 +208,6 @@ def parse_ternary(lexer: Lexer) -> Expression:
|
|||||||
return Ternary(expression, if_true, if_false)
|
return Ternary(expression, if_true, if_false)
|
||||||
|
|
||||||
def parse_expression(lexer: Lexer) -> Expression:
|
def parse_expression(lexer: Lexer) -> Expression:
|
||||||
if lexer.take_token(KeywordToken(Keyword.Return)): return Return(parse_expression(lexer))
|
|
||||||
if lexer.take_token(KeywordToken(Keyword.Lambda)):
|
if lexer.take_token(KeywordToken(Keyword.Lambda)):
|
||||||
parameters: List[TypeDeclaration]
|
parameters: List[TypeDeclaration]
|
||||||
if lexer.take_token(SymbolToken(Symbol.EqualArrow)):
|
if lexer.take_token(SymbolToken(Symbol.EqualArrow)):
|
||||||
@ -290,6 +288,10 @@ def parse_statement(lexer: Lexer) -> Statement:
|
|||||||
elif lexer.take_token(KeywordToken(Keyword.Continue)):
|
elif lexer.take_token(KeywordToken(Keyword.Continue)):
|
||||||
lexer.assert_token(SymbolToken(Symbol.Semicolon))
|
lexer.assert_token(SymbolToken(Symbol.Semicolon))
|
||||||
return ContinueStatement()
|
return ContinueStatement()
|
||||||
|
elif lexer.take_token(KeywordToken(Keyword.Return)):
|
||||||
|
expression = parse_expression(lexer)
|
||||||
|
lexer.assert_token(SymbolToken(Symbol.Semicolon))
|
||||||
|
return ReturnStatement(expression)
|
||||||
elif lexer.take_token(KeywordToken(Keyword.Do)):
|
elif lexer.take_token(KeywordToken(Keyword.Do)):
|
||||||
body = parse_statement(lexer)
|
body = parse_statement(lexer)
|
||||||
condition: Optional[Expression] = None
|
condition: Optional[Expression] = None
|
||||||
@ -330,8 +332,10 @@ def parse_statement(lexer: Lexer) -> Statement:
|
|||||||
elif lexer.take_token(KeywordToken(Keyword.Defer)):
|
elif lexer.take_token(KeywordToken(Keyword.Defer)):
|
||||||
statement = parse_statement(lexer)
|
statement = parse_statement(lexer)
|
||||||
return DeferStatement(statement)
|
return DeferStatement(statement)
|
||||||
elif lexer.check_tokenkind(KeywordToken) and not lexer.check_tokens(KeywordToken(Keyword.Return), KeywordToken(Keyword.Lambda)):
|
elif lexer.check_tokenkind(KeywordToken) and not lexer.check_token(KeywordToken(Keyword.Lambda)): # TODO: Maybe use '\' for lambda instead of a keyword
|
||||||
assert False, ("Unimplemented", lexer.next_token(), lexer.next_token(), lexer.next_token())
|
token = lexer.next_token()
|
||||||
|
assert isinstance(token.contents, KeywordToken)
|
||||||
|
raise SyntaxError(f"{token.loc}: Unexpected keyword: '{token.contents.keyword}'")
|
||||||
elif lexer.take_token(SymbolToken(Symbol.OpenCurly)):
|
elif lexer.take_token(SymbolToken(Symbol.OpenCurly)):
|
||||||
statements: List[Statement] = []
|
statements: List[Statement] = []
|
||||||
while not lexer.take_token(SymbolToken(Symbol.CloseCurly)):
|
while not lexer.take_token(SymbolToken(Symbol.CloseCurly)):
|
||||||
|
@ -23,6 +23,8 @@ class Keyword(Enum):
|
|||||||
Type = 'type'
|
Type = 'type'
|
||||||
Defer = 'defer'
|
Defer = 'defer'
|
||||||
|
|
||||||
|
def __str__(self) -> str: return self._value_
|
||||||
|
|
||||||
class Symbol(Enum):
|
class Symbol(Enum):
|
||||||
Open = '('
|
Open = '('
|
||||||
Close = ')'
|
Close = ')'
|
||||||
|
16
ppp_types.py
16
ppp_types.py
@ -164,22 +164,6 @@ class ObjectType(Primitive):
|
|||||||
def represent(self) -> str: return 'object'
|
def represent(self) -> str: return 'object'
|
||||||
Object = ObjectType()
|
Object = ObjectType()
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ReturnType(Type):
|
|
||||||
type: Type
|
|
||||||
|
|
||||||
def represent(self) -> str: return f"return<{self.type.represent()}>"
|
|
||||||
|
|
||||||
def fill(self, types: Dict[str, Type], stack: List[int]) -> Type:
|
|
||||||
if id(self) in stack: return self
|
|
||||||
self.type = self.type.fill(types, stack+[id(self)])
|
|
||||||
return self
|
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
|
||||||
assert id(self) not in stack
|
|
||||||
is_new, new_type = self.type.new_fill(types, stack+[id(self)])
|
|
||||||
return (is_new, ReturnType(new_type))
|
|
||||||
|
|
||||||
|
|
||||||
num_expressions: int = 0
|
num_expressions: int = 0
|
||||||
@dataclass
|
@dataclass
|
||||||
|
Loading…
Reference in New Issue
Block a user