📄 compile.c
字号:
static void com_factor(struct compiling *, node *);
static void com_addbyte(struct compiling *, int);
static void com_addint(struct compiling *, int);
static void com_addoparg(struct compiling *, int, int);
static void com_addfwref(struct compiling *, int, int *);
static void com_backpatch(struct compiling *, int);
static int com_add(struct compiling *, PyObject *, PyObject *, PyObject *);
static int com_addconst(struct compiling *, PyObject *);
static int com_addname(struct compiling *, PyObject *);
static void com_addopname(struct compiling *, int, node *);
static void com_list(struct compiling *, node *, int);
static void com_list_iter(struct compiling *, node *, node *, char *);
static int com_argdefs(struct compiling *, node *);
static void com_assign(struct compiling *, node *, int, node *);
static void com_assign_name(struct compiling *, node *, int);
static PyCodeObject *icompile(node *, struct compiling *);
static PyCodeObject *jcompile(node *, char *, struct compiling *,
PyCompilerFlags *);
static PyObject *parsestrplus(struct compiling*, node *);
static PyObject *parsestr(struct compiling *, char *);
static node *get_rawdocstring(node *);
static int get_ref_type(struct compiling *, char *);
/* symtable operations */
static int symtable_build(struct compiling *, node *);
static int symtable_load_symbols(struct compiling *);
static struct symtable *symtable_init(void);
static void symtable_enter_scope(struct symtable *, char *, int, int);
static int symtable_exit_scope(struct symtable *);
static int symtable_add_def(struct symtable *, char *, int);
static int symtable_add_def_o(struct symtable *, PyObject *, PyObject *, int);
static void symtable_node(struct symtable *, node *);
static void symtable_funcdef(struct symtable *, node *);
static void symtable_default_args(struct symtable *, node *);
static void symtable_params(struct symtable *, node *);
static void symtable_params_fplist(struct symtable *, node *n);
static void symtable_global(struct symtable *, node *);
static void symtable_import(struct symtable *, node *);
static void symtable_assign(struct symtable *, node *, int);
static void symtable_list_comprehension(struct symtable *, node *);
static int symtable_update_free_vars(struct symtable *);
static int symtable_undo_free(struct symtable *, PyObject *, PyObject *);
static int symtable_check_global(struct symtable *, PyObject *, PyObject *);
/* helper */
static void
do_pad(int pad)
{
int i;
for (i = 0; i < pad; ++i)
fprintf(stderr, " ");
}
static void
dump(node *n, int pad, int depth)
{
int i;
if (depth == 0)
return;
do_pad(pad);
fprintf(stderr, "%d: %s\n", TYPE(n), STR(n));
if (depth > 0)
depth--;
for (i = 0; i < NCH(n); ++i)
dump(CHILD(n, i), pad + 1, depth);
}
#define DUMP(N) dump(N, 0, -1)
static int
com_init(struct compiling *c, char *filename)
{
memset((void *)c, '\0', sizeof(struct compiling));
if ((c->c_code = PyString_FromStringAndSize((char *)NULL,
1000)) == NULL)
goto fail;
if ((c->c_consts = PyList_New(0)) == NULL)
goto fail;
if ((c->c_const_dict = PyDict_New()) == NULL)
goto fail;
if ((c->c_names = PyList_New(0)) == NULL)
goto fail;
if ((c->c_name_dict = PyDict_New()) == NULL)
goto fail;
if ((c->c_locals = PyDict_New()) == NULL)
goto fail;
if ((c->c_lnotab = PyString_FromStringAndSize((char *)NULL,
1000)) == NULL)
goto fail;
c->c_globals = NULL;
c->c_varnames = NULL;
c->c_freevars = NULL;
c->c_cellvars = NULL;
c->c_nlocals = 0;
c->c_argcount = 0;
c->c_flags = 0;
c->c_nexti = 0;
c->c_errors = 0;
c->c_infunction = 0;
c->c_interactive = 0;
c->c_loops = 0;
c->c_begin = 0;
c->c_nblocks = 0;
c->c_filename = filename;
c->c_name = "?";
c->c_lineno = 0;
c->c_stacklevel = 0;
c->c_maxstacklevel = 0;
c->c_firstlineno = 0;
c->c_last_addr = 0;
c->c_last_line = 0;
c->c_lnotab_next = 0;
c->c_tmpname = 0;
c->c_nested = 0;
c->c_closure = 0;
c->c_symtable = NULL;
return 1;
fail:
com_free(c);
return 0;
}
static void
com_free(struct compiling *c)
{
Py_XDECREF(c->c_code);
Py_XDECREF(c->c_consts);
Py_XDECREF(c->c_const_dict);
Py_XDECREF(c->c_names);
Py_XDECREF(c->c_name_dict);
Py_XDECREF(c->c_globals);
Py_XDECREF(c->c_locals);
Py_XDECREF(c->c_varnames);
Py_XDECREF(c->c_freevars);
Py_XDECREF(c->c_cellvars);
Py_XDECREF(c->c_lnotab);
if (c->c_future)
PyMem_Free((void *)c->c_future);
}
static void
com_push(struct compiling *c, int n)
{
c->c_stacklevel += n;
if (c->c_stacklevel > c->c_maxstacklevel) {
c->c_maxstacklevel = c->c_stacklevel;
/*
fprintf(stderr, "%s:%s:%d max stack nexti=%d level=%d n=%d\n",
c->c_filename, c->c_name, c->c_lineno,
c->c_nexti, c->c_stacklevel, n);
*/
}
}
static void
com_pop(struct compiling *c, int n)
{
if (c->c_stacklevel < n)
c->c_stacklevel = 0;
else
c->c_stacklevel -= n;
}
static void
com_done(struct compiling *c)
{
if (c->c_code != NULL)
_PyString_Resize(&c->c_code, c->c_nexti);
if (c->c_lnotab != NULL)
_PyString_Resize(&c->c_lnotab, c->c_lnotab_next);
}
static int
com_check_size(PyObject **s, int offset)
{
int len = PyString_GET_SIZE(*s);
if (offset >= len)
return _PyString_Resize(s, len * 2);
return 0;
}
static void
com_addbyte(struct compiling *c, int byte)
{
/*fprintf(stderr, "%3d: %3d\n", c->c_nexti, byte);*/
assert(byte >= 0 && byte <= 255);
assert(c->c_code);
if (com_check_size(&c->c_code, c->c_nexti)) {
c->c_errors++;
return;
}
PyString_AS_STRING(c->c_code)[c->c_nexti++] = byte;
}
static void
com_addint(struct compiling *c, int x)
{
com_addbyte(c, x & 0xff);
com_addbyte(c, x >> 8); /* XXX x should be positive */
}
static void
com_add_lnotab(struct compiling *c, int addr, int line)
{
char *p;
if (c->c_lnotab == NULL)
return;
if (com_check_size(&c->c_lnotab, c->c_lnotab_next + 2)) {
c->c_errors++;
return;
}
p = PyString_AS_STRING(c->c_lnotab) + c->c_lnotab_next;
*p++ = addr;
*p++ = line;
c->c_lnotab_next += 2;
}
static void
com_set_lineno(struct compiling *c, int lineno)
{
c->c_lineno = lineno;
if (c->c_firstlineno == 0) {
c->c_firstlineno = c->c_last_line = lineno;
}
else {
int incr_addr = c->c_nexti - c->c_last_addr;
int incr_line = lineno - c->c_last_line;
while (incr_addr > 255) {
com_add_lnotab(c, 255, 0);
incr_addr -= 255;
}
while (incr_line > 255) {
com_add_lnotab(c, incr_addr, 255);
incr_line -=255;
incr_addr = 0;
}
if (incr_addr > 0 || incr_line > 0)
com_add_lnotab(c, incr_addr, incr_line);
c->c_last_addr = c->c_nexti;
c->c_last_line = lineno;
}
}
static void
com_addoparg(struct compiling *c, int op, int arg)
{
int extended_arg = arg >> 16;
if (op == SET_LINENO) {
com_set_lineno(c, arg);
if (Py_OptimizeFlag)
return;
}
if (extended_arg){
com_addbyte(c, EXTENDED_ARG);
com_addint(c, extended_arg);
arg &= 0xffff;
}
com_addbyte(c, op);
com_addint(c, arg);
}
static void
com_addfwref(struct compiling *c, int op, int *p_anchor)
{
/* Compile a forward reference for backpatching */
int here;
int anchor;
com_addbyte(c, op);
here = c->c_nexti;
anchor = *p_anchor;
*p_anchor = here;
com_addint(c, anchor == 0 ? 0 : here - anchor);
}
static void
com_backpatch(struct compiling *c, int anchor)
{
unsigned char *code = (unsigned char *) PyString_AS_STRING(c->c_code);
int target = c->c_nexti;
int dist;
int prev;
for (;;) {
/* Make the JUMP instruction at anchor point to target */
prev = code[anchor] + (code[anchor+1] << 8);
dist = target - (anchor+2);
code[anchor] = dist & 0xff;
dist >>= 8;
code[anchor+1] = dist;
dist >>= 8;
if (dist) {
com_error(c, PyExc_SystemError,
"com_backpatch: offset too large");
break;
}
if (!prev)
break;
anchor -= prev;
}
}
/* Handle literals and names uniformly */
static int
com_add(struct compiling *c, PyObject *list, PyObject *dict, PyObject *v)
{
PyObject *w, *t, *np=NULL;
long n;
t = Py_BuildValue("(OO)", v, v->ob_type);
if (t == NULL)
goto fail;
w = PyDict_GetItem(dict, t);
if (w != NULL) {
n = PyInt_AsLong(w);
} else {
n = PyList_Size(list);
np = PyInt_FromLong(n);
if (np == NULL)
goto fail;
if (PyList_Append(list, v) != 0)
goto fail;
if (PyDict_SetItem(dict, t, np) != 0)
goto fail;
Py_DECREF(np);
}
Py_DECREF(t);
return n;
fail:
Py_XDECREF(np);
Py_XDECREF(t);
c->c_errors++;
return 0;
}
static int
com_addconst(struct compiling *c, PyObject *v)
{
return com_add(c, c->c_consts, c->c_const_dict, v);
}
static int
com_addname(struct compiling *c, PyObject *v)
{
return com_add(c, c->c_names, c->c_name_dict, v);
}
static int
mangle(char *p, char *name, char *buffer, size_t maxlen)
{
/* Name mangling: __private becomes _classname__private.
This is independent from how the name is used. */
size_t nlen, plen;
if (p == NULL || name == NULL || name[0] != '_' || name[1] != '_')
return 0;
nlen = strlen(name);
if (nlen+2 >= maxlen)
return 0; /* Don't mangle __extremely_long_names */
if (name[nlen-1] == '_' && name[nlen-2] == '_')
return 0; /* Don't mangle __whatever__ */
/* Strip leading underscores from class name */
while (*p == '_')
p++;
if (*p == '\0')
return 0; /* Don't mangle if class is just underscores */
plen = strlen(p);
if (plen + nlen >= maxlen)
plen = maxlen-nlen-2; /* Truncate class name if too long */
/* buffer = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */
buffer[0] = '_';
strncpy(buffer+1, p, plen);
strcpy(buffer+1+plen, name);
return 1;
}
static void
com_addop_name(struct compiling *c, int op, char *name)
{
PyObject *v;
int i;
char buffer[MANGLE_LEN];
if (mangle(c->c_private, name, buffer, sizeof(buffer)))
name = buffer;
if (name == NULL || (v = PyString_InternFromString(name)) == NULL) {
c->c_errors++;
i = 255;
}
else {
i = com_addname(c, v);
Py_DECREF(v);
}
com_addoparg(c, op, i);
}
#define NAME_LOCAL 0
#define NAME_GLOBAL 1
#define NAME_DEFAULT 2
#define NAME_CLOSURE 3
static int
com_lookup_arg(PyObject *dict, PyObject *name)
{
PyObject *v = PyDict_GetItem(dict, name);
if (v == NULL)
return -1;
else
return PyInt_AS_LONG(v);
}
static void
com_addop_varname(struct compiling *c, int kind, char *name)
{
PyObject *v;
int i, reftype;
int scope = NAME_DEFAULT;
int op = STOP_CODE;
char buffer[MANGLE_LEN];
if (mangle(c->c_private, name, buffer, sizeof(buffer)))
name = buffer;
if (name == NULL || (v = PyString_InternFromString(name)) == NULL) {
c->c_errors++;
i = 255;
goto done;
}
reftype = get_ref_type(c, name);
switch (reftype) {
case LOCAL:
if (c->c_symtable->st_cur->ste_type == TYPE_FUNCTION)
scope = NAME_LOCAL;
break;
case GLOBAL_EXPLICIT:
scope = NAME_GLOBAL;
break;
case GLOBAL_IMPLICIT:
if (c->c_flags & CO_OPTIMIZED)
scope = NAME_GLOBAL;
break;
case FREE:
case CELL:
scope = NAME_CLOSURE;
break;
}
i = com_addname(c, v);
if (scope == NAME_LOCAL)
i = com_lookup_arg(c->c_locals, v);
else if (reftype == FREE)
i = com_lookup_arg(c->c_freevars, v);
else if (reftype == CELL)
i = com_lookup_arg(c->c_cellvars, v);
if (i == -1) {
c->c_errors++; /* XXX no exception set */
i = 255;
goto done;
}
Py_DECREF(v);
switch (kind) {
case VAR_LOAD:
switch (scope) {
case NAME_LOCAL:
op = LOAD_FAST;
break;
case NAME_GLOBAL:
op = LOAD_GLOBAL;
break;
case NAME_DEFAULT:
op = LOAD_NAME;
break;
case NAME_CLOSURE:
op = LOAD_DEREF;
break;
}
break;
case VAR_STORE:
switch (scope) {
case NAME_LOCAL:
op = STORE_FAST;
break;
case NAME_GLOBAL:
op = STORE_GLOBAL;
break;
case NAME_DEFAULT:
op = STORE_NAME;
break;
case NAME_CLOSURE:
op = STORE_DEREF;
break;
}
break;
case VAR_DELETE:
switch (scope) {
case NAME_LOCAL:
op = DELETE_FAST;
break;
case NAME_GLOBAL:
op = DELETE_GLOBAL;
break;
case NAME_DEFAULT:
op = DELETE_NAME;
break;
case NAME_CLOSURE: {
char buf[500];
PyOS_snprintf(buf, sizeof(buf),
DEL_CLOSURE_ERROR, name);
com_error(c, PyExc_SyntaxError, buf);
i = 255;
break;
}
}
break;
}
done:
com_addoparg(c, op, i);
}
static void
com_addopname(struct compiling *c, int op, node *n)
{
char *name;
char buffer[1000];
/* XXX it is possible to write this code without the 1000
chars on the total length of dotted names, I just can't be
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -