def desugar_equation(self, params, param_types, result_type, equation): position = equation.position patterns = equation.lhs.application_args() body = equation.rhs if len(patterns) != len(params): self.fail('equations-arity-mismatch', name=name, position=position) self._env.open_scope() # Equation scope fvs = set() for var in syntax.free_variables_list(patterns): if not self._env.is_defined(var): fvs.add(var) self._env.define(var, syntax.Metavar(prefix="t", position=position)) # TODO: allow forced binding by prefixing a variable with "." if len(equation.where) == 0: d_type, d_body = self.check_expr(body) else: d_type, d_body = self.check_let( syntax.Let(declarations=equation.where, body=body, position=position)) self.unify_types(d_type, result_type) unif_goals = [] for param, pattern, t_param in zip(params, patterns, param_types): t_pattern, e_pattern = self.check_expr(pattern) self.unify_types(t_param, t_pattern) unif_goals.append(syntax.unify(param, e_pattern)) alternative = syntax.fresh_many( fvs, syntax.sequence_many1(unif_goals, d_body)) self._env.close_scope() # Equation scope return alternative
def check_application(self, expr): t_fun, e_fun = self.check_expr(expr.fun) t_arg, e_arg = self.check_expr(expr.arg) t_res = syntax.Metavar(prefix='t', position=expr.position) self.unify_types(t_fun, syntax.function(t_arg, t_res)) return (t_res, syntax.Application(fun=e_fun, arg=e_arg, position=expr.position))
def check_fresh(self, expr): self._env.open_scope() self._env.define(expr.var, syntax.Metavar(prefix='t', position=expr.position)) t_body, e_body = self.check_expr(expr.body) self._env.close_scope() return (t_body, syntax.Fresh(var=expr.var, body=e_body, position=expr.position))
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 check_let(self, expr): # Check kinds and extend environment # to allow for recursive definitions. definitions, definition_keys, type_declarations = \ self.check_let_declarations_well_formed(expr) # TODO: Dependency graph graph = self.dependency_graph(definitions) partition = dependencies.partition_dependencies(graph) desugared_declarations = [] for part in partition: part_definitions = {} part_type_declarations = {} for x in part: part_definitions[x] = definitions[x] if x in type_declarations: part_type_declarations[x] = type_declarations[x] part_definition_keys = [] for k in definition_keys: if k in part_definitions: part_definition_keys.append(k) self._env.open_scope() for name, defs in part_definitions.items(): self._env.define(name, syntax.Metavar(prefix='t', position=defs[0].position)) e_decls = [] for name in part_definition_keys: e_decls.append( self.desugar_definition(name, part_definitions[name]) ) self.generalize_types_in_current_scope() self.check_declared_instantiate_real(part_type_declarations) # To reconstruct the final AST ds = [] for e_decl in e_decls: t_decl = syntax.TypeDeclaration( name=e_decl.lhs.name, type=self._env.value(e_decl.lhs.name), position=e_decl.position ) ds.append(t_decl) ds.append(e_decl) desugared_declarations.append(ds) t_body, e_body = self.check_expr(expr.body) for part in reversed(partition): self._env.close_scope() e_body = syntax.Let( declarations=desugared_declarations.pop(), body=e_body, position=expr.position) return t_body, e_body
def check_let(self, expr): # Check kinds and extend environment # to allow for recursive definitions. declared_names = set() definitions = {} definition_keys = [] self._env.open_scope() type_declarations = [] for decl in expr.declarations: if decl.is_type_declaration(): decl = self.check_type_declaration(decl) declared_names.add(decl.name) type_declarations.append(decl) elif decl.is_definition(): head = decl.lhs.application_head() if not head.is_variable(): self.fail('declaration-head-is-not-variable', head=head, position=decl.position) declared_names.add(head.name) if head.name not in definitions: definition_keys.append(head.name) definitions[head.name] = [] definitions[head.name].append(decl) if not self._env.is_locally_defined(head.name): self._env.define( head.name, syntax.Metavar(prefix='t', position=decl.position)) else: raise Exception('Check for declaration not implemented.') defined_names = set(definitions.keys()) if declared_names != defined_names: missing = declared_names - defined_names self.fail('name-declared-but-not-defined', name=missing.pop(), position=expr.position) e_decls = [] for name in definition_keys: e_decls.append(self.desugar_definition(name, definitions[name])) self.generalize_types_in_current_scope() self.check_declared_instantiate_real(type_declarations) body_type, desugared_body = self.check_expr(expr.body) # To reconstruct the final AST desugared_declarations = [] for e_decl in e_decls: t_decl = syntax.TypeDeclaration(name=e_decl.lhs.name, type=self._env.value( e_decl.lhs.name), position=e_decl.position) desugared_declarations.append(t_decl) desugared_declarations.append(e_decl) self._env.close_scope() return (body_type, syntax.Let(declarations=desugared_declarations, body=desugared_body, position=expr.position))