示例#1
0
        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)
示例#2
0
        def call(module, f, arg):
            clc = module.clc
            f = module.eval(f)
            f.type = infer(f.type)

            to_mono = None
            to_poly = None
            func_type = f.type

            # row polymorphisms
            while isinstance(func_type, te.Implicit):
                func_type = func_type.type
            if isinstance(func_type, te.Arrow):
                # layout of record might change correspondingly.
                to_mono = func_type.ret
                to_poly = func_type.arg

            f.type = inst(f.type)[1]
            resolve_instance_(clc.scope, f)
            level = tc_state.push_level()
            arg = module.eval(arg)
            arg.type = infer(arg.type)
            arg_is_forall = isinstance(arg.type, te.Forall)
            arg.type = inst(arg.type)[1]
            resolve_instance_(clc.scope, arg)
            f.type = infer(f.type)
            if arg_is_forall and isinstance(f.type, te.Arrow) and isinstance(
                    f.type.arg, te.Forall):
                # a simple strategy to support higher rank types when annotated.
                f_type_arg = inst(f.type.arg, rigid=True)[1]
                unify(arg.type, f_type_arg)
                ret_t = f.type.ret
            else:
                ret_t = new_var(clc, name='ret')
                inst_arrow = te.Arrow(arg.type, ret_t)
                unify(inst_arrow, f.type)
                ret_t = generalise_type(tc_state,
                                        ret_t,
                                        loc=clc.location,
                                        filename=clc.filename,
                                        level=level)

            if to_poly:
                arg = ir.Expr(type=arg.type,
                              expr=ir.Polymorphization(layout_type=to_poly,
                                                       expr=arg))

            ret = ir.Expr(type=ret_t, expr=ir.Invoke(f, arg))

            if to_mono:
                ret = ir.Expr(type=ret_t,
                              expr=ir.Momomorphization(layout_type=to_mono,
                                                       expr=ret))
            return ret
示例#3
0
        def lam(module, arg, type, ret):
            loc, name = sexpr.unloc(arg)
            clc = module.clc
            outer_scope = clc.scope
            filename = clc.filename
            path = clc.path

            if type:
                type_arg = tc_state.infer(Typing(clc).eval(type))
            else:
                type_arg = new_var(clc, name)

            with clc.resume_scope():
                # level = tc_state.push_level()
                inner_scope = outer_scope.sub_scope(hold_bound=True)
                clc.scope = inner_scope
                sym_arg = inner_scope.enter(name)
                tenv[sym_arg] = type_arg
                ret = module.eval(ret)
                lam_type = te.Arrow(
                    type_arg, ret.type
                )  # lam_type = generalise_type(tc_state, lam_type, loc=loc, filename=filename, level=level)

            name = "{} |{}|".format(path, name)
            sym_arg = ir.Fun(name, filename, sym_arg, ret)
            return ir.Expr(type=lam_type, expr=sym_arg)
示例#4
0
 def tuple(module, elts):
     if not elts:
         return ir.Expr(expr=ir.Const(()), type=types.unit_t)
     if len(elts) is 1:
         ret = module.eval(elts[0])
         return ret
     level = tc_state.push_level()
     elts = list(map(module.eval_with_implicit, elts))
     type = te.Tuple(tuple(e.type for e in elts))
     loc = module.clc.location
     filename = module.clc.filename
     type = generalise_type(tc_state,
                            type,
                            loc=loc,
                            filename=filename,
                            level=level)
     return ir.Expr(expr=ir.Tuple(elts), type=type)
示例#5
0
def _resolve_instance_(implicit_types: typing.List[te.T], scope: Scope,
                       expr: ir.Expr):
    available_syms = list(scope.boundvars.values()) + list(
        scope.freevars.values())
    explicit_type = expr.type
    implicit_types.reverse()
    for implicit_t in implicit_types:
        instanced = ir.Expr(type=explicit_type, expr=expr.expr)
        expr.expr = ir.Instance(implicit_t, available_syms, instanced)
