2023-06-14 21:35:06 +01:00
|
|
|
from __future__ import annotations
|
2023-04-10 03:20:05 +01:00
|
|
|
from typing import Dict, List, Optional, cast
|
2023-04-11 01:33:23 +01:00
|
|
|
from position import Node, Span
|
2023-04-10 03:20:05 +01:00
|
|
|
from utils import Err, Ok, Result
|
2023-04-09 02:48:26 +01:00
|
|
|
import parsed
|
|
|
|
|
|
|
|
class Value:
|
|
|
|
pass
|
|
|
|
|
2023-06-14 21:35:06 +01:00
|
|
|
class UnitValue(Value):
|
2023-04-10 03:20:05 +01:00
|
|
|
def __init__(self) -> None:
|
|
|
|
super().__init__()
|
|
|
|
|
2023-06-14 21:35:06 +01:00
|
|
|
class IntValue(Value):
|
2023-04-09 02:48:26 +01:00
|
|
|
def __init__(self, value: int) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.value = value
|
|
|
|
|
2023-06-14 21:35:06 +01:00
|
|
|
class CharValue(Value):
|
2023-04-09 02:48:26 +01:00
|
|
|
def __init__(self, value: str) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.value = value
|
|
|
|
|
2023-06-14 21:35:06 +01:00
|
|
|
class StringValue(Value):
|
2023-04-09 02:48:26 +01:00
|
|
|
def __init__(self, value: str) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.value = value
|
|
|
|
|
2023-06-14 21:35:06 +01:00
|
|
|
class BoolValue(Value):
|
2023-04-09 02:48:26 +01:00
|
|
|
def __init__(self, value: bool) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.value = value
|
|
|
|
|
2023-06-14 21:35:06 +01:00
|
|
|
class TupleValue(Value):
|
|
|
|
def __init__(self, values: List[Value]) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.values = values
|
|
|
|
|
2023-04-11 01:33:23 +01:00
|
|
|
class Type:
|
|
|
|
pass
|
|
|
|
|
2023-04-09 02:48:26 +01:00
|
|
|
class EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
def __init__(self) -> None:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def is_value(self) -> bool:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def as_value(self) -> ValueResult:
|
|
|
|
raise Exception("guess it wasn't a value")
|
2023-04-09 02:48:26 +01:00
|
|
|
|
|
|
|
class ValueResult(EvalResult):
|
|
|
|
def __init__(self, value: Value) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.value = value
|
|
|
|
|
2023-06-14 21:35:06 +01:00
|
|
|
def is_value(self) -> bool:
|
|
|
|
return True
|
|
|
|
|
|
|
|
def as_value(self) -> ValueResult:
|
|
|
|
return self
|
|
|
|
|
2023-04-09 02:48:26 +01:00
|
|
|
class ReturnResult(EvalResult):
|
|
|
|
def __init__(self, value: Optional[Value]) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.value = value
|
|
|
|
|
|
|
|
class BreakResult(EvalResult):
|
|
|
|
def __init__(self, value: Optional[Value]) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.value = value
|
|
|
|
|
|
|
|
class ContinueResult(EvalResult):
|
|
|
|
def __init__(self, value: Optional[Value]) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.value = value
|
|
|
|
|
2023-04-10 03:20:05 +01:00
|
|
|
class PanicResult(EvalResult):
|
2023-06-14 21:35:06 +01:00
|
|
|
def __init__(self, span: Span, message: str) -> None:
|
2023-04-10 03:20:05 +01:00
|
|
|
super().__init__()
|
2023-06-14 21:35:06 +01:00
|
|
|
self.span = span
|
2023-04-10 03:20:05 +01:00
|
|
|
self.message = message
|
|
|
|
|
|
|
|
class SymbolTable:
|
|
|
|
def __init__(self) -> None:
|
2023-04-11 01:33:23 +01:00
|
|
|
self.values: Dict[str, Value] = {}
|
|
|
|
self.types: Dict[str, Type] = {}
|
|
|
|
|
|
|
|
def define_value(self, symbol_id: str, value: Value) -> Result[None, str]:
|
|
|
|
if symbol_id in self.values:
|
|
|
|
return Err("symbol already defined")
|
|
|
|
self.values[symbol_id] = value
|
|
|
|
return Ok(None)
|
2023-04-10 03:20:05 +01:00
|
|
|
|
2023-04-11 01:33:23 +01:00
|
|
|
def define_type(self, symbol_id: str, value_type: Type) -> Result[None, str]:
|
|
|
|
if symbol_id in self.types:
|
2023-04-10 03:20:05 +01:00
|
|
|
return Err("symbol already defined")
|
2023-04-11 01:33:23 +01:00
|
|
|
self.types[symbol_id] = value_type
|
2023-04-10 03:20:05 +01:00
|
|
|
return Ok(None)
|
|
|
|
|
2023-04-11 01:33:23 +01:00
|
|
|
def value(self, symbol_id: str) -> Optional[Value]:
|
|
|
|
if symbol_id not in self.values:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return self.values[symbol_id]
|
|
|
|
|
|
|
|
def type(self, symbol_id: str) -> Optional[Type]:
|
|
|
|
if symbol_id not in self.types:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return self.types[symbol_id]
|
|
|
|
|
2023-04-09 02:48:26 +01:00
|
|
|
class Evaluator:
|
|
|
|
def __init__(self) -> None:
|
2023-04-11 01:33:23 +01:00
|
|
|
self.table = SymbolTable()
|
2023-04-09 02:48:26 +01:00
|
|
|
|
|
|
|
def evaluate(self, ast: List[Node[parsed.Expr]]) -> None:
|
|
|
|
for node in ast:
|
|
|
|
self.eval_expr(node)
|
|
|
|
|
|
|
|
def eval_expr(self, node: Node[parsed.Expr]) -> EvalResult:
|
2023-04-10 03:20:05 +01:00
|
|
|
if isinstance(node.value, parsed.ExprError):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_expr_error(cast(parsed.ExprError, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Id):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_id(cast(parsed.Id, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Int):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_int(cast(parsed.Int, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Char):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_char(cast(parsed.Char, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.String):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_string(cast(parsed.String, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Bool):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_bool(cast(parsed.Bool, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Unit):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_unit(cast(parsed.Unit, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Tuple):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_tuple(cast(parsed.Tuple, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Block):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_block(cast(parsed.Block, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Lambda):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_lambda(cast(parsed.Lambda, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.If):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_if(cast(parsed.If, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Match):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_match(cast(parsed.Match, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Loop):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_loop(cast(parsed.Loop, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.While):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_while(cast(parsed.While, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.For):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_for(cast(parsed.For, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.StructMember):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_struct_member(cast(parsed.StructMember, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.TupleMember):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_tuple_member(cast(parsed.TupleMember, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Index):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_index(cast(parsed.Index, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Call):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_call(cast(parsed.Call, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Unary):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_unary(cast(parsed.Unary, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Binary):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_binary(cast(parsed.Binary, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Assign):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_assign(cast(parsed.Assign, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Let):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_let(cast(parsed.Let, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Function):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_function(cast(parsed.Function, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Return):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_return(cast(parsed.Return, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Break):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_break(cast(parsed.Break, node.value), node.span)
|
2023-04-10 03:20:05 +01:00
|
|
|
elif isinstance(node.value, parsed.Continue):
|
2023-04-11 01:33:23 +01:00
|
|
|
return self.eval_continue(cast(parsed.Continue, node.value), node.span)
|
2023-04-09 02:48:26 +01:00
|
|
|
else:
|
2023-04-10 03:20:05 +01:00
|
|
|
raise NotImplementedError(str(node))
|
2023-04-09 02:48:26 +01:00
|
|
|
|
2023-04-11 01:33:23 +01:00
|
|
|
def eval_expr_error(self, expr: parsed.ExprError, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
return PanicResult(span, f"error: {expr.message}, at {span}")
|
2023-04-11 01:33:23 +01:00
|
|
|
|
|
|
|
def eval_id(self, expr: parsed.Id, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
value = self.table.value(expr.value)
|
|
|
|
if not value:
|
|
|
|
return PanicResult(span, f"undeclared identifier \"{expr.value}\"")
|
|
|
|
return ValueResult(value)
|
2023-04-11 01:33:23 +01:00
|
|
|
|
|
|
|
def eval_int(self, expr: parsed.Int, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
return ValueResult(IntValue(expr.value))
|
2023-04-11 01:33:23 +01:00
|
|
|
|
|
|
|
def eval_char(self, expr: parsed.Char, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
return ValueResult(CharValue(expr.value))
|
2023-04-11 01:33:23 +01:00
|
|
|
|
|
|
|
def eval_string(self, expr: parsed.String, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
return ValueResult(StringValue(expr.value))
|
2023-04-11 01:33:23 +01:00
|
|
|
|
|
|
|
def eval_bool(self, expr: parsed.Bool, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
return ValueResult(BoolValue(expr.value))
|
2023-04-11 01:33:23 +01:00
|
|
|
|
|
|
|
def eval_unit(self, expr: parsed.Unit, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
return ValueResult(UnitValue())
|
2023-04-11 01:33:23 +01:00
|
|
|
|
|
|
|
def eval_tuple(self, expr: parsed.Tuple, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
values: List[Value] = []
|
|
|
|
for value in expr.values:
|
|
|
|
evaluated = self.eval_expr(value)
|
|
|
|
if not evaluated.is_value():
|
|
|
|
return evaluated
|
|
|
|
values.append(evaluated.as_value().value)
|
|
|
|
return ValueResult(TupleValue(values))
|
2023-04-11 01:33:23 +01:00
|
|
|
|
|
|
|
def eval_block(self, expr: parsed.Block, span: Span) -> EvalResult:
|
2023-06-14 21:35:06 +01:00
|
|
|
for statement in expr.statements:
|
|
|
|
evaluated = self.eval_expr(statement)
|
|
|
|
if not evaluated.is_value():
|
|
|
|
return evaluated
|
2023-04-11 01:33:23 +01:00
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_lambda(self, expr: parsed.Lambda, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_if(self, expr: parsed.If, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_match(self, expr: parsed.Match, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_loop(self, expr: parsed.Loop, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_while(self, expr: parsed.While, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_for(self, expr: parsed.For, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_struct_member(self, expr: parsed.StructMember, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_tuple_member(self, expr: parsed.TupleMember, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_index(self, expr: parsed.Index, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_call(self, expr: parsed.Call, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_unary(self, expr: parsed.Unary, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_binary(self, expr: parsed.Binary, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_assign(self, expr: parsed.Assign, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_let(self, expr: parsed.Let, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_function(self, expr: parsed.Function, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_return(self, expr: parsed.Return, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_break(self, expr: parsed.Break, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
def eval_continue(self, expr: parsed.Continue, span: Span) -> EvalResult:
|
|
|
|
raise NotImplementedError()
|
|
|
|
|