Compare commits
3 Commits
affcbc33ee
...
6e46f485c1
Author | SHA1 | Date |
---|---|---|
Mark | 6e46f485c1 | |
Mark | e41de764e8 | |
Mark | 8871f1430d |
|
@ -45,9 +45,9 @@ r.run_lines([
|
||||||
"T = λab.a",
|
"T = λab.a",
|
||||||
"F = λab.b",
|
"F = λab.b",
|
||||||
"NOT = λa.(a F T)",
|
"NOT = λa.(a F T)",
|
||||||
"AND = λab.(a F b)",
|
"AND = λab.(a b F)",
|
||||||
"OR = λab.(a T b)",
|
"OR = λab.(a T b)",
|
||||||
"XOR = λab.(a (NOT a b) b)",
|
"XOR = λab.(a (NOT b) b)",
|
||||||
"M = λx.(x x)",
|
"M = λx.(x x)",
|
||||||
"W = M M",
|
"W = M M",
|
||||||
"Y = λf.( (λx.(f (x x))) (λx.(f (x x))) )",
|
"Y = λf.( (λx.(f (x x))) (λx.(f (x x))) )",
|
||||||
|
|
16
lamb/node.py
16
lamb/node.py
|
@ -372,7 +372,7 @@ class Call(Node):
|
||||||
def print_node(node: Node) -> str:
|
def print_node(node: Node) -> str:
|
||||||
if not isinstance(node, Node):
|
if not isinstance(node, Node):
|
||||||
raise TypeError(f"I don't know how to print a {type(node)}")
|
raise TypeError(f"I don't know how to print a {type(node)}")
|
||||||
else:
|
|
||||||
out = ""
|
out = ""
|
||||||
|
|
||||||
for s, n in node:
|
for s, n in node:
|
||||||
|
@ -489,16 +489,13 @@ def bind_variables(node: Node, *, ban_macro_name = None) -> None:
|
||||||
# Returns the function's output.
|
# Returns the function's output.
|
||||||
def call_func(fn: Func, arg: Node):
|
def call_func(fn: Func, arg: Node):
|
||||||
for s, n in fn:
|
for s, n in fn:
|
||||||
if isinstance(n, Bound):
|
if isinstance(n, Bound) and (s == Direction.UP):
|
||||||
if n == fn.input:
|
if n == fn.input:
|
||||||
if n.parent is None:
|
if n.parent is None:
|
||||||
raise Exception("Tried to substitute a None bound variable.")
|
raise Exception("Tried to substitute a None bound variable.")
|
||||||
|
|
||||||
if n.parent_side == Direction.LEFT:
|
n.parent.set_side(n.parent_side, clone(arg)) # type: ignore
|
||||||
n.parent.left = clone(arg)
|
return clone(fn.left)
|
||||||
else:
|
|
||||||
n.parent.right = clone(arg)
|
|
||||||
return fn.left
|
|
||||||
|
|
||||||
|
|
||||||
# Do a single reduction step
|
# Do a single reduction step
|
||||||
|
@ -514,7 +511,10 @@ def reduce(node: Node, *, macro_table = {}) -> tuple[ReductionType, Node]:
|
||||||
out = call_func(n.left, n.right)
|
out = call_func(n.left, n.right)
|
||||||
out._set_parent(None, None)
|
out._set_parent(None, None)
|
||||||
else:
|
else:
|
||||||
n.parent.left = call_func(n.left, n.right)
|
n.parent.set_side(
|
||||||
|
n.parent_side, # type: ignore
|
||||||
|
call_func(n.left, n.right)
|
||||||
|
)
|
||||||
|
|
||||||
return ReductionType.FUNCTION_APPLY, out
|
return ReductionType.FUNCTION_APPLY, out
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
from prompt_toolkit import PromptSession
|
from prompt_toolkit import PromptSession
|
||||||
from prompt_toolkit.formatted_text import FormattedText
|
from prompt_toolkit.formatted_text import FormattedText
|
||||||
from prompt_toolkit import print_formatted_text as printf
|
from prompt_toolkit import print_formatted_text as printf
|
||||||
|
from prompt_toolkit.shortcuts import clear as clear_screen
|
||||||
import enum
|
import enum
|
||||||
|
import math
|
||||||
|
|
||||||
import lamb
|
import lamb
|
||||||
|
|
||||||
|
@ -11,7 +13,6 @@ class StopReason(enum.Enum):
|
||||||
LOOP_DETECTED = ("class:warn", "Loop detected")
|
LOOP_DETECTED = ("class:warn", "Loop detected")
|
||||||
MAX_EXCEEDED = ("class:err", "Too many reductions")
|
MAX_EXCEEDED = ("class:err", "Too many reductions")
|
||||||
INTERRUPT = ("class:warn", "User interrupt")
|
INTERRUPT = ("class:warn", "User interrupt")
|
||||||
RECURSION = ("class:err", "Python Recursion Error")
|
|
||||||
|
|
||||||
class MacroDef:
|
class MacroDef:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -78,6 +79,11 @@ class Runner:
|
||||||
# a bound variable.
|
# a bound variable.
|
||||||
self.bound_variable_counter = 0
|
self.bound_variable_counter = 0
|
||||||
|
|
||||||
|
# Update iteration after this many iterations
|
||||||
|
# Make sure every place value has a non-zero digit
|
||||||
|
# so that all digits appear to be changing.
|
||||||
|
self.iter_update = 231
|
||||||
|
|
||||||
def prompt(self):
|
def prompt(self):
|
||||||
return self.prompt_session.prompt(message = self.prompt_message)
|
return self.prompt_session.prompt(message = self.prompt_message)
|
||||||
|
|
||||||
|
@ -102,14 +108,19 @@ class Runner:
|
||||||
|
|
||||||
while (self.reduction_limit is None) or (i < self.reduction_limit):
|
while (self.reduction_limit is None) or (i < self.reduction_limit):
|
||||||
|
|
||||||
|
# Show reduction count
|
||||||
|
if (i >= self.iter_update) and (i % self.iter_update == 0):
|
||||||
|
print(f" Reducing... {i}", end = "\r")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
red_type, new_node = lamb.node.reduce(
|
red_type, new_node = lamb.node.reduce(
|
||||||
node,
|
node,
|
||||||
macro_table = self.macro_table
|
macro_table = self.macro_table
|
||||||
)
|
)
|
||||||
except RecursionError:
|
except KeyboardInterrupt:
|
||||||
stop_reason = StopReason.RECURSION
|
stop_reason = StopReason.INTERRUPT
|
||||||
break
|
break
|
||||||
|
|
||||||
node = new_node
|
node = new_node
|
||||||
|
|
||||||
# If we can't reduce this expression anymore,
|
# If we can't reduce this expression anymore,
|
||||||
|
@ -123,6 +134,9 @@ class Runner:
|
||||||
if red_type == lamb.node.ReductionType.FUNCTION_APPLY:
|
if red_type == lamb.node.ReductionType.FUNCTION_APPLY:
|
||||||
macro_expansions += 1
|
macro_expansions += 1
|
||||||
|
|
||||||
|
if i >= self.iter_update:
|
||||||
|
# Clear reduction counter
|
||||||
|
print(" " * round(14 + math.log10(i)), end = "\r")
|
||||||
|
|
||||||
if (
|
if (
|
||||||
stop_reason == StopReason.BETA_NORMAL or
|
stop_reason == StopReason.BETA_NORMAL or
|
||||||
|
|
Reference in New Issue