53 lines
1.8 KiB
Python
53 lines
1.8 KiB
Python
from core.primitives.list import NIL, cons, car, cdr
|
|
from core.primitives.symbol import isSymbol, symbolName
|
|
|
|
from core.exceptions import syntaxError
|
|
|
|
from core.tokens import Lambda
|
|
from core.tail_recursion import tailRecursion
|
|
|
|
# from core.evaluator.naively_evaluate import naivelyEvaluate
|
|
from core.evaluator.utils.getFirstN import getFirstN
|
|
|
|
from core.environment import TCO
|
|
|
|
def evalCall(head, tail, environment, environmentParent, strict):
|
|
from core.evaluator.naively_evaluate import naivelyEvaluate
|
|
args = head.args
|
|
|
|
if args == NIL and tail != NIL:
|
|
raise syntaxError(f'more than zero args for {repr(head)}')
|
|
|
|
while args != NIL:
|
|
firstArg = car(args)
|
|
if not isSymbol(firstArg):
|
|
raise syntaxError(f'cannot take non-symbol as argument: {repr(firstArg)}')
|
|
if symbolName(firstArg) == '.':
|
|
firstArg = getFirstN(args, 2)[1]
|
|
arr = []
|
|
while tail != NIL:
|
|
arr.append(naivelyEvaluate(car(tail), environmentParent, True))
|
|
tail = cdr(tail)
|
|
arg = NIL
|
|
for elem in reversed(arr):
|
|
arg = cons(elem, arg)
|
|
args = NIL
|
|
else:
|
|
if tail == NIL:
|
|
break
|
|
arg = naivelyEvaluate(car(tail), environmentParent, True)
|
|
args = cdr(args)
|
|
tail = cdr(tail)
|
|
environment.add(firstArg, arg)
|
|
|
|
if tail != NIL:
|
|
raise syntaxError(f'extra args {repr(tail)}\nfor not variable lambda {repr(head)}')
|
|
|
|
if args != NIL:
|
|
return Lambda(args, head.body, environment)
|
|
|
|
if not TCO:
|
|
return naivelyEvaluate(head.body, environment, True)
|
|
|
|
ret = tailRecursion(naivelyEvaluate, head.body, environment, False)
|
|
return tailRecursion.eval(ret) if strict else ret |