Improved macro reduction

master
Mark 2022-10-21 17:13:58 -07:00
parent 01632f6ec3
commit a4af47435a
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
2 changed files with 38 additions and 9 deletions

View File

@ -6,7 +6,6 @@
- Good command parsing (`:help`, `:save`, `:load`, `:macros`, `:clear` are a bare minimum)
- Python files: installable, package list, etc
- $\alpha$-equivalence check
- Don't expand macros until you absolutely have to
- Versioning
- Clean up runner & printing
- Count reductions

View File

@ -109,15 +109,36 @@ class macro(LambdaToken):
raise TypeError("Can only compare macro with macro")
return self.name == other.name
def reduce(self, macro_table = {}, *, auto_free_vars = True) -> ReductionStatus:
if self.name in macro_table:
def reduce(
self,
macro_table = {},
*,
# To keep output readable, we avoid expanding macros as often as possible.
# Macros are irreducible if force_substitute is false.
force_substitute = False,
# If this is false, error when macros aren't defined instead of
# invisibly making a free variable.
auto_free_vars = True
) -> ReductionStatus:
if (self.name in macro_table) and force_substitute:
if force_substitute: # Only expand macros if we NEED to
return ReductionStatus(
output = macro_table[self.name],
reduction_type = ReductionType.MACRO_EXPAND,
was_reduced = True
)
else: # Otherwise, do nothing.
return ReductionStatus(
output = self,
reduction_type = ReductionType.MACRO_EXPAND,
was_reduced = False
)
elif not auto_free_vars:
raise NameError(f"Name {self.name} is not defined!")
else:
return ReductionStatus(
output = free_variable(self.name),
@ -449,8 +470,17 @@ class lambda_apply(LambdaToken):
# Otherwise, try to reduce self.fn.
# If that is impossible, try to reduce self.arg.
else:
if isinstance(self.fn, macro):
# Macros must be reduced before we apply them as functions.
# This is the only place we force substitution.
r = self.fn.reduce(
macro_table,
force_substitute = True
)
else:
r = self.fn.reduce(macro_table)
# If a macro becomes a free variable,
# reduce twice.
if r.reduction_type == ReductionType.MACRO_TO_FREE: