def desugar_definition(self, name, equations): position = equations[0].position alternatives = [] patterns_0 = equations[0].lhs.application_args() params = [syntax.fresh_variable(position=position) for pat in patterns_0] definition_type = self._env.value(name) self._env.open_scope() # Definition scope param_types = [] for param in params: param_type = syntax.Metavar(prefix='t', position=position) self._env.define(param, param_type) param_types.append(param_type) result_type = syntax.Metavar(prefix='t', position=position) self.unify_types( definition_type, syntax.function_many(param_types, result_type) ) for equation in equations: alternatives.append( self.desugar_equation(params, param_types, result_type, equation) ) rhs = syntax.lambda_many( [param.name for param in params], syntax.alternative_many(alternatives, position=position), position=position, ) self._env.close_scope() # Definition scope return syntax.Definition( lhs=syntax.Variable(name=name, position=position), rhs=rhs, where=[], position=position)
def unify(self, goals): if not goals: yield values.unit() return (value1, value2) = goals[0] goals = goals[1:] if not value1.is_decided(): for v1 in self.eval_value(value1): yield from self.unify([(v1, value2)] + goals) return elif not value2.is_decided(): for v2 in self.eval_value(value2): yield from self.unify([(value1, v2)] + goals) return if value1.is_integer_constant() and value2.is_integer_constant(): if value1.value == value2.value: yield from self.unify(goals) elif value1.is_rigid_structure() and value2.is_rigid_structure(): if value1.constructor == value2.constructor and \ len(value1.args) == len(value2.args): subgoals = list(zip(value1.args, value2.args)) yield from self.unify(subgoals + goals) # Same head: # x t1 ... tn == x s1 ... sn #elif val1.is_flex_structure() \ # and val2.is_flex_structure() \ # and val1.symbol == val2.symbol \ # and len(val1.args) == len(val2.args): # subgoals = list(zip(val1.args, val2.args)) # yield from self.unify(subgoals + goals) elif value1.is_flex_structure() and len(value1.args) == 0: # TODO: occurs check assert not value1.symbol.is_instantiated() # decided value1.symbol.instantiate(value2) yield from self.unify(goals) value1.symbol.uninstantiate() elif value1.is_flex_structure() and len(value1.args) > 0: # TODO: occurs check assert not value1.symbol.is_instantiated() # decided new_var = syntax.fresh_variable() params = [syntax.fresh_variable() for arg in value1.args] term = syntax.lambda_many( [p.name for p in params], syntax.alternative( syntax.sequence_many1( [ syntax.unify(p, a) for p, a in zip(params, value1.args) ], value2 # body ), syntax.application_many(new_var, params))) env = environment.PersistentEnvironment() env.define(new_var.name, values.FlexStructure(values.Metavar(prefix='F'), [])) value1.symbol.instantiate(values.Thunk(term, env)) yield from self.unify(goals) value1.symbol.uninstantiate() elif value2.is_flex_structure(): yield from self.unify([(value2, value1)] + goals) else: return # Otherwise we fail
def unify(self, goals): if len(goals) == 0: yield values.unit() return (val1, val2) = goals[0] goals = goals[1:] if not val1.is_decided(): for v1 in self.eval_value(val1): yield from self.unify([(v1, val2)] + goals) return elif not val2.is_decided(): for v2 in self.eval_value(val2): yield from self.unify([(val1, v2)] + goals) return if val1.is_integer_constant() and val2.is_integer_constant(): if val1.value == val2.value: yield from self.unify(goals) elif val1.is_rigid_structure() and val2.is_rigid_structure(): if val1.constructor == val2.constructor and \ len(val1.args) == len(val2.args): subgoals = list(zip(val1.args, val2.args)) yield from self.unify(subgoals + goals) # Same head: # x t1 ... tn == x s1 ... sn elif val1.is_flex_structure() \ and val2.is_flex_structure() \ and val1.symbol == val2.symbol \ and len(val1.args) == len(val2.args): subgoals = list(zip(val1.args, val2.args)) yield from self.unify(subgoals + goals) elif val1.is_flex_structure() and len(val1.args) == 0: # TODO: occurs check assert not val1.symbol.is_instantiated() # decided val1.symbol.instantiate(val2) yield from self.unify(goals) val1.symbol.uninstantiate() elif val1.is_flex_structure() and len(val1.args) > 0: # TODO: occurs check assert not val1.symbol.is_instantiated() # decided new_var = syntax.fresh_variable() params = [] u_goals = [] for arg in val1.args: param = syntax.fresh_variable() params.append(param) u_goals.append(syntax.unify(param, arg)) term = syntax.lambda_many( [p.name for p in params], syntax.alternative( syntax.sequence_many1( u_goals, val2 # body ), syntax.application_many(new_var, params))) env = environment.PersistentEnvironment() env.define(new_var.name, values.FlexStructure(values.Metavar(prefix='F'), [])) val1.symbol.instantiate(values.Thunk(term, env)) yield from self.unify(goals) val1.symbol.uninstantiate() elif val2.is_flex_structure(): yield from self.unify([(val2, val1)] + goals) elif val1.is_closure(): #print('OPEN') #print(val1.var) #print(val1.body) #print(val1.env) uvar = values.UniversalVariable(prefix=val1.var) uval = values.UniversalStructure(uvar, []) env1 = val1.env.extended() env2 = environment.PersistentEnvironment() env1.define(val1.var, uval) env2.define(val1.var, uval) lhs = values.Thunk(val1.body, env1) rhs = values.Thunk(syntax.Application(fun=val2, arg=uval), env2) for x in self.unify([(lhs, rhs)]): # TODO: # forbid metavariables pointing directly # or indirectly to uvar # (???) yield from self.unify(goals) elif val2.is_closure(): yield from self.unify([(val2, val1)] + goals) else: print(val1, val2) return # Otherwise we fail