Add special case to improve quality of generated code for simple functions

This commit is contained in:
Emi Simpson 2024-03-16 09:36:30 -04:00
parent 79deebabf4
commit 55fa7add0e
Signed by: Emi
GPG key ID: A12F2C2FFDC3D847

34
ir.py
View file

@ -116,10 +116,40 @@ class Function:
def codegen_inner(self) -> str:
return unwrap_r(self.eliminate(Variable('$'))).codegen()
def try_codegen_sp(self) -> Option[Tuple[str, str]]:
""" A special-case of codegen inner (see description)
In certain cases, starting a function with a full match tree may be unnecessary.
Specifically, if there exists only one possible branch and that branch binds only
one value and that value is equal to the whole entire input, rather than assigning
that input to a new variable, we may simply use argument variable instead.
This method returns the generated code for the inner branch in such a case.
Additionally, the second string returned represents the name of the variable which
ought to be bound as the argument. If the argument is unused, this will be "$".
"""
match self.forms:
case [(patt, expr)]: # A single possible branch
match patt.bindings():
case []: # Binds nothing
return Some((expr.codegen(), '$'))
case [(var, [])]: # Binds a single variable to the entire input
return Some((expr.codegen(), var))
return None
def codegen(self) -> str:
return '$=>' + self.codegen_inner()
match self.try_codegen_sp():
case Some((codegen, var)):
return f'{var}=>{codegen}'
case None:
return '$=>' + self.codegen_inner()
raise Exception('Unreachable')
def codegen_named(self, name) -> str:
return f'function {name}($){{return {self.codegen_inner()}}}'
match self.try_codegen_sp():
case Some((codegen, var)):
return f'function {name}({var}){{return {codegen}}}'
case None:
return f'function {name}($){{return {self.codegen_inner()}}}'
raise Exception('Unreachable')
def __repr__(self) -> str:
return '{ ' + ', '.join('"' + repr(repr(p))[1:-1] + '" : ' + repr(e) for (p, e) in self.forms) + ' }'