def quote(module, contents): clc = module.clc quotation = Quote(clc) quote_expr = quotation.eval(contents) quote_scope: Scope = quotation.clc.scope sym_arg = quote_scope.enter(".external") name_var = new_var(clc, name="external") tenv[sym_arg] = name_var record_fields = [] for attr_name, each in quote_scope.freevars.items(): record_fields.append((each, attr_name, tenv[each])) rho_group = types.ForallScope(clc.location, filename=clc.filename) rho = te.Bound('ρ', rho_group) type_arg = te.Record( te.row_from_list([(attr, t) for _, attr, t in record_fields], te.RowPoly(rho))) tc_state.unify(name_var, type_arg) exp_arg = ir.Expr(type=tc_state.infer(type_arg), expr=sym_arg) block = [ ignore( ir.Set( each, ir.Expr(type=t, expr=ir.Field(base=exp_arg, attr=attr)))) for each, attr, t in record_fields ] block.append(quote_expr) ret_expr = ir.Fun( "<quote>", clc.filename, sym_arg, ir.Expr(expr=ir.Block(block), type=quote_expr.type)) ret_type = te.Arrow(type_arg, quote_expr.type) ret_type = te.Forall(rho_group, (rho, ), ret_type) return ir.Expr(expr=ret_expr, type=ret_type)
def imp(module, qualname: typing.List[str], *, backend=backend): clc = module.clc name = qualname[-1] sym = clc.scope.enter(name) module_finder = backend.search_module(qualname) if module_finder.exist: sym_mod = module_finder.exist type_mod = type_of_value(sym_mod) exp_mod = ir.Expr(expr=sym_mod, type=type_mod) return ignore(ir.Set(module_finder.exist, exp_mod)) filename, get_code = module_finder.filename, module_finder.get_code path = '.'.join(qualname) new_modular = Modular( CompilerLocalContext(scope=backend.mk_top_scope(), filename=filename, path=path)) ast_mod = parse(get_code(), filename) exp_mod = new_modular.eval(ast_mod) tenv[sym] = exp_mod.type backend.remember_module(path, sym) return ignore(ir.Set(sym, exp_mod))
def define(self, is_rec, name, annotated, bound): module = Express(self.clc) loc, name = sexpr.unloc(name) clc = self.clc outer_scope = clc.scope if is_rec: sym_def = outer_scope.require(name) else: sym_def = outer_scope.shadow(name) # may shadow with clc.resume_scope(): inner_scope = outer_scope.sub_scope() clc.scope = inner_scope if annotated: t1 = infer(Typing(clc).eval(annotated)) if sym_def in tenv: unify(inst(tenv[sym_def])[1], inst(t1)[1]) else: tenv[sym_def] = t1 else: if sym_def in tenv: t1 = infer(tenv[sym_def]) else: new_var = tc_state.new_var(Var=types.Var, loc=loc, filename=clc.filename, name=sym_def.name) tenv[sym_def] = t1 = new_var level = tc_state.push_level() bound: ir.Expr = module.eval(bound) t1_inst = te.fresh(tc_state.new_var, infer(t1)) t1_inst = inst(t1_inst, rigid=True)[1] t2_inst = bound.type = inst(infer(bound.type))[1] resolve_instance_(outer_scope, bound) unify(t1_inst, t2_inst) bound.type = generalise_type(tc_state, t2_inst, loc=loc, filename=clc.filename, level=level) unify(bound.type, t1) exp_def = ir.Set(sym_def, bound) return ignore(exp_def)
def let(module, is_rec, seq, body): clc = module.clc with clc.resume_scope(): outer_scope = clc.scope = clc.scope.sub_scope() types = [] for loc, name, annotation, _ in seq: if annotation: type_bind = Typing(clc).eval(annotation) else: type_bind = new_var(clc, name) types.append(type_bind) if is_rec: _, name = sexpr.unloc(name) sym_bind = outer_scope.enter(name) tenv[sym_bind] = type_bind block = [] syms = [] for (loc, name, annotation, bound), sym_type in zip(seq, types): _, name = sexpr.unloc(name) level = tc_state.push_level() inner_scope = clc.scope = outer_scope.sub_scope() if is_rec: sym_bind = inner_scope.require(name) else: sym_bind = inner_scope.enter(name) tenv[sym_bind] = sym_type syms.append(sym_bind) t_inst = te.fresh(tc_state.new_var, sym_type) t_inst = inst(t_inst, rigid=True)[1] bound = module.eval_with_implicit(bound) tc_state.unify(t_inst, bound.type) gen_type = generalise_type(tc_state, t_inst, loc=loc, filename=clc.filename, level=level) bound.type = gen_type unify(gen_type, sym_type) block.append(ignore(ir.Set(sym_bind, bound))) # level = tc_state.push_level() clc.scope = inner_scope.sub_scope() body = module.eval(body) # block.append(body) # body.type = generalise_type(tc_state, body.type, loc=clc.location, filename=clc.filename, level=level) return ir.Expr(type=body.type, expr=ir.Block(block))
def type(module, typename, typedef): clc = module.clc path = clc.path loc, typename = sexpr.unloc(typename) qual_typename = '{}.{}'.format(path, typename) sym_typename = clc.scope.enter(typename) if typedef: # type alias nom_type = tc_state.infer(Typing(clc).eval(typedef)) else: nom_type = types.Nom(qual_typename, loc=loc, filename=clc.filename) tenv[sym_typename] = te.App(types.type_type, nom_type) return wrap_loc( loc, ignore( ir.Set(sym_typename, ir.Expr(type=nom_type, expr=ir.Const(nom_type)))))
def module(module_eval, is_rec, name, stmts, loc=None): loc, name = sexpr.unloc(name) clc = module_eval.clc scope = clc.scope filename = clc.filename path = clc.path = '.'.join( (*filter(None, clc.path.split('.')), name)) # only for recursive modules. sym_mod: typing.Optional[Sym] = None # generated ir outside module; # only for recursive modules. outer_stmts: typing.List[ir.Expr] = [] # generated ir for module itself inner_stmts: typing.List[ir.Expr] = [] # type of module. will be a non-extensible record. type_mod = None # recursive module. if is_rec: sym_mod = scope.enter(name) new_var = tc_state.new_var(Var=types.Var, loc=loc, filename=filename, name=path) type_mod = tenv[sym_mod] = new_var outer_stmts.append( ignore(ir.Set(sym_mod, ignore(ir.Const(()))))) # for preprocessing # 1. recursive functions and # 2. type definitions. filter_stmts = [] for stmt in stmts: _, stmt_unloc = sexpr.unloc(stmt) # type definition if stmt_unloc[0] is sexpr.type_k: inner_stmts.append(module_eval.eval(stmt)) continue filter_stmts.append(stmt) if stmt_unloc[0] is sexpr.def_k: if stmt_unloc[1]: # Recursive definition. It's guaranteed to # be a function in syntax level. loc, n = sexpr.unloc(stmt_unloc[2]) sym = scope.enter(n) tenv[sym] = tc_state.new_var(Var=types.Var, loc=loc, filename=filename, name=n) for stmt in filter_stmts: inner_stmts.append(module_eval.eval(stmt)) syms = [ sym for sym in scope.get_newest_bounds() if sym is not sym_mod ] row_mod = te.row_from_list([(s.name, tenv[s]) for s in syms], te.empty_row) if type_mod: # recursive module tc_state.unify(type_mod, te.Record(row_mod)) else: type_mod = te.Record(row_mod) elts_mod = [ir.Expr(type=tenv[sym], expr=sym) for sym in syms] elts_mod.sort(key=_sort_sym) val_mod = ir.Expr(type=type_mod, expr=ir.Tuple([ anyway(ir.Tuple(elts_mod)), anyway(ir.Tuple([])) ])) inner_stmts.append(val_mod) exp_mod = ir.Expr(type=type_mod, expr=ir.Block(inner_stmts)) if not is_rec: return exp_mod outer_stmts.append(ignore(ir.Set(sym_mod, exp_mod))) outer_stmts.append(ir.Expr(type=type_mod, expr=sym_mod)) return ir.Expr(type=type_mod, expr=ir.Block(outer_stmts))