Ejemplo n.º 1
0
struct symtable *
PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
{
    struct symtable *st = symtable_new();
    asdl_seq *seq;
    int i;

    if (st == NULL)
        return st;
    st->st_filename = filename;
    st->st_future = future;
    if (!GET_IDENTIFIER(top) ||
        !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0)) {
        PySymtable_Free(st);
        return NULL;
    }

    st->st_top = st->st_cur;
    st->st_cur->ste_unoptimized = OPT_TOPLEVEL;
    /* Any other top-level initialization? */
    switch (mod->kind) {
    case Module_kind:
        seq = mod->v.Module.body;
        for (i = 0; i < asdl_seq_LEN(seq); i++)
            if (!symtable_visit_stmt(st,
                        (stmt_ty)asdl_seq_GET(seq, i)))
                goto error;
        break;
    case Expression_kind:
        if (!symtable_visit_expr(st, mod->v.Expression.body))
            goto error;
        break;
    case Interactive_kind:
        seq = mod->v.Interactive.body;
        for (i = 0; i < asdl_seq_LEN(seq); i++)
            if (!symtable_visit_stmt(st,
                        (stmt_ty)asdl_seq_GET(seq, i)))
                goto error;
        break;
    case Suite_kind:
        PyErr_SetString(PyExc_RuntimeError,
                        "this compiler does not handle Suites");
        goto error;
    }
    if (!symtable_exit_block(st, (void *)mod)) {
        PySymtable_Free(st);
        return NULL;
    }
    if (symtable_analyze(st))
        return st;
    PySymtable_Free(st);
    return NULL;
 error:
    (void) symtable_exit_block(st, (void *)mod);
    PySymtable_Free(st);
    return NULL;
}
Ejemplo n.º 2
0
static int
future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
{
    int i, found_docstring = 0, done = 0, prev_line = 0;

    if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
        return 1;

    /* A subsequent pass will detect future imports that don't
       appear at the beginning of the file.  There's one case,
       however, that is easier to handle here: A series of imports
       joined by semi-colons, where the first import is a future
       statement but some subsequent import has the future form
       but is preceded by a regular import.
    */


    for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
        stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);

        if (done && s->lineno > prev_line)
            return 1;
        prev_line = s->lineno;

        /* The tests below will return from this function unless it is
           still possible to find a future statement.  The only things
           that can precede a future statement are another future
           statement and a doc string.
        */

        if (s->kind == ImportFrom_kind) {
            identifier modname = s->v.ImportFrom.module;
            if (modname && PyString_GET_SIZE(modname) == 10 &&
                !strcmp(PyString_AS_STRING(modname), "__future__")) {
                if (done) {
                    PyErr_SetString(PyExc_SyntaxError,
                                    ERR_LATE_FUTURE);
                    PyErr_SyntaxLocation(filename,
                                         s->lineno);
                    return 0;
                }
                if (!future_check_features(ff, s, filename))
                    return 0;
                ff->ff_lineno = s->lineno;
            }
            else
                done = 1;
        }
        else if (s->kind == Expr_kind && !found_docstring) {
            expr_ty e = s->v.Expr.value;
            if (e->kind != Str_kind)
                done = 1;
            else
                found_docstring = 1;
        }
        else
            done = 1;
    }
    return 1;
}
Ejemplo n.º 3
0
static int
future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
{
    int i, done = 0, prev_line = 0;

    if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
        return 1;

    if (asdl_seq_LEN(mod->v.Module.body) == 0)
        return 1;

    /* A subsequent pass will detect future imports that don't
       appear at the beginning of the file.  There's one case,
       however, that is easier to handle here: A series of imports
       joined by semi-colons, where the first import is a future
       statement but some subsequent import has the future form
       but is preceded by a regular import.
    */

    i = 0;
    if (_PyAST_GetDocString(mod->v.Module.body) != NULL)
        i++;

    for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {
        stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);

        if (done && s->lineno > prev_line)
            return 1;
        prev_line = s->lineno;

        /* The tests below will return from this function unless it is
           still possible to find a future statement.  The only things
           that can precede a future statement are another future
           statement and a doc string.
        */

        if (s->kind == ImportFrom_kind) {
            identifier modname = s->v.ImportFrom.module;
            if (modname &&
                _PyUnicode_EqualToASCIIString(modname, "__future__")) {
                if (done) {
                    PyErr_SetString(PyExc_SyntaxError,
                                    ERR_LATE_FUTURE);
                    PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
                    return 0;
                }
                if (!future_check_features(ff, s, filename))
                    return 0;
                ff->ff_lineno = s->lineno;
            }
            else {
                done = 1;
            }
        }
        else {
            done = 1;
        }
    }
    return 1;
}
Ejemplo n.º 4
0
static int 
symtable_visit_genexp(struct symtable *st, expr_ty e)
{
	comprehension_ty outermost = ((comprehension_ty)
			 (asdl_seq_GET(e->v.GeneratorExp.generators, 0)));
	/* Outermost iterator is evaluated in current scope */
	VISIT(st, expr, outermost->iter);
	/* Create generator scope for the rest */
	if (!GET_IDENTIFIER(genexpr) ||
	    !symtable_enter_block(st, genexpr, FunctionBlock, (void *)e, 0)) {
		return 0;
	}
	st->st_cur->ste_generator = 1;
	/* Outermost iter is received as an argument */
	if (!symtable_implicit_arg(st, 0)) {
		symtable_exit_block(st, (void *)e);
		return 0;
	}
	VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e);
	VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e);
	VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension,
				e->v.GeneratorExp.generators, 1, (void*)e);
	VISIT_IN_BLOCK(st, expr, e->v.GeneratorExp.elt, (void*)e);
	return symtable_exit_block(st, (void *)e);
}
Ejemplo n.º 5
0
static int
symtable_visit_params_nested(struct symtable *st, asdl_seq *args)
{
    int i;
    for (i = 0; i < asdl_seq_LEN(args); i++) {
        expr_ty arg = (expr_ty)asdl_seq_GET(args, i);
        if (arg->kind == Tuple_kind &&
            !symtable_visit_params(st, arg->v.Tuple.elts, 0))
            return 0;
    }

    return 1;
}
Ejemplo n.º 6
0
static int
future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
{
    int i;
    asdl_seq *names;

    assert(s->kind == ImportFrom_kind);

    names = s->v.ImportFrom.names;
    for (i = 0; i < asdl_seq_LEN(names); i++) {
        alias_ty name = (alias_ty)asdl_seq_GET(names, i);
        const char *feature = PyUnicode_AsUTF8(name->name);
        if (!feature)
            return 0;
        if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
            ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
        } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) {
            ff->ff_features |= CO_FUTURE_ANNOTATIONS;
        } else if (strcmp(feature, "braces") == 0) {
            PyErr_SetString(PyExc_SyntaxError,
                            "not a chance");
            PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
            return 0;
        } else {
            PyErr_Format(PyExc_SyntaxError,
                         UNDEFINED_FUTURE_FEATURE, feature);
            PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
            return 0;
        }
    }
    return 1;
}
Ejemplo n.º 7
0
static int
fold_unaryop(expr_ty node, PyArena *arena, int optimize)
{
    expr_ty arg = node->v.UnaryOp.operand;

    if (!is_const(arg)) {
        /* Fold not into comparison */
        if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
                asdl_seq_LEN(arg->v.Compare.ops) == 1) {
            /* Eq and NotEq are often implemented in terms of one another, so
               folding not (self == other) into self != other breaks implementation
               of !=. Detecting such cases doesn't seem worthwhile.
               Python uses </> for 'is subset'/'is superset' operations on sets.
               They don't satisfy not folding laws. */
            int op = asdl_seq_GET(arg->v.Compare.ops, 0);
            switch (op) {
            case Is:
                op = IsNot;
                break;
            case IsNot:
                op = Is;
                break;
            case In:
                op = NotIn;
                break;
            case NotIn:
                op = In;
                break;
            default:
                op = 0;
            }
            if (op) {
                asdl_seq_SET(arg->v.Compare.ops, 0, op);
                COPY_NODE(node, arg);
                return 1;
            }
        }
        return 1;
    }

    typedef PyObject *(*unary_op)(PyObject*);
    static const unary_op ops[] = {
        [Invert] = PyNumber_Invert,
        [Not] = unary_not,
        [UAdd] = PyNumber_Positive,
        [USub] = PyNumber_Negative,
    };