示例#6
0
        def record(module, pairs, row):
            clc = module.clc
            filename = clc.filename
            location = clc.location
            level = tc_state.push_level()
            kv = []
            for each in pairs:
                loc, (attr_name, expr) = sexpr.unloc(each)
                expr = module.eval_with_implicit(expr)
                kv.append((attr_name, expr))

            kv.sort(key=lambda tp: tp[0])
            elts = [elt for _, elt in kv]
            left = ir.Tuple(elts)
            fields = []
            for k, v in kv:
                v_type = tc_state.infer(v.type)
                if isinstance(v_type, te.Forall):
                    v_type = v_type.poly_type
                fields.append((k, v_type))

            if not row:
                mono = te.Record(te.row_from_list(fields, te.empty_row))
                mono = generalise_type(tc_state,
                                       mono,
                                       level=level,
                                       loc=location,
                                       filename=filename)
                return ir.Expr(expr=ir.Tuple(
                    [anyway(left), anyway(ir.Tuple([]))]),
                               type=mono)

            right = module.eval_with_implicit(row)
            poly = tc_state.infer(
                te.Record(te.row_from_list(fields, te.RowPoly(right.type))))
            poly = generalise_type(tc_state,
                                   poly,
                                   level=level,
                                   loc=location,
                                   filename=filename)
            return ir.Expr(expr=ir.Merge(left=anyway(left), right=right),
                           type=poly)
示例#7
0
        def ite(module, cond, true_clause, else_clause):
            # level = tc_state.push_level()
            cond = module.eval_with_implicit(cond)

            tc_state.unify(cond.type, types.bool_t)

            tc = module.eval_with_implicit(true_clause)
            ec = module.eval_with_implicit(else_clause)

            tc_state.unify(tc.type, ec.type)
            # clc = module.clc
            # ec.type = tc.type = generalise_type(tc_state, tc.type, level=level, loc=clc.location, filename=clc.filename)
            return ir.Expr(expr=ir.ITE(cond, tc, ec), type=tc.type)
示例#8
0
        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))
示例#9
0
        def attr(module, base, attr_name: str):
            # level = tc_state.push_level()
            base = module.eval_with_implicit(base)
            clc = module.clc
            var = new_var(clc, 'attr')
            tho = new_var(clc, 'ρ')
            record_type = te.Record(
                te.row_from_list([(attr_name, var)], te.RowPoly(tho)))

            # TODO: how to deal with a polymorphic record value?
            # e.g., forall a. {x : ... | a}
            unify(record_type, base.type)
            # var = infer(var)
            # var = generalise_type(tc_state, var, level=level, loc=clc.location, filename=clc.filename)
            return ir.Expr(expr=ir.Field(base=base, attr=attr_name), type=var)
示例#10
0
        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)))))
示例#11
0
        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))
示例#12
0
def wrap_loc(loc: Location, expr: ir.Expr):
    return ir.Expr(type=expr.type, expr=ir.WrapLoc(loc, expr))
示例#13
0
def anyway(x: ir.BaseExpr):
    return ir.Expr(expr=x, type=types.anyway_type)
示例#14
0
def ignore(ex: ir.BaseExpr):
    return ir.Expr(type=types.unit_t, expr=ex)
示例#15
0
}


def ignore(ex: ir.BaseExpr):
    return ir.Expr(type=types.unit_t, expr=ex)


def anyway(x: ir.BaseExpr):
    return ir.Expr(expr=x, type=types.anyway_type)


def wrap_loc(loc: Location, expr: ir.Expr):
    return ir.Expr(type=expr.type, expr=ir.WrapLoc(loc, expr))


unit = ir.Expr(type=types.unit_t, expr=ir.Const(()))


## Compiler contexts
class CompilerGlobalContext:
    tc_state: TCState
    tenv: typing.Dict[Sym, te.T]
    backend: 'BackEnd'

    def __init__(self, tc_state: TCState, tenv: typing.Dict[Sym, te.T],
                 backend: 'BackEnd'):
        self.tc_state = tc_state
        self.tenv = tenv
        self.backend = backend

    @classmethod
示例#16
0
 def coerce(module, expr):
     expr = module.eval(expr)
     loc, _ = sexpr.unloc(expr)
     return ir.Expr(expr=ir.Coerce(expr),
                    type=new_var(module.clc, "coerce"))
示例#17
0
 def literal(module, val):
     my_type = type_map[type(val)]
     return ir.Expr(type=my_type, expr=ir.Const(val))
示例#18
0
 def type(module, name, definition):
     assert name is None
     t = Typing(module.clc).eval(definition)
     return ir.Expr(expr=ir.Const(t), type=te.App(types.type_type, t))
示例#19
0
 def loc(module, location, contents):
     module.clc.location = location
     a = module.eval(contents)
     return ir.Expr(type=a.type, expr=ir.WrapLoc(location, a))
示例#20
0
 def extern(module, foreign_code):
     clc = module.clc
     return ir.Expr(expr=ir.Extern(foreign_code),
                    type=new_var(clc, 'extern'))
示例#21
0
        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))
示例#22
0
 def eval_sym(self, x: str) -> ir.Expr:
     scope = self.clc.scope
     my_type = type_of_value(scope.require(x))
     var = scope.require(x)
     return ir.Expr(type=my_type, expr=var)