174 lines
6.1 KiB
Python
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)
|