Ejemplo n.º 8
0
static int
future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
{
    int i;
    asdl_seq *names;

    assert(s->kind == ImportFrom_kind);

    names = s->v.ImportFrom.names;
    for (i = 0; i < asdl_seq_LEN(names); i++) {
        alias_ty name = (alias_ty)asdl_seq_GET(names, i);
        const char *feature = PyString_AsString(name->name);
        if (!feature)
            return 0;
        if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
            continue;
        } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
            ff->ff_features |= CO_FUTURE_DIVISION;
        } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
            ff->ff_features |= CO_FUTURE_ABSOLUTE_IMPORT;
        } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
            ff->ff_features |= CO_FUTURE_WITH_STATEMENT;
        } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
            ff->ff_features |= CO_FUTURE_PRINT_FUNCTION;
        } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
            ff->ff_features |= CO_FUTURE_UNICODE_LITERALS;
        } else if (strcmp(feature, "braces") == 0) {
            PyErr_SetString(PyExc_SyntaxError,
                            "hell yeah!!!");
            PyErr_SyntaxLocation(filename, s->lineno);
            return 0;
        } else {
            PyErr_Format(PyExc_SyntaxError,
                         UNDEFINED_FUTURE_FEATURE, feature);
            PyErr_SyntaxLocation(filename, s->lineno);
            return 0;
        }
    }
    return 1;
}
Ejemplo n.º 9
0
static int
symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel)
{
    int i;

    /* go through all the toplevel arguments first */
    for (i = 0; i < asdl_seq_LEN(args); i++) {
        expr_ty arg = (expr_ty)asdl_seq_GET(args, i);
        if (arg->kind == Name_kind) {
            assert(arg->v.Name.ctx == Param ||
                   (arg->v.Name.ctx == Store && !toplevel));
            if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM))
                return 0;
        }
        else if (arg->kind == Tuple_kind) {
            assert(arg->v.Tuple.ctx == Store);
            if (toplevel) {
                if (!symtable_implicit_arg(st, i))
                    return 0;
            }
        }
        else {
            PyErr_SetString(PyExc_SyntaxError,
                            "invalid expression in parameter list");
            PyErr_SyntaxLocation(st->st_filename,
                                 st->st_cur->ste_lineno);
            return 0;
        }
    }

    if (!toplevel) {
        if (!symtable_visit_params_nested(st, args))
            return 0;
    }

    return 1;
}
Ejemplo n.º 10
0
static int
symtable_handle_comprehension(struct symtable *st, expr_ty e,
                              identifier scope_name, asdl_seq *generators,
                              expr_ty elt, expr_ty value)
{
    int is_generator = (e->kind == GeneratorExp_kind);
    int needs_tmp = !is_generator;
    comprehension_ty outermost = ((comprehension_ty)
                                    asdl_seq_GET(generators, 0));
    /* Outermost iterator is evaluated in current scope */
    VISIT(st, expr, outermost->iter);
    /* Create comprehension scope for the rest */
    if (!scope_name ||
        !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, 0)) {
        return 0;
    }
    st->st_cur->ste_generator = is_generator;
    /* Outermost iter is received as an argument */
    if (!symtable_implicit_arg(st, 0)) {
        symtable_exit_block(st, (void *)e);
        return 0;
    }
    /* Allocate temporary name if needed */
    if (needs_tmp && !symtable_new_tmpname(st)) {
        symtable_exit_block(st, (void *)e);
        return 0;
    }
    VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e);
    VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e);
    VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension,
                            generators, 1, (void*)e);
    if (value)
        VISIT_IN_BLOCK(st, expr, value, (void*)e);
    VISIT_IN_BLOCK(st, expr, elt, (void*)e);
    return symtable_exit_block(st, (void *)e);
}
Ejemplo n.º 11
0
static int
symtable_visit_stmt(struct symtable *st, stmt_ty s)
{
    switch (s->kind) {
    case FunctionDef_kind:
        if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL))
            return 0;
        if (s->v.FunctionDef.args->defaults)
            VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
        if (s->v.FunctionDef.decorator_list)
            VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list);
        if (!symtable_enter_block(st, s->v.FunctionDef.name,
                                  FunctionBlock, (void *)s, s->lineno))
            return 0;
        VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s);
        VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s);
        if (!symtable_exit_block(st, s))
            return 0;
        break;
    case ClassDef_kind: {
        PyObject *tmp;
        if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL))
            return 0;
        VISIT_SEQ(st, expr, s->v.ClassDef.bases);
        if (s->v.ClassDef.decorator_list)
            VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);
        if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,
                                  (void *)s, s->lineno))
            return 0;
        tmp = st->st_private;
        st->st_private = s->v.ClassDef.name;
        VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s);
        st->st_private = tmp;
        if (!symtable_exit_block(st, s))
            return 0;
        break;
    }
    case Return_kind:
        if (s->v.Return.value) {
            VISIT(st, expr, s->v.Return.value);
            st->st_cur->ste_returns_value = 1;
            if (st->st_cur->ste_generator) {
                PyErr_SetString(PyExc_SyntaxError,
                    RETURN_VAL_IN_GENERATOR);
                PyErr_SyntaxLocation(st->st_filename,
                             s->lineno);
                return 0;
            }
        }
        break;
    case Delete_kind:
        VISIT_SEQ(st, expr, s->v.Delete.targets);
        break;
    case Assign_kind:
        VISIT_SEQ(st, expr, s->v.Assign.targets);
        VISIT(st, expr, s->v.Assign.value);
        break;
    case AugAssign_kind:
        VISIT(st, expr, s->v.AugAssign.target);
        VISIT(st, expr, s->v.AugAssign.value);
        break;
    case Print_kind:
        if (s->v.Print.dest)
            VISIT(st, expr, s->v.Print.dest);
        VISIT_SEQ(st, expr, s->v.Print.values);
        break;
    case For_kind:
        VISIT(st, expr, s->v.For.target);
        VISIT(st, expr, s->v.For.iter);
        VISIT_SEQ(st, stmt, s->v.For.body);
        if (s->v.For.orelse)
            VISIT_SEQ(st, stmt, s->v.For.orelse);
        break;
    case While_kind:
        VISIT(st, expr, s->v.While.test);
        VISIT_SEQ(st, stmt, s->v.While.body);
        if (s->v.While.orelse)
            VISIT_SEQ(st, stmt, s->v.While.orelse);
        break;
    case If_kind:
        /* XXX if 0: and lookup_yield() hacks */
        VISIT(st, expr, s->v.If.test);
        VISIT_SEQ(st, stmt, s->v.If.body);
        if (s->v.If.orelse)
            VISIT_SEQ(st, stmt, s->v.If.orelse);
        break;
    case Raise_kind:
        if (s->v.Raise.type) {
            VISIT(st, expr, s->v.Raise.type);
            if (s->v.Raise.inst) {
                VISIT(st, expr, s->v.Raise.inst);
                if (s->v.Raise.tback)
                    VISIT(st, expr, s->v.Raise.tback);
            }
        }
        break;
    case TryExcept_kind:
        VISIT_SEQ(st, stmt, s->v.TryExcept.body);
        VISIT_SEQ(st, stmt, s->v.TryExcept.orelse);
        VISIT_SEQ(st, excepthandler, s->v.TryExcept.handlers);
        break;
    case TryFinally_kind:
        VISIT_SEQ(st, stmt, s->v.TryFinally.body);
        VISIT_SEQ(st, stmt, s->v.TryFinally.finalbody);
        break;
    case Assert_kind:
        VISIT(st, expr, s->v.Assert.test);
        if (s->v.Assert.msg)
            VISIT(st, expr, s->v.Assert.msg);
        break;
    case Import_kind:
        VISIT_SEQ(st, alias, s->v.Import.names);
        /* XXX Don't have the lineno available inside
           visit_alias */
        if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno)
            st->st_cur->ste_opt_lineno = s->lineno;
        break;
    case ImportFrom_kind:
        VISIT_SEQ(st, alias, s->v.ImportFrom.names);
        /* XXX Don't have the lineno available inside
           visit_alias */
        if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno)
            st->st_cur->ste_opt_lineno = s->lineno;
        break;
    case Exec_kind:
        VISIT(st, expr, s->v.Exec.body);
        if (!st->st_cur->ste_opt_lineno)
            st->st_cur->ste_opt_lineno = s->lineno;
        if (s->v.Exec.globals) {
            st->st_cur->ste_unoptimized |= OPT_EXEC;
            VISIT(st, expr, s->v.Exec.globals);
            if (s->v.Exec.locals)
                VISIT(st, expr, s->v.Exec.locals);
        } else {
            st->st_cur->ste_unoptimized |= OPT_BARE_EXEC;
        }
        break;
    case Global_kind: {
        int i;
        asdl_seq *seq = s->v.Global.names;
        for (i = 0; i < asdl_seq_LEN(seq); i++) {
            identifier name = (identifier)asdl_seq_GET(seq, i);
            char *c_name = PyString_AS_STRING(name);
            long cur = symtable_lookup(st, name);
            if (cur < 0)
                return 0;
            if (cur & (DEF_LOCAL | USE)) {
                char buf[256];
                if (cur & DEF_LOCAL)
                    PyOS_snprintf(buf, sizeof(buf),
                                  GLOBAL_AFTER_ASSIGN,
                                  c_name);
                else
                    PyOS_snprintf(buf, sizeof(buf),
                                  GLOBAL_AFTER_USE,
                                  c_name);
                if (!symtable_warn(st, buf, s->lineno))
                    return 0;
            }
            if (!symtable_add_def(st, name, DEF_GLOBAL))
                return 0;
        }
        break;
    }
    case Expr_kind:
        VISIT(st, expr, s->v.Expr.value);
        break;
    case Pass_kind:
    case Break_kind:
    case Continue_kind:
        /* nothing to do here */
        break;
    case With_kind:
        VISIT(st, expr, s->v.With.context_expr);
        if (s->v.With.optional_vars) {
            VISIT(st, expr, s->v.With.optional_vars);
        }
        VISIT_SEQ(st, stmt, s->v.With.body);
        break;
    }
    return 1;
}