from core.tokens import ( BinaryOperator, BinaryPredicate, SpecialForm, Lambda, Pure, Macro, ) # debug import sys from core.primitives.symbol import ( isSymbol ) from core.primitives.list import ( cons, car, cdr, isList, NIL ) from core.environment import EVAL_NIL, Environment, RepresentateAST from core.evaluator.evaluate_binary_operator import evalBinaryOperator from core.evaluator.evaluate_binary_predicate import evalBinaryPredicate from core.evaluator.evaluate_special_form import evalSpecialForm from core.evaluator.evaluate_call import evalCall from core.evaluator.evaluate_macro import evalMacro from core.evaluator.utils.getFirstN import getFirstN from core.exceptions import error, syntaxError, typeError def naivelyEvaluate(value, localEnvironment, strict): if isSymbol(value): return localEnvironment.get(value) elif isList(value): if value == NIL: return EVAL_NIL() head = naivelyEvaluate(car(value), localEnvironment, True) tail = cdr(value) try: if isinstance(head, (BinaryOperator, BinaryPredicate)): try: a, b = getFirstN(tail, 2) evaledA = naivelyEvaluate(a, localEnvironment, True) evaledB = naivelyEvaluate(b, localEnvironment, True) if isinstance(head, BinaryOperator): return evalBinaryOperator(head, evaledA, evaledB) return evalBinaryPredicate(head, evaledA, evaledB) except syntaxError as e: raise syntaxError(f'wrong args for: {repr(value)}') from e elif isinstance(head, SpecialForm): return evalSpecialForm(head, tail, localEnvironment, strict) elif isinstance(head, (Lambda, Pure)): if isinstance(head, Lambda): environment = Environment(head.env) else: environment = Environment(parent=localEnvironment) return evalCall(head, tail, environment, localEnvironment, strict) elif isinstance(head, Macro): return evalMacro(head, tail, localEnvironment, strict) except error as e: raise syntaxError(f'wrong args for {repr(head)}: {repr(cdr(value))}') from e raise typeError(f'wrong head form: {RepresentateAST(head)}') return value