def eval_let(self, expr, env): extended_env = env.extended() for decl in expr.declarations: if not decl.is_definition(): continue extended_env.define(decl.lhs.name, values.Thunk(decl.rhs, extended_env)) yield from self.eval_expression(expr.body, extended_env)
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 eval_application(self, expr, env): for value in self.eval_expression(expr.fun, env): yield from self.apply(value, values.Thunk(expr.arg, env))
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