49 lines
1.5 KiB
Python
49 lines
1.5 KiB
Python
from core.primitives.list import cons, car, cdr, NIL
|
|
from core.primitives.symbol import symbolName, symbolKey
|
|
|
|
from core.tokens import Macro
|
|
from core.exceptions import syntaxError
|
|
|
|
from core.tail_recursion import tailRecursion
|
|
from core.macro_expand import macroExpand
|
|
|
|
# from core.evaluator.naively_evaluate import naivelyEvaluate
|
|
from core.evaluator.utils.getFirstN import getFirstN
|
|
|
|
from core.environment import TCO
|
|
|
|
def evalMacro(head, tail, environment, strict):
|
|
from core.evaluator.naively_evaluate import naivelyEvaluate
|
|
d = dict()
|
|
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 symbolName(firstArg) == '.':
|
|
firstArg = getFirstN(args, 2)[1]
|
|
arg = tail
|
|
args = NIL
|
|
tail = NIL
|
|
else:
|
|
if tail == NIL:
|
|
break
|
|
arg = car(tail)
|
|
args = cdr(args)
|
|
tail = cdr(tail)
|
|
d[symbolKey(firstArg)] = arg
|
|
|
|
if tail != NIL:
|
|
raise syntaxError(f'extra args {repr(tail)}\nfor not variable macro {repr(head)}')
|
|
expanded = macroExpand(head.body, d)
|
|
|
|
if args != NIL:
|
|
return Macro(args, expanded)
|
|
|
|
if not TCO:
|
|
return naivelyEvaluate(expanded, environment, True)
|
|
|
|
ret = tailRecursion(naivelyEvaluate, expanded, environment, False)
|
|
return tailRecursion.eval(ret) if strict else ret |