예제 #1
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))
예제 #2
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)
예제 #3
0
파일: typing.py 프로젝트: RemuLang/proud
        def record(module, pairs, row):
            _, pairs = sexpr.unloc(pairs)
            if row:
                row_t = te.RowPoly(module.eval(row))
            else:
                row_t = te.empty_row

            fields = [(k, module.eval(v)) for k, v in pairs]
            row_t = te.row_from_list(fields, row_t)
            return te.Record(row_t)
예제 #4
0
        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)
예제 #5
0
파일: typing.py 프로젝트: RemuLang/proud
        def exist(module, bound_vars: tuple, monotype):
            bound_vars_ = set(bound_vars)
            if len(bound_vars) != len(bound_vars_):
                raise excs.DuplicatedNamedTypeVar(bound_vars_)
            bound_vars = bound_vars_
            filename = module.clc.filename
            scope = module.clc.scope
            for n in bound_vars:
                loc, n = sexpr.unloc(n)
                sym = scope.enter(n)
                tvar = tc_state.user_var(Var=types.Var,
                                         loc=loc,
                                         filename=filename,
                                         name=n)
                tenv[sym] = te.App(types.type_type, tvar)

            return module.eval(monotype)
예제 #6
0
파일: typing.py 프로젝트: RemuLang/proud
 def forall(module, unbound_fresh_decls: typing.Tuple[str, ...],
            polytype):
     fresh_vars_ = set(unbound_fresh_decls)
     if len(fresh_vars_) != len(unbound_fresh_decls):
         raise excs.DuplicatedNamedTypeVar(fresh_vars_)
     unbound_fresh_decls = fresh_vars_
     clc = module.clc
     forall_scope = types.ForallScope(clc.location, clc.filename)
     bound_vars = []
     with clc.resume_scope():
         clc.scope = sub_scope = clc.scope.sub_scope()
         for n in unbound_fresh_decls:
             _, n = sexpr.unloc(n)
             sym = sub_scope.enter(n)
             bound_var = te.Bound(n, forall_scope)
             bound_vars.append(bound_var)
             tenv[sym] = te.App(types.type_type, bound_var)
         return te.Forall(forall_scope, tuple(bound_vars),
                          module.eval(polytype))
예제 #7
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)
예제 #8
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)))))
예제 #9
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"))
예제 #10
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))