builtup4/bu4/combinatory/tocombinatory.py

174 lines
6.1 KiB
Python

# Copyright (c) PARRRATE T&V 2021. All rights reserved.
from bu4.combinatory.lcombinatory import LCombinatory
from bu4.combinatory.lic import LIC
from bu4.combinatory.lkc import LKC
from bu4.combinatory.lsc import LSC
from bu4.linking.constructs.lcall import LCall
from bu4.linking.constructs.ldelayed import LDelayed
from bu4.linking.constructs.lexception import LException
from bu4.linking.constructs.linked import Linked
from bu4.linking.constructs.llambda import LLambda
from bu4.linking.constructs.lname import LName
from bu4.linking.constructs.lnull import LNull
from bu4.transform.states.aftertransform import AfterTransform
from bu4.transform.states.transformfinished import TransformFinished
from bu4.transform.states.transformstart import TransformStart
from bu4.transform.states.transformstate import TransformState
from bu4.transform.targets.atlambda import ATLambda
class LCCall(LCall, LCombinatory):
def __init__(self, argument: LCombinatory, lambda_: LCombinatory):
super().__init__(argument, lambda_)
class LCNull(LNull, LCombinatory):
pass
class LCException(LException, LCombinatory):
pass
def is_kks(linked: Linked) -> bool:
if not isinstance(linked, LCall):
return False
if not isinstance(linked.lambda_, LSC):
return False
linked = linked.argument
if not isinstance(linked, LCall):
return False
if not isinstance(linked.argument, LKC):
return False
if not isinstance(linked.lambda_, LKC):
return False
return True
def is_ikks(linked: Linked) -> bool:
if not isinstance(linked, LCall):
return False
if not isinstance(linked.argument, LIC):
return False
return is_kks(linked.lambda_)
def is_eta(linked: Linked) -> bool:
if not isinstance(linked, LCall):
return False
if not isinstance(linked.argument, LKC):
return False
linked = linked.lambda_
if not isinstance(linked, LCall):
return False
if not isinstance(linked.lambda_, LSC):
return False
linked = linked.argument
if not isinstance(linked, LCall):
return False
if not isinstance(linked.lambda_, LKC):
return False
linked = linked.argument
if not isinstance(linked, LCall):
return False
if not isinstance(linked.argument, LIC):
return False
if not isinstance(linked.lambda_, LSC):
return False
return True
def lccall(argument: Linked, lambda_: Linked) -> TransformState[Linked]:
if isinstance(lambda_, LIC):
return TransformFinished(argument)
elif isinstance(argument, LKC) and isinstance(lambda_, LSC):
return TransformFinished(LCCall(LIC(), LKC()))
elif isinstance(lambda_, LCall) and isinstance(lambda_.lambda_, LKC):
return TransformFinished(lambda_.argument)
elif isinstance(argument, LIC) and is_kks(lambda_):
return TransformFinished(LKC())
elif isinstance(lambda_, LCall) and is_eta(lambda_.lambda_):
lcall = lambda_
return TransformStart(lambda: lccall(lcall.argument, argument))
elif isinstance(argument, LCombinatory) and isinstance(lambda_, LCombinatory):
return TransformFinished(LCCall(argument, lambda_))
else:
return TransformFinished(LCall.new(argument, lambda_))
def to_combinatory(linked: Linked) -> TransformState[Linked]:
if isinstance(linked, LCombinatory):
return TransformFinished(linked)
elif is_ikks(linked):
return TransformFinished(LKC())
elif isinstance(linked, LCall):
lcall = linked
return AfterTransform(
TransformStart(lambda: to_combinatory(lcall.argument)),
ATLambda(
lambda argument: AfterTransform(
TransformStart(lambda: to_combinatory(lcall.lambda_)),
ATLambda(
lambda lambda_: lccall(argument, lambda_)
)
)
)
)
elif isinstance(linked, LDelayed):
ldelayed = linked
return AfterTransform(
TransformStart(lambda: to_combinatory(ldelayed.value)),
ATLambda(
lambda value: lccall(value, LKC())
)
)
elif isinstance(linked, LLambda):
llambda = linked
if not llambda.used:
return AfterTransform(
TransformStart(lambda: to_combinatory(llambda.value)),
ATLambda(
lambda value: lccall(value, LKC())
)
)
elif isinstance(llambda.value, LName) and llambda.value.name == llambda.name:
return TransformFinished(LIC())
elif isinstance(llambda.value, LCall):
lcall = llambda.value
return AfterTransform(
TransformStart(lambda: to_combinatory(LLambda(llambda.name, lcall.argument))),
ATLambda(
lambda argument: AfterTransform(
TransformStart(lambda: to_combinatory(LLambda(llambda.name, lcall.lambda_))),
ATLambda(
lambda lambda_: AfterTransform(
lccall(
lambda_,
LSC()
),
ATLambda(
lambda combined: lccall(
argument,
combined
)
)
)
)
)
)
)
else:
return AfterTransform(
TransformStart(lambda: to_combinatory(llambda.value)),
ATLambda(
lambda value: to_combinatory(LLambda(llambda.name, value))
)
)
elif isinstance(linked, LNull):
return TransformFinished(LCNull())
elif isinstance(linked, LException):
return TransformFinished(LCException(linked.name))
else:
return TransformFinished(linked)