diff --git a/.gitignore b/.gitignore index fbc3dfd..53108de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ __pycache__ .mypy_cache +session.vim diff --git a/evaluator.py b/evaluator.py index c1b258b..077ac12 100644 --- a/evaluator.py +++ b/evaluator.py @@ -1,3 +1,4 @@ +from __future__ import annotations from typing import Dict, List, Optional, cast from position import Node, Span from utils import Err, Ok, Result @@ -6,41 +7,59 @@ import parsed class Value: pass -class Unit(Value): +class UnitValue(Value): def __init__(self) -> None: super().__init__() -class Int(Value): +class IntValue(Value): def __init__(self, value: int) -> None: super().__init__() self.value = value -class Char(Value): +class CharValue(Value): def __init__(self, value: str) -> None: super().__init__() self.value = value -class String(Value): +class StringValue(Value): def __init__(self, value: str) -> None: super().__init__() self.value = value -class Bool(Value): +class BoolValue(Value): def __init__(self, value: bool) -> None: super().__init__() self.value = value +class TupleValue(Value): + def __init__(self, values: List[Value]) -> None: + super().__init__() + self.values = values + class Type: pass class EvalResult: - pass + 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") class ValueResult(EvalResult): def __init__(self, value: Value) -> None: super().__init__() self.value = value + def is_value(self) -> bool: + return True + + def as_value(self) -> ValueResult: + return self + class ReturnResult(EvalResult): def __init__(self, value: Optional[Value]) -> None: super().__init__() @@ -57,8 +76,9 @@ class ContinueResult(EvalResult): self.value = value class PanicResult(EvalResult): - def __init__(self, message: str) -> None: + def __init__(self, span: Span, message: str) -> None: super().__init__() + self.span = span self.message = message class SymbolTable: @@ -157,30 +177,43 @@ class Evaluator: raise NotImplementedError(str(node)) def eval_expr_error(self, expr: parsed.ExprError, span: Span) -> EvalResult: - return PanicResult(f"error: {expr.message}, at {span}") + return PanicResult(span, f"error: {expr.message}, at {span}") def eval_id(self, expr: parsed.Id, span: Span) -> EvalResult: - raise NotImplementedError() + value = self.table.value(expr.value) + if not value: + return PanicResult(span, f"undeclared identifier \"{expr.value}\"") + return ValueResult(value) def eval_int(self, expr: parsed.Int, span: Span) -> EvalResult: - return ValueResult(Int(expr.value)) + return ValueResult(IntValue(expr.value)) def eval_char(self, expr: parsed.Char, span: Span) -> EvalResult: - return ValueResult(Char(expr.value)) + return ValueResult(CharValue(expr.value)) def eval_string(self, expr: parsed.String, span: Span) -> EvalResult: - return ValueResult(String(expr.value)) + return ValueResult(StringValue(expr.value)) def eval_bool(self, expr: parsed.Bool, span: Span) -> EvalResult: - return ValueResult(Bool(expr.value)) + return ValueResult(BoolValue(expr.value)) def eval_unit(self, expr: parsed.Unit, span: Span) -> EvalResult: - return ValueResult(Unit()) + return ValueResult(UnitValue()) def eval_tuple(self, expr: parsed.Tuple, span: Span) -> EvalResult: - raise NotImplementedError() + 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)) def eval_block(self, expr: parsed.Block, span: Span) -> EvalResult: + for statement in expr.statements: + evaluated = self.eval_expr(statement) + if not evaluated.is_value(): + return evaluated raise NotImplementedError() def eval_lambda(self, expr: parsed.Lambda, span: Span) -> EvalResult: diff --git a/parser.py b/parser.py index 1a397b3..af186a4 100644 --- a/parser.py +++ b/parser.py @@ -40,7 +40,7 @@ class Parser: while self.current_is(TokenType.KwOr): self.step() right = self.parse_and() - left = Node(Binary(BinaryType.Or, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.Or, left, right), left.span.to(right.span)) return left @@ -49,7 +49,7 @@ class Parser: while self.current_is(TokenType.KwOr): self.step() right = self.parse_equal() - left = Node(Binary(BinaryType.And, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.And, left, right), left.span.to(right.span)) return left def parse_equal(self) -> Node[Expr]: @@ -58,11 +58,11 @@ class Parser: if self.current_is(TokenType.EqualEqual): self.step() right = self.parse_compare() - left = Node(Binary(BinaryType.Equal, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.Equal, left, right), left.span.to(right.span)) elif self.current_is(TokenType.ExclamationEqual): self.step() right = self.parse_compare() - left = Node(Binary(BinaryType.Inequal, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.Inequal, left, right), left.span.to(right.span)) else: break return left @@ -73,19 +73,19 @@ class Parser: if self.current_is(TokenType.LT): self.step() right = self.parse_add_subtract() - left = Node(Binary(BinaryType.LT, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.LT, left, right), left.span.to(right.span)) elif self.current_is(TokenType.GT): self.step() right = self.parse_add_subtract() - left = Node(Binary(BinaryType.LT, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.LT, left, right), left.span.to(right.span)) elif self.current_is(TokenType.LTEqual): self.step() right = self.parse_add_subtract() - left = Node(Binary(BinaryType.LTEqual, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.LTEqual, left, right), left.span.to(right.span)) elif self.current_is(TokenType.GTEqual): self.step() right = self.parse_add_subtract() - left = Node(Binary(BinaryType.GTEqual, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.GTEqual, left, right), left.span.to(right.span)) else: break return left @@ -96,11 +96,11 @@ class Parser: if self.current_is(TokenType.Plus): self.step() right = self.parse_multiply_divide_modulo() - left = Node(Binary(BinaryType.Add, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.Add, left, right), left.span.to(right.span)) elif self.current_is(TokenType.Minus): self.step() right = self.parse_multiply_divide_modulo() - left = Node(Binary(BinaryType.Subtract, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.Subtract, left, right), left.span.to(right.span)) else: break return left @@ -111,15 +111,15 @@ class Parser: if self.current_is(TokenType.Asterisk): self.step() right = self.parse_negate() - left = Node(Binary(BinaryType.Multiply, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.Multiply, left, right), left.span.to(right.span)) elif self.current_is(TokenType.Slash): self.step() right = self.parse_negate() - left = Node(Binary(BinaryType.Divide, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.Divide, left, right), left.span.to(right.span)) elif self.current_is(TokenType.Percent): self.step() right = self.parse_negate() - left = Node(Binary(BinaryType.Modulo, left, right), left.span.to(right.span)) + left = Node[Expr](Binary(BinaryType.Modulo, left, right), left.span.to(right.span)) else: break return left