diff options
author | Guido van Rossum <guido@python.org> | 1991-04-04 10:40:29 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1991-04-04 10:40:29 (GMT) |
commit | 374a92261b191df619f7bcbde104eeda5edede2d (patch) | |
tree | 4142194008ceebb8c20e8b4c6324b07afd3ea511 /Python/ceval.c | |
parent | 5662746a9e0545120d5a0368b465bc93aee3a069 (diff) | |
download | cpython-374a92261b191df619f7bcbde104eeda5edede2d.zip cpython-374a92261b191df619f7bcbde104eeda5edede2d.tar.gz cpython-374a92261b191df619f7bcbde104eeda5edede2d.tar.bz2 |
Moved support functions after main function; added prototypes;
Fixed 'needspace' hack to use a flag in the stdout file object;
added local and global variable lookup cases.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 1189 |
1 files changed, 617 insertions, 572 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 5a9723f..badfced 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -39,569 +39,32 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define TRACE #endif -#ifdef TRACE -static int -prtrace(v, str) - object *v; - char *str; -{ - printf("%s ", str); - printobject(v, stdout, 0); - printf("\n"); -} -#endif - -static frameobject *current_frame; - -object * -getlocals() -{ - if (current_frame == NULL) - return NULL; - else - return current_frame->f_locals; -} - -object * -getglobals() -{ - if (current_frame == NULL) - return NULL; - else - return current_frame->f_globals; -} - -void -printtraceback(fp) - FILE *fp; -{ - object *v = tb_fetch(); - if (v != NULL) { - fprintf(fp, "Stack backtrace (innermost last):\n"); - tb_print(v, fp); - DECREF(v); - } -} - - -/* XXX Mixing "print ...," and direct file I/O on stdin/stdout - XXX has some bad consequences. The needspace flag should - XXX really be part of the file object. */ - -static int needspace; - -void -flushline() -{ - FILE *fp = sysgetfile("stdout", stdout); - if (needspace) { - fprintf(fp, "\n"); - needspace = 0; - } -} - - -/* Test a value used as condition, e.g., in a for or if statement */ - -static int -testbool(v) - object *v; -{ - if (is_intobject(v)) - return getintvalue(v) != 0; - if (is_floatobject(v)) - return getfloatvalue(v) != 0.0; - if (v->ob_type->tp_as_sequence != NULL) - return (*v->ob_type->tp_as_sequence->sq_length)(v) != 0; - if (v->ob_type->tp_as_mapping != NULL) - return (*v->ob_type->tp_as_mapping->mp_length)(v) != 0; - if (v == None) - return 0; - /* All other objects are 'true' */ - return 1; -} +/* Forward declarations */ +/* XXX Need prototypes */ -static object * -add(v, w) - object *v, *w; -{ - if (v->ob_type->tp_as_number != NULL) - v = (*v->ob_type->tp_as_number->nb_add)(v, w); - else if (v->ob_type->tp_as_sequence != NULL) - v = (*v->ob_type->tp_as_sequence->sq_concat)(v, w); - else { - err_setstr(TypeError, "+ not supported by operands"); - return NULL; - } - return v; -} +void flushline(); +static object *add(); +static object *sub(); +static object *mul(); +static object *divide(); +static object *rem(); +static object *neg(); +static object *pos(); +static object *not(); +static object *call_builtin(); +static object *call_function(); +static object *apply_subscript(); +static object *loop_subscript(); +static object *apply_slice(); +static object *cmp_outcome(); +static object *build_class(); +static int testbool(); +static int assign_subscript PROTO((object *, object *, object *)); +static int assign_slice PROTO((object *, object *, object *, object *)); +static int import_from PROTO((object *, object *, char *)); -static object * -sub(v, w) - object *v, *w; -{ - if (v->ob_type->tp_as_number != NULL) - return (*v->ob_type->tp_as_number->nb_subtract)(v, w); - err_setstr(TypeError, "bad operand type(s) for -"); - return NULL; -} -static object * -mul(v, w) - object *v, *w; -{ - typeobject *tp; - if (is_intobject(v) && w->ob_type->tp_as_sequence != NULL) { - /* int*sequence -- swap v and w */ - object *tmp = v; - v = w; - w = tmp; - } - tp = v->ob_type; - if (tp->tp_as_number != NULL) - return (*tp->tp_as_number->nb_multiply)(v, w); - if (tp->tp_as_sequence != NULL) { - if (!is_intobject(w)) { - err_setstr(TypeError, - "can't multiply sequence with non-int"); - return NULL; - } - if (tp->tp_as_sequence->sq_repeat == NULL) { - err_setstr(TypeError, "sequence does not support *"); - return NULL; - } - return (*tp->tp_as_sequence->sq_repeat) - (v, (int)getintvalue(w)); - } - err_setstr(TypeError, "bad operand type(s) for *"); - return NULL; -} - -static object * -divide(v, w) - object *v, *w; -{ - if (v->ob_type->tp_as_number != NULL) - return (*v->ob_type->tp_as_number->nb_divide)(v, w); - err_setstr(TypeError, "bad operand type(s) for /"); - return NULL; -} - -static object * -rem(v, w) - object *v, *w; -{ - if (v->ob_type->tp_as_number != NULL) - return (*v->ob_type->tp_as_number->nb_remainder)(v, w); - err_setstr(TypeError, "bad operand type(s) for %"); - return NULL; -} - -static object * -neg(v) - object *v; -{ - if (v->ob_type->tp_as_number != NULL) - return (*v->ob_type->tp_as_number->nb_negative)(v); - err_setstr(TypeError, "bad operand type(s) for unary -"); - return NULL; -} - -static object * -pos(v) - object *v; -{ - if (v->ob_type->tp_as_number != NULL) - return (*v->ob_type->tp_as_number->nb_positive)(v); - err_setstr(TypeError, "bad operand type(s) for unary +"); - return NULL; -} - -static object * -not(v) - object *v; -{ - int outcome = testbool(v); - object *w = outcome == 0 ? True : False; - INCREF(w); - return w; -} - -static object * -call_builtin(func, arg) - object *func; - object *arg; -{ - if (is_methodobject(func)) { - method meth = getmethod(func); - object *self = getself(func); - return (*meth)(self, arg); - } - if (is_classobject(func)) { - if (arg != NULL) { - err_setstr(TypeError, - "classobject() allows no arguments"); - return NULL; - } - return newclassmemberobject(func); - } - err_setstr(TypeError, "call of non-function"); - return NULL; -} - -static object * -call_function(func, arg) - object *func; - object *arg; -{ - object *newarg = NULL; - object *newlocals, *newglobals; - object *co, *v; - - if (is_classmethodobject(func)) { - object *self = classmethodgetself(func); - func = classmethodgetfunc(func); - if (arg == NULL) { - arg = self; - } - else { - newarg = newtupleobject(2); - if (newarg == NULL) - return NULL; - INCREF(self); - INCREF(arg); - settupleitem(newarg, 0, self); - settupleitem(newarg, 1, arg); - arg = newarg; - } - } - else { - if (!is_funcobject(func)) { - err_setstr(TypeError, "call of non-function"); - return NULL; - } - } - - co = getfunccode(func); - if (co == NULL) { - XDECREF(newarg); - return NULL; - } - if (!is_codeobject(co)) { - fprintf(stderr, "XXX Bad code\n"); - abort(); - } - newlocals = newdictobject(); - if (newlocals == NULL) { - XDECREF(newarg); - return NULL; - } - - newglobals = getfuncglobals(func); - INCREF(newglobals); - - v = eval_code((codeobject *)co, newglobals, newlocals, arg); - - DECREF(newlocals); - DECREF(newglobals); - - XDECREF(newarg); - - return v; -} - -static object * -apply_subscript(v, w) - object *v, *w; -{ - typeobject *tp = v->ob_type; - if (tp->tp_as_sequence == NULL && tp->tp_as_mapping == NULL) { - err_setstr(TypeError, "unsubscriptable object"); - return NULL; - } - if (tp->tp_as_sequence != NULL) { - int i; - if (!is_intobject(w)) { - err_setstr(TypeError, "sequence subscript not int"); - return NULL; - } - i = getintvalue(w); - return (*tp->tp_as_sequence->sq_item)(v, i); - } - return (*tp->tp_as_mapping->mp_subscript)(v, w); -} - -static object * -loop_subscript(v, w) - object *v, *w; -{ - sequence_methods *sq = v->ob_type->tp_as_sequence; - int i, n; - if (sq == NULL) { - err_setstr(TypeError, "loop over non-sequence"); - return NULL; - } - i = getintvalue(w); - n = (*sq->sq_length)(v); - if (i >= n) - return NULL; /* End of loop */ - return (*sq->sq_item)(v, i); -} - -static int -slice_index(v, isize, pi) - object *v; - int isize; - int *pi; -{ - if (v != NULL) { - if (!is_intobject(v)) { - err_setstr(TypeError, "slice index must be int"); - return -1; - } - *pi = getintvalue(v); - if (*pi < 0) - *pi += isize; - } - return 0; -} - -static object * -apply_slice(u, v, w) /* return u[v:w] */ - object *u, *v, *w; -{ - typeobject *tp = u->ob_type; - int ilow, ihigh, isize; - if (tp->tp_as_sequence == NULL) { - err_setstr(TypeError, "only sequences can be sliced"); - return NULL; - } - ilow = 0; - isize = ihigh = (*tp->tp_as_sequence->sq_length)(u); - if (slice_index(v, isize, &ilow) != 0) - return NULL; - if (slice_index(w, isize, &ihigh) != 0) - return NULL; - return (*tp->tp_as_sequence->sq_slice)(u, ilow, ihigh); -} - -static int -assign_subscript(w, key, v) /* w[key] = v */ - object *w; - object *key; - object *v; -{ - typeobject *tp = w->ob_type; - sequence_methods *sq; - mapping_methods *mp; - int (*func)(); - if ((sq = tp->tp_as_sequence) != NULL && - (func = sq->sq_ass_item) != NULL) { - if (!is_intobject(key)) { - err_setstr(TypeError, - "sequence subscript must be integer"); - return -1; - } - else - return (*func)(w, (int)getintvalue(key), v); - } - else if ((mp = tp->tp_as_mapping) != NULL && - (func = mp->mp_ass_subscript) != NULL) { - return (*func)(w, key, v); - } - else { - err_setstr(TypeError, - "can't assign to this subscripted object"); - return -1; - } -} - -static int -assign_slice(u, v, w, x) /* u[v:w] = x */ - object *u, *v, *w, *x; -{ - sequence_methods *sq = u->ob_type->tp_as_sequence; - int ilow, ihigh, isize; - if (sq == NULL) { - err_setstr(TypeError, "assign to slice of non-sequence"); - return -1; - } - if (sq == NULL || sq->sq_ass_slice == NULL) { - err_setstr(TypeError, "unassignable slice"); - return -1; - } - ilow = 0; - isize = ihigh = (*sq->sq_length)(u); - if (slice_index(v, isize, &ilow) != 0) - return -1; - if (slice_index(w, isize, &ihigh) != 0) - return -1; - return (*sq->sq_ass_slice)(u, ilow, ihigh, x); -} - -static int -cmp_exception(err, v) - object *err, *v; -{ - if (is_tupleobject(v)) { - int i, n; - n = gettuplesize(v); - for (i = 0; i < n; i++) { - if (err == gettupleitem(v, i)) - return 1; - } - return 0; - } - return err == v; -} - -static int -cmp_member(v, w) - object *v, *w; -{ - int i, n, cmp; - object *x; - sequence_methods *sq; - /* Special case for char in string */ - if (is_stringobject(w)) { - register char *s, *end; - register char c; - if (!is_stringobject(v) || getstringsize(v) != 1) { - err_setstr(TypeError, - "string member test needs char left operand"); - return -1; - } - c = getstringvalue(v)[0]; - s = getstringvalue(w); - end = s + getstringsize(w); - while (s < end) { - if (c == *s++) - return 1; - } - return 0; - } - sq = w->ob_type->tp_as_sequence; - if (sq == NULL) { - err_setstr(TypeError, - "'in' or 'not in' needs sequence right argument"); - return -1; - } - n = (*sq->sq_length)(w); - for (i = 0; i < n; i++) { - x = (*sq->sq_item)(w, i); - cmp = cmpobject(v, x); - XDECREF(x); - if (cmp == 0) - return 1; - } - return 0; -} - -static object * -cmp_outcome(op, v, w) - enum cmp_op op; - register object *v; - register object *w; -{ - register int cmp; - register int res = 0; - switch (op) { - case IS: - case IS_NOT: - res = (v == w); - if (op == IS_NOT) - res = !res; - break; - case IN: - case NOT_IN: - res = cmp_member(v, w); - if (res < 0) - return NULL; - if (op == NOT_IN) - res = !res; - break; - case EXC_MATCH: - res = cmp_exception(v, w); - break; - default: - cmp = cmpobject(v, w); - switch (op) { - case LT: res = cmp < 0; break; - case LE: res = cmp <= 0; break; - case EQ: res = cmp == 0; break; - case NE: res = cmp != 0; break; - case GT: res = cmp > 0; break; - case GE: res = cmp >= 0; break; - /* XXX no default? (res is initialized to 0 though) */ - } - } - v = res ? True : False; - INCREF(v); - return v; -} - -static int -import_from(locals, v, name) - object *locals; - object *v; - char *name; -{ - object *w, *x; - w = getmoduledict(v); - if (name[0] == '*') { - int i; - int n = getdictsize(w); - for (i = 0; i < n; i++) { - name = getdictkey(w, i); - if (name == NULL || name[0] == '_') - continue; - x = dictlookup(w, name); - if (x == NULL) { - /* XXX can't happen? */ - err_setstr(NameError, name); - return -1; - } - if (dictinsert(locals, name, x) != 0) - return -1; - } - return 0; - } - else { - x = dictlookup(w, name); - if (x == NULL) { - err_setstr(NameError, name); - return -1; - } - else - return dictinsert(locals, name, x); - } -} - -static object * -build_class(v, w) - object *v; /* None or tuple containing base classes */ - object *w; /* dictionary */ -{ - if (is_tupleobject(v)) { - int i; - for (i = gettuplesize(v); --i >= 0; ) { - object *x = gettupleitem(v, i); - if (!is_classobject(x)) { - err_setstr(TypeError, - "base is not a class object"); - return NULL; - } - } - } - else { - v = NULL; - } - if (!is_dictobject(w)) { - err_setstr(SystemError, "build_class with non-dictionary"); - return NULL; - } - return newclassobject(v, w); -} +static frameobject *current_frame; /* Status code for main loop (reason for stack unwind) */ @@ -614,6 +77,7 @@ enum why_code { WHY_BREAK /* 'break' statement */ }; + /* Interpreter main loop */ object * @@ -708,7 +172,7 @@ eval_code(co, globals, locals, arg) err_set(KeyboardInterrupt); why = WHY_EXCEPTION; tb_here(f, INSTR_OFFSET(), lineno); - break; + goto on_error; } } @@ -963,8 +427,9 @@ eval_code(co, globals, locals, arg) /* Print value except if procedure result */ if (v != None) { flushline(); + softspace(sysget("stdout"), 1); printobject(v, fp, 0); - fprintf(fp, "\n"); + flushline(); } DECREF(v); break; @@ -972,20 +437,17 @@ eval_code(co, globals, locals, arg) case PRINT_ITEM: v = POP(); fp = sysgetfile("stdout", stdout); - if (needspace) + if (softspace(sysget("stdout"), 1)) fprintf(fp, " "); if (is_stringobject(v)) { char *s = getstringvalue(v); int len = getstringsize(v); fwrite(s, 1, len, fp); if (len > 0 && s[len-1] == '\n') - needspace = 0; - else - needspace = 1; + softspace(sysget("stdout"), 0); } else { printobject(v, fp, 0); - needspace = 1; } DECREF(v); break; @@ -993,7 +455,7 @@ eval_code(co, globals, locals, arg) case PRINT_NEWLINE: fp = sysgetfile("stdout", stdout); fprintf(fp, "\n"); - needspace = 0; + softspace(sysget("stdout"), 0); break; case BREAK_LOOP: @@ -1173,13 +635,40 @@ eval_code(co, globals, locals, arg) x = dictlookup(f->f_locals, name); if (x == NULL) { x = dictlookup(f->f_globals, name); - if (x == NULL) + if (x == NULL) { x = getbuiltin(name); + if (x == NULL) { + err_setstr(NameError, name); + break; + } + } } - if (x == NULL) + INCREF(x); + PUSH(x); + break; + + case LOAD_GLOBAL: + name = GETNAME(oparg); + x = dictlookup(f->f_globals, name); + if (x == NULL) { + x = getbuiltin(name); + if (x == NULL) { + err_setstr(NameError, name); + break; + } + } + INCREF(x); + PUSH(x); + break; + + case LOAD_LOCAL: + name = GETNAME(oparg); + x = dictlookup(f->f_locals, name); + if (x == NULL) { err_setstr(NameError, name); - else - INCREF(x); + break; + } + INCREF(x); PUSH(x); break; @@ -1315,6 +804,7 @@ eval_code(co, globals, locals, arg) } /* switch */ + on_error: /* Quickly continue if no error occurred */ @@ -1435,3 +925,558 @@ eval_code(co, globals, locals, arg) else return NULL; } + +#ifdef TRACE +static int +prtrace(v, str) + object *v; + char *str; +{ + printf("%s ", str); + printobject(v, stdout, 0); + printf("\n"); +} +#endif + +object * +getlocals() +{ + if (current_frame == NULL) + return NULL; + else + return current_frame->f_locals; +} + +object * +getglobals() +{ + if (current_frame == NULL) + return NULL; + else + return current_frame->f_globals; +} + +void +printtraceback(fp) + FILE *fp; +{ + object *v = tb_fetch(); + if (v != NULL) { + fprintf(fp, "Stack backtrace (innermost last):\n"); + tb_print(v, fp); + DECREF(v); + } +} + + +void +flushline() +{ + if (softspace(sysget("stdout"), 0)) + fprintf(sysgetfile("stdout", stdout), "\n"); +} + + +/* Test a value used as condition, e.g., in a for or if statement */ + +static int +testbool(v) + object *v; +{ + if (is_intobject(v)) + return getintvalue(v) != 0; + if (is_floatobject(v)) + return getfloatvalue(v) != 0.0; + if (v->ob_type->tp_as_sequence != NULL) + return (*v->ob_type->tp_as_sequence->sq_length)(v) != 0; + if (v->ob_type->tp_as_mapping != NULL) + return (*v->ob_type->tp_as_mapping->mp_length)(v) != 0; + if (v == None) + return 0; + /* All other objects are 'true' */ + return 1; +} + +static object * +add(v, w) + object *v, *w; +{ + if (v->ob_type->tp_as_number != NULL) + v = (*v->ob_type->tp_as_number->nb_add)(v, w); + else if (v->ob_type->tp_as_sequence != NULL) + v = (*v->ob_type->tp_as_sequence->sq_concat)(v, w); + else { + err_setstr(TypeError, "+ not supported by operands"); + return NULL; + } + return v; +} + +static object * +sub(v, w) + object *v, *w; +{ + if (v->ob_type->tp_as_number != NULL) + return (*v->ob_type->tp_as_number->nb_subtract)(v, w); + err_setstr(TypeError, "bad operand type(s) for -"); + return NULL; +} + +static object * +mul(v, w) + object *v, *w; +{ + typeobject *tp; + if (is_intobject(v) && w->ob_type->tp_as_sequence != NULL) { + /* int*sequence -- swap v and w */ + object *tmp = v; + v = w; + w = tmp; + } + tp = v->ob_type; + if (tp->tp_as_number != NULL) + return (*tp->tp_as_number->nb_multiply)(v, w); + if (tp->tp_as_sequence != NULL) { + if (!is_intobject(w)) { + err_setstr(TypeError, + "can't multiply sequence with non-int"); + return NULL; + } + if (tp->tp_as_sequence->sq_repeat == NULL) { + err_setstr(TypeError, "sequence does not support *"); + return NULL; + } + return (*tp->tp_as_sequence->sq_repeat) + (v, (int)getintvalue(w)); + } + err_setstr(TypeError, "bad operand type(s) for *"); + return NULL; +} + +static object * +divide(v, w) + object *v, *w; +{ + if (v->ob_type->tp_as_number != NULL) + return (*v->ob_type->tp_as_number->nb_divide)(v, w); + err_setstr(TypeError, "bad operand type(s) for /"); + return NULL; +} + +static object * +rem(v, w) + object *v, *w; +{ + if (v->ob_type->tp_as_number != NULL) + return (*v->ob_type->tp_as_number->nb_remainder)(v, w); + err_setstr(TypeError, "bad operand type(s) for %"); + return NULL; +} + +static object * +neg(v) + object *v; +{ + if (v->ob_type->tp_as_number != NULL) + return (*v->ob_type->tp_as_number->nb_negative)(v); + err_setstr(TypeError, "bad operand type(s) for unary -"); + return NULL; +} + +static object * +pos(v) + object *v; +{ + if (v->ob_type->tp_as_number != NULL) + return (*v->ob_type->tp_as_number->nb_positive)(v); + err_setstr(TypeError, "bad operand type(s) for unary +"); + return NULL; +} + +static object * +not(v) + object *v; +{ + int outcome = testbool(v); + object *w = outcome == 0 ? True : False; + INCREF(w); + return w; +} + +static object * +call_builtin(func, arg) + object *func; + object *arg; +{ + if (is_methodobject(func)) { + method meth = getmethod(func); + object *self = getself(func); + return (*meth)(self, arg); + } + if (is_classobject(func)) { + if (arg != NULL) { + err_setstr(TypeError, + "classobject() allows no arguments"); + return NULL; + } + return newinstanceobject(func); + } + err_setstr(TypeError, "call of non-function"); + return NULL; +} + +static object * +call_function(func, arg) + object *func; + object *arg; +{ + object *newarg = NULL; + object *newlocals, *newglobals; + object *co, *v; + + if (is_classmethodobject(func)) { + object *self = classmethodgetself(func); + func = classmethodgetfunc(func); + if (arg == NULL) { + arg = self; + } + else { + newarg = newtupleobject(2); + if (newarg == NULL) + return NULL; + INCREF(self); + INCREF(arg); + settupleitem(newarg, 0, self); + settupleitem(newarg, 1, arg); + arg = newarg; + } + } + else { + if (!is_funcobject(func)) { + err_setstr(TypeError, "call of non-function"); + return NULL; + } + } + + co = getfunccode(func); + if (co == NULL) { + XDECREF(newarg); + return NULL; + } + if (!is_codeobject(co)) { + fprintf(stderr, "XXX Bad code\n"); + abort(); + } + newlocals = newdictobject(); + if (newlocals == NULL) { + XDECREF(newarg); + return NULL; + } + + newglobals = getfuncglobals(func); + INCREF(newglobals); + + v = eval_code((codeobject *)co, newglobals, newlocals, arg); + + DECREF(newlocals); + DECREF(newglobals); + + XDECREF(newarg); + + return v; +} + +static object * +apply_subscript(v, w) + object *v, *w; +{ + typeobject *tp = v->ob_type; + if (tp->tp_as_sequence == NULL && tp->tp_as_mapping == NULL) { + err_setstr(TypeError, "unsubscriptable object"); + return NULL; + } + if (tp->tp_as_sequence != NULL) { + int i; + if (!is_intobject(w)) { + err_setstr(TypeError, "sequence subscript not int"); + return NULL; + } + i = getintvalue(w); + return (*tp->tp_as_sequence->sq_item)(v, i); + } + return (*tp->tp_as_mapping->mp_subscript)(v, w); +} + +static object * +loop_subscript(v, w) + object *v, *w; +{ + sequence_methods *sq = v->ob_type->tp_as_sequence; + int i, n; + if (sq == NULL) { + err_setstr(TypeError, "loop over non-sequence"); + return NULL; + } + i = getintvalue(w); + n = (*sq->sq_length)(v); + if (i >= n) + return NULL; /* End of loop */ + return (*sq->sq_item)(v, i); +} + +static int +slice_index(v, isize, pi) + object *v; + int isize; + int *pi; +{ + if (v != NULL) { + if (!is_intobject(v)) { + err_setstr(TypeError, "slice index must be int"); + return -1; + } + *pi = getintvalue(v); + if (*pi < 0) + *pi += isize; + } + return 0; +} + +static object * +apply_slice(u, v, w) /* return u[v:w] */ + object *u, *v, *w; +{ + typeobject *tp = u->ob_type; + int ilow, ihigh, isize; + if (tp->tp_as_sequence == NULL) { + err_setstr(TypeError, "only sequences can be sliced"); + return NULL; + } + ilow = 0; + isize = ihigh = (*tp->tp_as_sequence->sq_length)(u); + if (slice_index(v, isize, &ilow) != 0) + return NULL; + if (slice_index(w, isize, &ihigh) != 0) + return NULL; + return (*tp->tp_as_sequence->sq_slice)(u, ilow, ihigh); +} + +static int +assign_subscript(w, key, v) /* w[key] = v */ + object *w; + object *key; + object *v; +{ + typeobject *tp = w->ob_type; + sequence_methods *sq; + mapping_methods *mp; + int (*func)(); + if ((sq = tp->tp_as_sequence) != NULL && + (func = sq->sq_ass_item) != NULL) { + if (!is_intobject(key)) { + err_setstr(TypeError, + "sequence subscript must be integer"); + return -1; + } + else + return (*func)(w, (int)getintvalue(key), v); + } + else if ((mp = tp->tp_as_mapping) != NULL && + (func = mp->mp_ass_subscript) != NULL) { + return (*func)(w, key, v); + } + else { + err_setstr(TypeError, + "can't assign to this subscripted object"); + return -1; + } +} + +static int +assign_slice(u, v, w, x) /* u[v:w] = x */ + object *u, *v, *w, *x; +{ + sequence_methods *sq = u->ob_type->tp_as_sequence; + int ilow, ihigh, isize; + if (sq == NULL) { + err_setstr(TypeError, "assign to slice of non-sequence"); + return -1; + } + if (sq == NULL || sq->sq_ass_slice == NULL) { + err_setstr(TypeError, "unassignable slice"); + return -1; + } + ilow = 0; + isize = ihigh = (*sq->sq_length)(u); + if (slice_index(v, isize, &ilow) != 0) + return -1; + if (slice_index(w, isize, &ihigh) != 0) + return -1; + return (*sq->sq_ass_slice)(u, ilow, ihigh, x); +} + +static int +cmp_exception(err, v) + object *err, *v; +{ + if (is_tupleobject(v)) { + int i, n; + n = gettuplesize(v); + for (i = 0; i < n; i++) { + if (err == gettupleitem(v, i)) + return 1; + } + return 0; + } + return err == v; +} + +static int +cmp_member(v, w) + object *v, *w; +{ + int i, n, cmp; + object *x; + sequence_methods *sq; + /* Special case for char in string */ + if (is_stringobject(w)) { + register char *s, *end; + register char c; + if (!is_stringobject(v) || getstringsize(v) != 1) { + err_setstr(TypeError, + "string member test needs char left operand"); + return -1; + } + c = getstringvalue(v)[0]; + s = getstringvalue(w); + end = s + getstringsize(w); + while (s < end) { + if (c == *s++) + return 1; + } + return 0; + } + sq = w->ob_type->tp_as_sequence; + if (sq == NULL) { + err_setstr(TypeError, + "'in' or 'not in' needs sequence right argument"); + return -1; + } + n = (*sq->sq_length)(w); + for (i = 0; i < n; i++) { + x = (*sq->sq_item)(w, i); + cmp = cmpobject(v, x); + XDECREF(x); + if (cmp == 0) + return 1; + } + return 0; +} + +static object * +cmp_outcome(op, v, w) + enum cmp_op op; + register object *v; + register object *w; +{ + register int cmp; + register int res = 0; + switch (op) { + case IS: + case IS_NOT: + res = (v == w); + if (op == IS_NOT) + res = !res; + break; + case IN: + case NOT_IN: + res = cmp_member(v, w); + if (res < 0) + return NULL; + if (op == NOT_IN) + res = !res; + break; + case EXC_MATCH: + res = cmp_exception(v, w); + break; + default: + cmp = cmpobject(v, w); + switch (op) { + case LT: res = cmp < 0; break; + case LE: res = cmp <= 0; break; + case EQ: res = cmp == 0; break; + case NE: res = cmp != 0; break; + case GT: res = cmp > 0; break; + case GE: res = cmp >= 0; break; + /* XXX no default? (res is initialized to 0 though) */ + } + } + v = res ? True : False; + INCREF(v); + return v; +} + +/* XXX This function should use dict2 variants (change interface!) */ + +static int +import_from(locals, v, name) + object *locals; + object *v; + char *name; +{ + object *w, *x; + w = getmoduledict(v); + if (name[0] == '*') { + int i; + int n = getdictsize(w); + for (i = 0; i < n; i++) { + name = getdictkey(w, i); + if (name == NULL || name[0] == '_') + continue; + x = dictlookup(w, name); + if (x == NULL) { + /* XXX can't happen? */ + err_setstr(NameError, name); + return -1; + } + if (dictinsert(locals, name, x) != 0) + return -1; + } + return 0; + } + else { + x = dictlookup(w, name); + if (x == NULL) { + err_setstr(NameError, name); + return -1; + } + else + return dictinsert(locals, name, x); + } +} + +static object * +build_class(v, w) + object *v; /* None or tuple containing base classes */ + object *w; /* dictionary */ +{ + if (is_tupleobject(v)) { + int i; + for (i = gettuplesize(v); --i >= 0; ) { + object *x = gettupleitem(v, i); + if (!is_classobject(x)) { + err_setstr(TypeError, + "base is not a class object"); + return NULL; + } + } + } + else { + v = NULL; + } + if (!is_dictobject(w)) { + err_setstr(SystemError, "build_class with non-dictionary"); + return NULL; + } + return newclassobject(v, w); +} |