Compare commits

..

No commits in common. "01e542f88c741124b7bd03d07cc67384117a8ebb" and "09f78a764265fa7a74f23175b51d44a358cec7c1" have entirely different histories.

5 changed files with 73 additions and 163 deletions

View File

@ -36,7 +36,7 @@ def cmd_save(command, runner) -> None:
if len(command.args) != 1: if len(command.args) != 1:
printf( printf(
HTML( HTML(
f"<err>Command <code>:{command.name}</code> takes exactly one argument.</err>" f"<err>Command <cmd_code>:{command.name}</cmd_code> takes exactly one argument.</err>"
), ),
style = lamb.utils.style style = lamb.utils.style
) )
@ -67,7 +67,7 @@ def cmd_save(command, runner) -> None:
printf( printf(
HTML( HTML(
f"Wrote {len(runner.macro_table)} macros to <code>{target}</code>" f"Wrote {len(runner.macro_table)} macros to <cmd_code>{target}</cmd_code>"
), ),
style = lamb.utils.style style = lamb.utils.style
) )
@ -81,7 +81,7 @@ def cmd_load(command, runner):
if len(command.args) != 1: if len(command.args) != 1:
printf( printf(
HTML( HTML(
f"<err>Command <code>:{command.name}</code> takes exactly one argument.</err>" f"<err>Command <cmd_code>:{command.name}</cmd_code> takes exactly one argument.</err>"
), ),
style = lamb.utils.style style = lamb.utils.style
) )
@ -108,9 +108,9 @@ def cmd_load(command, runner):
printf( printf(
FormattedText([ FormattedText([
("class:warn", f"Syntax error on line {i+1:02}: "), ("class:warn", f"Syntax error on line {i+1:02}: "),
("class:code", l[:e.loc]), ("class:cmd_code", l[:e.loc]),
("class:err", l[e.loc]), ("class:err", l[e.loc]),
("class:code", l[e.loc+1:]) ("class:cmd_code", l[e.loc+1:])
]), ]),
style = lamb.utils.style style = lamb.utils.style
) )
@ -120,7 +120,7 @@ def cmd_load(command, runner):
printf( printf(
FormattedText([ FormattedText([
("class:warn", f"Skipping line {i+1:02}: "), ("class:warn", f"Skipping line {i+1:02}: "),
("class:code", l), ("class:cmd_code", l),
("class:warn", f" is not a macro definition.") ("class:warn", f" is not a macro definition.")
]), ]),
style = lamb.utils.style style = lamb.utils.style
@ -132,7 +132,7 @@ def cmd_load(command, runner):
printf( printf(
FormattedText([ FormattedText([
("class:ok", f"Loaded {x.label}: "), ("class:ok", f"Loaded {x.label}: "),
("class:code", str(x.expr)) ("class:cmd_code", str(x.expr))
]), ]),
style = lamb.utils.style style = lamb.utils.style
) )
@ -145,7 +145,7 @@ def mdel(command, runner) -> None:
if len(command.args) != 1: if len(command.args) != 1:
printf( printf(
HTML( HTML(
f"<err>Command <code>:{command.name}</code> takes exactly one argument.</err>" f"<err>Command <cmd_code>:{command.name}</cmd_code> takes exactly one argument.</err>"
), ),
style = lamb.utils.style style = lamb.utils.style
) )
@ -172,7 +172,7 @@ def macros(command, runner) -> None:
("class:cmd_h", "\nDefined Macros:\n"), ("class:cmd_h", "\nDefined Macros:\n"),
] + ] +
[ [
("class:text", f"\t{name} \t {exp}\n") ("class:cmd_text", f"\t{name} \t {exp}\n")
for name, exp in runner.macro_table.items() for name, exp in runner.macro_table.items()
]), ]),
style = lamb.utils.style style = lamb.utils.style
@ -209,7 +209,7 @@ def rlimit(command, runner) -> None:
elif len(command.args) != 1: elif len(command.args) != 1:
printf( printf(
HTML( HTML(
f"<err>Command <code>:{command.name}</code> takes exactly one argument.</err>" f"<err>Command <cmd_code>:{command.name}</cmd_code> takes exactly one argument.</err>"
), ),
style = lamb.utils.style style = lamb.utils.style
) )
@ -262,27 +262,25 @@ def rlimit(command, runner) -> None:
def help(command, runner) -> None: def help(command, runner) -> None:
printf( printf(
HTML( HTML(
"\n<text>" + "\n<cmd_text>" +
"<cmd_h>Usage:</cmd_h>" + "<cmd_h>Usage:</cmd_h>" +
"\n" + "\n" +
"\tWrite lambda expressions using your <cmd_key>\\</cmd_key> key." + "\tWrite lambda expressions using your <cmd_key>\\</cmd_key> key." +
"\n" + "\n" +
"\tMacros can be defined using <cmd_key>=</cmd_key>, as in <code>T = λab.a</code>" + "\tMacros can be defined using <cmd_key>=</cmd_key>, as in <cmd_code>T = λab.a</cmd_code>" +
"\n" + "\n" +
"\tRun commands using <cmd_key>:</cmd_key>, for example <code>:help</code>" + "\tRun commands using <cmd_key>:</cmd_key>, for example <cmd_code>:help</cmd_code>" +
"\n" +
"\tHistory can be accessed with <cmd_key>$</cmd_key>, which will expand to the result of the last successful reduction." +
"\n\n" + "\n\n" +
"<cmd_h>Commands:</cmd_h>"+ "<cmd_h>Commands:</cmd_h>"+
"\n" + "\n" +
"\n".join([ "\n".join([
f"\t<code>{name}</code> \t {text}" f"\t<cmd_code>{name}</cmd_code> \t {text}"
for name, text in help_texts.items() for name, text in help_texts.items()
]) + ]) +
"\n\n" "\n\n"
"<muted>Detailed documentation can be found on this project's git page.</muted>" + "<muted>Detailed documentation can be found on this project's git page.</muted>" +
"</text>" "</cmd_text>"
), ),
style = lamb.utils.style style = lamb.utils.style
) )

View File

@ -14,9 +14,6 @@ class ReductionType(enum.Enum):
# We replaced a macro with an expression. # We replaced a macro with an expression.
MACRO_EXPAND = enum.auto() MACRO_EXPAND = enum.auto()
# We expanded a history reference
HIST_EXPAND = enum.auto()
# We turned a church numeral into an expression # We turned a church numeral into an expression
AUTOCHURCH = enum.auto() AUTOCHURCH = enum.auto()
@ -104,10 +101,6 @@ class Node:
self._left: Node | None = None self._left: Node | None = None
self._right: Node | None = None self._right: Node | None = None
# The runner this node is attached to.
# Set by Node.set_runner()
self.runner: lamb.runner.Runner = None # type: ignore
def __iter__(self): def __iter__(self):
return TreeWalker(self) return TreeWalker(self)
@ -227,25 +220,17 @@ class Node:
ban_macro_name = ban_macro_name ban_macro_name = ban_macro_name
) )
def set_runner(self, runner):
for s, n in self:
if s == Direction.UP:
n.runner = runner # type: ignore
return self
class EndNode(Node): class EndNode(Node):
def print_value(self, *, export: bool = False) -> str: def print_value(self, *, export: bool = False) -> str:
raise NotImplementedError("EndNodes MUST provide a `print_value` method!") raise NotImplementedError("EndNodes MUST provide a `print_value` method!")
class ExpandableEndNode(EndNode): class ExpandableEndNode(EndNode):
always_expand = False def expand(self, *, macro_table = {}) -> tuple[ReductionType, Node]:
def expand(self) -> tuple[ReductionType, Node]:
raise NotImplementedError("ExpandableEndNodes MUST provide an `expand` method!") raise NotImplementedError("ExpandableEndNodes MUST provide an `expand` method!")
class FreeVar(EndNode): class FreeVar(EndNode):
def __init__(self, name: str, *, runner = None): def __init__(self, name: str):
self.name = name self.name = name
self.runner = runner # type: ignore
def __repr__(self): def __repr__(self):
return f"<freevar {self.name}>" return f"<freevar {self.name}>"
@ -264,12 +249,11 @@ class Macro(ExpandableEndNode):
def from_parse(results): def from_parse(results):
return Macro(results[0]) return Macro(results[0])
def __init__(self, name: str, *, runner = None) -> None: def __init__(self, name: str) -> None:
super().__init__() super().__init__()
self.name = name self.name = name
self.left = None self.left = None
self.right = None self.right = None
self.runner = runner # type: ignore
def __repr__(self): def __repr__(self):
return f"<macro {self.name}>" return f"<macro {self.name}>"
@ -277,26 +261,25 @@ class Macro(ExpandableEndNode):
def print_value(self, *, export: bool = False) -> str: def print_value(self, *, export: bool = False) -> str:
return self.name return self.name
def expand(self) -> tuple[ReductionType, Node]: def expand(self, *, macro_table = {}) -> tuple[ReductionType, Node]:
if self.name in self.runner.macro_table: if self.name in macro_table:
return ReductionType.MACRO_EXPAND, clone(self.runner.macro_table[self.name]) return ReductionType.MACRO_EXPAND, clone(macro_table[self.name])
else: else:
return ReductionType.MACRO_TO_FREE, FreeVar(self.name, runner = self.runner) return ReductionType.MACRO_TO_FREE, FreeVar(self.name)
def copy(self): def copy(self):
return Macro(self.name, runner = self.runner) return Macro(self.name)
class Church(ExpandableEndNode): class Church(ExpandableEndNode):
@staticmethod @staticmethod
def from_parse(results): def from_parse(results):
return Church(int(results[0])) return Church(int(results[0]))
def __init__(self, value: int, *, runner = None) -> None: def __init__(self, value: int) -> None:
super().__init__() super().__init__()
self.value = value self.value = value
self.left = None self.left = None
self.right = None self.right = None
self.runner = runner # type: ignore
def __repr__(self): def __repr__(self):
return f"<church {self.value}>" return f"<church {self.value}>"
@ -304,7 +287,7 @@ class Church(ExpandableEndNode):
def print_value(self, *, export: bool = False) -> str: def print_value(self, *, export: bool = False) -> str:
return str(self.value) return str(self.value)
def expand(self) -> tuple[ReductionType, Node]: def expand(self, *, macro_table = {}) -> tuple[ReductionType, Node]:
f = Bound("f") f = Bound("f")
a = Bound("a") a = Bound("a")
chain = a chain = a
@ -314,46 +297,17 @@ class Church(ExpandableEndNode):
return ( return (
ReductionType.AUTOCHURCH, ReductionType.AUTOCHURCH,
Func(f, Func(a, chain)).set_runner(self.runner) Func(f, Func(a, chain))
) )
def copy(self): def copy(self):
return Church(self.value, runner = self.runner) return Church(self.value)
class History(ExpandableEndNode):
always_expand = True
@staticmethod
def from_parse(results):
return History()
def __init__(self, *, runner = None) -> None:
super().__init__()
self.left = None
self.right = None
self.runner = runner # type: ignore
def __repr__(self):
return f"<$>"
def print_value(self, *, export: bool = False) -> str:
return "$"
def expand(self) -> tuple[ReductionType, Node]:
if len(self.runner.history) == 0:
raise ReductionError(f"There isn't any history to reference.")
return ReductionType.HIST_EXPAND, clone(self.runner.history[-1])
def copy(self):
return History(runner = self.runner)
bound_counter = 0 bound_counter = 0
class Bound(EndNode): class Bound(EndNode):
def __init__(self, name: str, *, forced_id = None, runner = None): def __init__(self, name: str, *, forced_id = None):
self.name = name self.name = name
global bound_counter global bound_counter
self.runner = runner # type: ignore
if forced_id is None: if forced_id is None:
self.identifier = bound_counter self.identifier = bound_counter
@ -362,7 +316,7 @@ class Bound(EndNode):
self.identifier = forced_id self.identifier = forced_id
def copy(self): def copy(self):
return Bound(self.name, forced_id = self.identifier, runner = self.runner) return Bound(self.name, forced_id = self.identifier)
def __eq__(self, other): def __eq__(self, other):
if not isinstance(other, Bound): if not isinstance(other, Bound):
@ -389,18 +343,17 @@ class Func(Node):
Func.from_parse(result) Func.from_parse(result)
) )
def __init__(self, input: Macro | Bound, output: Node, *, runner = None) -> None: def __init__(self, input: Macro | Bound, output: Node) -> None:
super().__init__() super().__init__()
self.input: Macro | Bound = input self.input: Macro | Bound = input
self.left: Node = output self.left: Node = output
self.right: None = None self.right: None = None
self.runner = runner # type: ignore
def __repr__(self): def __repr__(self):
return f"<func {self.input!r} {self.left!r}>" return f"<func {self.input!r} {self.left!r}>"
def copy(self): def copy(self):
return Func(self.input, None, runner = self.runner) # type: ignore return Func(self.input, None) # type: ignore
class Call(Node): class Call(Node):
@staticmethod @staticmethod
@ -423,17 +376,16 @@ class Call(Node):
)] + results[2:] )] + results[2:]
) )
def __init__(self, fn: Node, arg: Node, *, runner = None) -> None: def __init__(self, fn: Node, arg: Node) -> None:
super().__init__() super().__init__()
self.left: Node = fn self.left: Node = fn
self.right: Node = arg self.right: Node = arg
self.runner = runner # type: ignore
def __repr__(self): def __repr__(self):
return f"<call {self.left!r} {self.right!r}>" return f"<call {self.left!r} {self.right!r}>"
def copy(self): def copy(self):
return Call(None, None, runner = self.runner) # type: ignore return Call(None, None) # type: ignore
def print_node(node: Node, *, export: bool = False) -> str: def print_node(node: Node, *, export: bool = False) -> str:
@ -524,31 +476,21 @@ def clone(node: Node):
break break
return out return out
def bind_variables(node: Node, *, ban_macro_name = None) -> dict: def bind_variables(node: Node, *, ban_macro_name = None) -> None:
if not isinstance(node, Node): if not isinstance(node, Node):
raise TypeError(f"I don't know what to do with a {type(node)}") raise TypeError(f"I don't know what to do with a {type(node)}")
bound_variables = {} bound_variables = {}
output = {
"has_history": False,
"free_variables": set()
}
for s, n in node: for s, n in node:
if isinstance(n, History):
output["has_history"] = True
# If this expression is part of a macro, # If this expression is part of a macro,
# make sure we don't reference it inside itself. # make sure we don't reference it inside itself.
elif isinstance(n, Macro): if isinstance(n, Macro) and ban_macro_name is not None:
if (n.name == ban_macro_name) and (ban_macro_name is not None): if n.name == ban_macro_name:
raise ReductionError("Macro cannot reference self") raise ReductionError("Macro cannot reference self")
if n.name not in node.runner.macro_table: if isinstance(n, Func):
output["free_variables"].add(n.name)
elif isinstance(n, Func):
if s == Direction.UP: if s == Direction.UP:
# Add this function's input to the table of bound variables. # Add this function's input to the table of bound variables.
# If it is already there, raise an error. # If it is already there, raise an error.
@ -575,7 +517,6 @@ def bind_variables(node: Node, *, ban_macro_name = None) -> dict:
if isinstance(n.right, Macro): if isinstance(n.right, Macro):
if n.right.name in bound_variables: if n.right.name in bound_variables:
n.right = clone(bound_variables[n.right.name]) n.right = clone(bound_variables[n.right.name])
return output
# Apply a function. # Apply a function.
# Returns the function's output. # Returns the function's output.
@ -591,7 +532,7 @@ def call_func(fn: Func, arg: Node):
# Do a single reduction step # Do a single reduction step
def reduce(node: Node) -> tuple[ReductionType, Node]: def reduce(node: Node, *, macro_table = {}) -> tuple[ReductionType, Node]:
if not isinstance(node, Node): if not isinstance(node, Node):
raise TypeError(f"I can't reduce a {type(node)}") raise TypeError(f"I can't reduce a {type(node)}")
@ -611,14 +552,16 @@ def reduce(node: Node) -> tuple[ReductionType, Node]:
return ReductionType.FUNCTION_APPLY, out return ReductionType.FUNCTION_APPLY, out
elif isinstance(n.left, ExpandableEndNode): elif isinstance(n.left, ExpandableEndNode):
r, n.left = n.left.expand() r, n.left = n.left.expand(
macro_table = macro_table
)
return r, out return r, out
return ReductionType.NOTHING, out return ReductionType.NOTHING, out
# Expand all expandable end nodes. # Expand all expandable end nodes.
def finalize_macros(node: Node, *, force = False) -> tuple[int, Node]: def force_expand_macros(node: Node, *, macro_table = {}) -> tuple[int, Node]:
if not isinstance(node, Node): if not isinstance(node, Node):
raise TypeError(f"I can't reduce a {type(node)}") raise TypeError(f"I can't reduce a {type(node)}")
@ -629,18 +572,15 @@ def finalize_macros(node: Node, *, force = False) -> tuple[int, Node]:
macro_expansions = 0 macro_expansions = 0
while True: while True:
if ( if isinstance(ptr, ExpandableEndNode):
isinstance(ptr, ExpandableEndNode) and
(force or ptr.always_expand)
):
if ptr.parent is None: if ptr.parent is None:
ptr = ptr.expand()[1] ptr = ptr.expand(macro_table = macro_table)[1]
out = ptr out = ptr
ptr._set_parent(None, None) ptr._set_parent(None, None)
else: else:
ptr.parent.set_side( ptr.parent.set_side(
ptr.parent_side, # type: ignore ptr.parent_side, # type: ignore
ptr.expand()[1] ptr.expand(macro_table = macro_table)[1]
) )
ptr = ptr.parent.get_side( ptr = ptr.parent.get_side(
ptr.parent_side # type: ignore ptr.parent_side # type: ignore

View File

@ -16,14 +16,13 @@ class LambdaParser:
self.pp_bound = pp.Char(pp.srange("[a-z]")) self.pp_bound = pp.Char(pp.srange("[a-z]"))
self.pp_name = self.pp_bound ^ self.pp_macro self.pp_name = self.pp_bound ^ self.pp_macro
self.pp_church = pp.Word(pp.nums) self.pp_church = pp.Word(pp.nums)
self.pp_history = pp.Char("$")
# Function calls. # Function calls.
# #
# <exp> <exp> # <exp> <exp>
# <exp> <exp> <exp> # <exp> <exp> <exp>
self.pp_call = pp.Forward() self.pp_call = pp.Forward()
self.pp_call <<= (self.pp_expr | self.pp_bound | self.pp_history)[2, ...] self.pp_call <<= (self.pp_expr | self.pp_bound)[2, ...]
# Function definitions, right associative. # Function definitions, right associative.
# Function args MUST be lowercase. # Function args MUST be lowercase.
@ -44,7 +43,7 @@ class LambdaParser:
pp.line_start() + pp.line_start() +
self.pp_macro + self.pp_macro +
pp.Suppress("=") + pp.Suppress("=") +
(self.pp_expr ^ self.pp_call ^ self.pp_history) (self.pp_expr ^ self.pp_call)
) )
self.pp_expr <<= ( self.pp_expr <<= (
@ -52,8 +51,7 @@ class LambdaParser:
self.pp_lambda_fun ^ self.pp_lambda_fun ^
self.pp_name ^ self.pp_name ^
(self.lp + self.pp_expr + self.rp) ^ (self.lp + self.pp_expr + self.rp) ^
(self.lp + self.pp_call + self.rp) ^ (self.lp + self.pp_call + self.rp)
(self.lp + self.pp_history + self.rp)
) )
self.pp_command = pp.Suppress(":") + pp.Word(pp.alphas + "_") + pp.Word(pp.alphas + pp.nums + "_")[0, ...] self.pp_command = pp.Suppress(":") + pp.Word(pp.alphas + "_") + pp.Word(pp.alphas + pp.nums + "_")[0, ...]
@ -63,8 +61,7 @@ class LambdaParser:
self.pp_expr ^ self.pp_expr ^
self.pp_macro_def ^ self.pp_macro_def ^
self.pp_command ^ self.pp_command ^
self.pp_call ^ self.pp_call
self.pp_history
) )
def __init__( def __init__(
@ -76,8 +73,7 @@ class LambdaParser:
action_func, action_func,
action_bound, action_bound,
action_macro, action_macro,
action_call, action_call
action_history
): ):
self.make_parser() self.make_parser()
@ -89,7 +85,6 @@ class LambdaParser:
self.pp_macro.set_parse_action(action_macro) self.pp_macro.set_parse_action(action_macro)
self.pp_bound.set_parse_action(action_bound) self.pp_bound.set_parse_action(action_bound)
self.pp_call.set_parse_action(action_call) self.pp_call.set_parse_action(action_call)
self.pp_history.set_parse_action(action_history)
def parse_line(self, line: str): def parse_line(self, line: str):
return self.pp_all.parse_string( return self.pp_all.parse_string(

View File

@ -37,9 +37,6 @@ class MacroDef:
ban_macro_name = ban_macro_name ban_macro_name = ban_macro_name
) )
def set_runner(self, runner):
return self.expr.set_runner(runner)
class Command: class Command:
@staticmethod @staticmethod
def from_parse(result): def from_parse(result):
@ -69,8 +66,7 @@ class Runner:
action_call = lamb.node.Call.from_parse, action_call = lamb.node.Call.from_parse,
action_church = lamb.node.Church.from_parse, action_church = lamb.node.Church.from_parse,
action_macro_def = MacroDef.from_parse, action_macro_def = MacroDef.from_parse,
action_command = Command.from_parse, action_command = Command.from_parse
action_history = lamb.node.History.from_parse
) )
# Maximum amount of reductions. # Maximum amount of reductions.
@ -88,48 +84,22 @@ class Runner:
# so that all digits appear to be changing. # so that all digits appear to be changing.
self.iter_update = 231 self.iter_update = 231
self.history = []
def prompt(self): def prompt(self):
return self.prompt_session.prompt( return self.prompt_session.prompt(
message = self.prompt_message message = self.prompt_message
) )
def parse(self, line) -> tuple[lamb.node.Node | MacroDef | Command, dict]: def parse(self, line):
e = self.parser.parse_line(line) e = self.parser.parse_line(line)
o = {}
if isinstance(e, MacroDef): if isinstance(e, MacroDef):
e.set_runner(self) e.bind_variables(ban_macro_name = e.label)
o = e.bind_variables(ban_macro_name = e.label)
elif isinstance(e, lamb.node.Node): elif isinstance(e, lamb.node.Node):
e.set_runner(self) e.bind_variables()
o = e.bind_variables() return e
return e, o
def reduce(self, node: lamb.node.Node, *, status = {}) -> None: def reduce(self, node: lamb.node.Node) -> None:
# Show warnings
warning_text = []
if status["has_history"] and len(self.history) != 0:
warning_text += [
("class:code", "$"),
("class:warn", " will be expanded to "),
("class:code", str(self.history[-1])),
("class:warn", "\n")
]
for i in status["free_variables"]:
warning_text += [
("class:warn", "Macro "),
("class:code", i),
("class:warn", " will become a free variable.\n"),
]
printf(FormattedText(warning_text), style = lamb.utils.style)
# Reduction Counter. # Reduction Counter.
# We also count macro (and church) expansions, # We also count macro (and church) expansions,
# and subtract those from the final count. # and subtract those from the final count.
@ -149,7 +119,10 @@ class Runner:
print(f" Reducing... {i:,}", end = "\r") print(f" Reducing... {i:,}", end = "\r")
try: try:
red_type, node = lamb.node.reduce(node) red_type, node = lamb.node.reduce(
node,
macro_table = self.macro_table
)
except KeyboardInterrupt: except KeyboardInterrupt:
stop_reason = StopReason.INTERRUPT stop_reason = StopReason.INTERRUPT
break break
@ -165,8 +138,12 @@ class Runner:
if red_type == lamb.node.ReductionType.FUNCTION_APPLY: if red_type == lamb.node.ReductionType.FUNCTION_APPLY:
macro_expansions += 1 macro_expansions += 1
# Expand all remaining macros # Expand all macros if we need to
m, node = lamb.node.finalize_macros(node, force = full_reduce) if full_reduce:
m, node = lamb.node.force_expand_macros(
node,
macro_table = self.macro_table
)
macro_expansions += m macro_expansions += m
if i >= self.iter_update: if i >= self.iter_update:
@ -199,9 +176,6 @@ class Runner:
("class:text", str(node)), # type: ignore ("class:text", str(node)), # type: ignore
] ]
self.history.append(lamb.node.finalize_macros(node, force = True)[1])
printf( printf(
FormattedText(out_text), FormattedText(out_text),
style = lamb.utils.style style = lamb.utils.style
@ -231,7 +205,7 @@ class Runner:
*, *,
silent = False silent = False
) -> None: ) -> None:
e, o = self.parse(line) e = self.parse(line)
# If this line is a macro definition, save the macro. # If this line is a macro definition, save the macro.
if isinstance(e, MacroDef): if isinstance(e, MacroDef):
@ -251,7 +225,7 @@ class Runner:
# If this line is a plain expression, reduce it. # If this line is a plain expression, reduce it.
elif isinstance(e, lamb.node.Node): elif isinstance(e, lamb.node.Node):
self.reduce(e, status = o) self.reduce(e)
# We shouldn't ever get here. # We shouldn't ever get here.
else: else:

View File

@ -11,7 +11,6 @@ style = Style.from_dict({ # type: ignore
"err": "#FF0000", "err": "#FF0000",
"prompt": "#00FFFF", "prompt": "#00FFFF",
"ok": "#B4EC85", "ok": "#B4EC85",
"code": "#AAAAAA italic",
"muted": "#AAAAAA", "muted": "#AAAAAA",
# Syntax # Syntax
@ -24,8 +23,12 @@ style = Style.from_dict({ # type: ignore
# Command formatting # Command formatting
# cmd_h: section titles # cmd_h: section titles
# cmd_code: example snippets
# cmd_text: regular text
# cmd_key: keyboard keys, usually one character # cmd_key: keyboard keys, usually one character
"cmd_h": "#FF6600 bold", "cmd_h": "#FF6600 bold",
"cmd_code": "#AAAAAA italic",
"cmd_text": "#FFFFFF",
"cmd_key": "#B4EC85 bold", "cmd_key": "#B4EC85 bold",
# Only used in greeting # Only used in greeting