Exemplo n.º 1
0
def _check_Call_expr(call, t, env):
    """Application."""

    assert call.__class__ is ast.Call

    f = call.func
    a = call.args
    k = call.keywords
    s = call.starargs
    kw = call.kwargs

    # All App rules have specific forms for keywords, starargs, and kwargs.
    if not k and not s and not kw:

        # (App1) assignment rule.
        if not a:
            return check_expr(f, PType.arrow(unit_t, t), env)

        # (App2) assignment rule.
        elif len(a) == 1 and f.__class__ is ast.Name:
            f_t = env_get(env, f.id)
            return check_expr(a[0], f_t.dom, env) and f_t.ran == t

        # (App3) assignment rule.
        elif f.__class__ is ast.Name:
            f_t = env_get(env, f.id)
            tup = ast.Tuple([b for b in a], ast.Load())
            return check_expr(tup, f_t.dom, env) and f_t.ran == t

    # No assignment rule found.
    return False
Exemplo n.º 2
0
def _check_Expr_stmt(stmt, env):
    """Expression Statement."""

    assert stmt.__class__ is ast.Expr

    e = stmt.value

    # (Expr-Stmt) assignment rule
    if e.__class__ is ast.Call and e.func.__class__ is ast.Name:
        f = e.func
        f_t = env_get(env, f.id)
        return check_expr(e, f_t.ran, env)

    # No assignment rule found.
    else:
        return False
Exemplo n.º 3
0
def _check_Return_stmt(stmt, env):
    """Return Statement."""
    
    assert stmt.__class__ is ast.Return

    e = stmt.value

    try:
        r_t = env_get(env, "return")
    except TypeUnspecifiedError:
        return False

    # (RetU) assignment rule.
    if not e:
        return r_t == unit_t

    # (Ret) assignment rule.
    else:
        return check_expr(e, r_t, env)
Exemplo n.º 4
0
def _check_Name_expr(name, t, env):
    """Identifiers."""

    assert name.__class__ is ast.Name

    x = name.id

    base_env = {"True" : bool_t, "False" : bool_t, "None" : unit_t}

    # (Base-Env) assignment rule.
    if x in base_env:
        return t == base_env[x]

    # (Idn) assignment rule.
    elif env_get(env, x) == t:
        return True

    # No assignment rule found.
    else:
        return False
Exemplo n.º 5
0
def _check_FunctionDef_stmt(stmt, env):
    """Function Definition."""

    assert stmt.__class__ is ast.FunctionDef

    f = stmt.name
    a = stmt.args
    b = stmt.body
    d = stmt.decorator_list

    # All Fn-Def rules have specific forms for args and decorator_list.
    if (all(arg.__class__ is ast.Name for arg in a.args) and
        not a.vararg and not a.kwarg and not a.defaults and not d):

        f_t = env_get(env, f)

        # (Fn-Def1) assignment rule.
        if not a.args:
            new_env = dict(env.items() + [("return", f_t.ran)])
            return check_stmt_list(b, new_env)

        # (Fn-Def2) assignment rule.
        elif len(a.args) == 1 and f_t.dom != unit_t:
            arg_id = a.args[0].id
            new_env = dict(env.items() +
                           [(arg_id, f_t.dom), ("return", f_t.ran)])
            return check_stmt_list(b, new_env)

        # (Fn-Def3) assignment rule.
        elif f_t.dom.is_tuple() and f_t.dom.tuple_len() == len(a.args):
            arg_ids = map(lambda x: x.id, a.args)
            arg_ts = f_t.dom.elts
            new_env = dict(env.items() +
                           zip(arg_ids, arg_ts) + [("return", f_t.ran)])
            return check_stmt_list(b, new_env)

    # No assignment rule found.
    return False
Exemplo n.º 6
0
def check_stmt_list(stmts, env):
    """
    Check whether each stmt in `stmts` typechecks correctly. `env` is the
    common type environment shared by all stmts in `stmts`
    """

    # (Stmts-Base) assignment rule.
    if not stmts:
        return True

    # (Stmts) assignment rule.
    elif stmts[0].__class__ is not TypeDec:
        return check_stmt(stmts[0], env) and check_stmt_list(stmts[1:], env)

    # (Stmts-LetA) assignment rule.
    elif (stmts[1].__class__ is ast.Assign and
          len(stmts[0].targets) == 1 and len(stmts[1].targets) == 1 and
          stmts[0].targets[0].__class__ is ast.Name and
          stmts[1].targets[0].__class__ is ast.Name and
          stmts[0].targets[0].id == stmts[1].targets[0].id):
        tdec = stmts[0]
        tar_id = tdec.targets[0].id
        assmt = stmts[1]

        # Throw an error if the typedec target has already been declared with a
        # different type.
        try:
            tar_t = env_get(env, tar_id)
            if tar_t != tedc.t:
                raise TypeMultiSpecifiedError()
        except TypeUnspecifiedError:
            pass

        new_env = dict(env)
        new_env[tar_id] = tdec.t.quantify()

        return (check_expr(assmt.value, tdec.t, env) and
                check_stmt_list(stmts[2:], new_env))        

    # (Stmts-LetF) assignment rule.
    elif (stmts[1].__class__ is ast.FunctionDef and
          len(stmts[0].targets) == 1 and stmts[0].t.is_arrow() and
          stmts[0].targets[0].id == stmts[1].name):
        tdec = stmts[0]
        tar_id = tdec.targets[0].id
        fndef = stmts[1]

        # Throw an error if the typedec target has already been declared with a
        # different type.
        try:
            tar_t = env_get(env, tar_id)
            if tar_t != tdec.t:
                raise TypeMultiSpecifiedError()
        except TypeUnspecifiedError:
            pass

        env1, env2 = dict(env), dict(env)
        env1[tar_id] = tdec.t
        env2[tar_id] = tdec.t.quantify()

        return check_stmt(fndef, env1) and check_stmt_list(stmts[2:], env2)

    # (StmtsT) assignment rule.
    else:
        tdec = stmts[0]

        # Throw an error if a typedec target has already been declared with a
        # different type.
        for tar in tdec.targets:
            try:
                tar_t = env_get(env, tar.id)
                if tar_t != tdec.t:
                    raise TypeMultiSpecifiedError()
            except TypeUnspecifiedError:
                pass

        new_env = dict(env)
        for tar in tdec.targets:
            new_env[tar.id] = tdec.t

        return check_stmt_list(stmts[1:], new_env)

    # No assignment rule found.
    return False