Several changes in one:
(1) dictionaries/mappings now have attributes values() and items() as well as keys(); at the C level, use the new function mappinggetnext() to iterate over a dictionary. (2) "class C(): ..." is now illegal; you must write "class C: ...". (3) Class objects now know their own name (finally!); and minor improvements to the way how classes, functions and methods are represented as strings. (4) Added an "access" statement and semantics. (This is still experimental -- as long as you don't use the keyword 'access' nothing should be changed.)
This commit is contained in:
parent
687dd13bfe
commit
25831652fd
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
# Change log:
|
# Change log:
|
||||||
|
|
||||||
|
# 19-May-93:
|
||||||
|
# Add access statement
|
||||||
|
|
||||||
|
# 18-May-93:
|
||||||
|
# Abolish old class header syntax
|
||||||
|
|
||||||
# 06-Apr-92:
|
# 06-Apr-92:
|
||||||
# Use only '*' for varargs list
|
# Use only '*' for varargs list
|
||||||
|
|
||||||
|
@ -81,7 +87,7 @@ fplist: fpdef (',' fpdef)* [',']
|
||||||
|
|
||||||
stmt: simple_stmt | compound_stmt
|
stmt: simple_stmt | compound_stmt
|
||||||
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
|
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
|
||||||
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt
|
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt
|
||||||
expr_stmt: (exprlist '=')* exprlist
|
expr_stmt: (exprlist '=')* exprlist
|
||||||
# For assignments, additional restrictions enforced by the interpreter
|
# For assignments, additional restrictions enforced by the interpreter
|
||||||
print_stmt: 'print' (test ',')* [test]
|
print_stmt: 'print' (test ',')* [test]
|
||||||
|
@ -94,6 +100,11 @@ return_stmt: 'return' [testlist]
|
||||||
raise_stmt: 'raise' test [',' test]
|
raise_stmt: 'raise' test [',' test]
|
||||||
import_stmt: 'import' NAME (',' NAME)* | 'from' NAME 'import' ('*' | NAME (',' NAME)*)
|
import_stmt: 'import' NAME (',' NAME)* | 'from' NAME 'import' ('*' | NAME (',' NAME)*)
|
||||||
global_stmt: 'global' NAME (',' NAME)*
|
global_stmt: 'global' NAME (',' NAME)*
|
||||||
|
access_stmt: 'access' NAME (',' NAME)* ':' accesstype (',' accesstype)*
|
||||||
|
accesstype: NAME+
|
||||||
|
# accesstype should be ('public' | 'protected' | 'private') ['read'] ['write']
|
||||||
|
# but can't be because that would create undesirable reserved words!
|
||||||
|
|
||||||
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
|
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
|
||||||
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
|
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
|
||||||
while_stmt: 'while' test ':' suite ['else' ':' suite]
|
while_stmt: 'while' test ':' suite ['else' ':' suite]
|
||||||
|
@ -122,9 +133,4 @@ exprlist: expr (',' expr)* [',']
|
||||||
testlist: test (',' test)* [',']
|
testlist: test (',' test)* [',']
|
||||||
dictmaker: test ':' test (',' test ':' test)* [',']
|
dictmaker: test ':' test (',' test ':' test)* [',']
|
||||||
|
|
||||||
# New class syntax should be:
|
classdef: class NAME ['(' testlist ')'] ':' suite
|
||||||
# classdef: class NAME ['(' testlist ')'] ':' suite
|
|
||||||
# but merged with old syntax for compatibility it becomes:
|
|
||||||
classdef: 'class' NAME ['(' testlist ')' |'(' ')' ['=' baselist]] ':' suite
|
|
||||||
baselist: atom arguments (',' atom arguments)*
|
|
||||||
arguments: '(' ')'
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "objimpl.h"
|
#include "objimpl.h"
|
||||||
|
|
||||||
|
#include "accessobject.h"
|
||||||
#include "intobject.h"
|
#include "intobject.h"
|
||||||
#include "longobject.h"
|
#include "longobject.h"
|
||||||
#include "floatobject.h"
|
#include "floatobject.h"
|
||||||
|
|
|
@ -37,7 +37,7 @@ extern typeobject Classtype, Instancetype, Instancemethodtype;
|
||||||
#define is_instancemethodobject(op) ((op)->ob_type == &Instancemethodtype)
|
#define is_instancemethodobject(op) ((op)->ob_type == &Instancemethodtype)
|
||||||
|
|
||||||
extern object *newclassobject PROTO((object *, object *, object *));
|
extern object *newclassobject PROTO((object *, object *, object *));
|
||||||
extern object *newinstanceobject PROTO((object *));
|
extern object *newinstanceobject PROTO((object *, object *));
|
||||||
extern object *newinstancemethodobject PROTO((object *, object *));
|
extern object *newinstancemethodobject PROTO((object *, object *));
|
||||||
|
|
||||||
extern object *instancemethodgetfunc PROTO((object *));
|
extern object *instancemethodgetfunc PROTO((object *));
|
||||||
|
|
|
@ -33,12 +33,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
extern object *dictlookup PROTO((object *dp, char *key));
|
extern object *dictlookup PROTO((object *dp, char *key));
|
||||||
extern int dictinsert PROTO((object *dp, char *key, object *item));
|
extern int dictinsert PROTO((object *dp, char *key, object *item));
|
||||||
extern int dictremove PROTO((object *dp, char *key));
|
extern int dictremove PROTO((object *dp, char *key));
|
||||||
extern char *getdictkey PROTO((object *dp, int i));
|
|
||||||
|
|
||||||
#define getdictsize getmappingsize
|
|
||||||
#define getdictkeys getmappingkeys
|
#define getdictkeys getmappingkeys
|
||||||
|
|
||||||
#define getdict2key getmappingkey
|
|
||||||
#define dict2lookup mappinglookup
|
#define dict2lookup mappinglookup
|
||||||
#define dict2insert mappinginsert
|
#define dict2insert mappinginsert
|
||||||
#define dict2remove mappingremove
|
#define dict2remove mappingremove
|
||||||
|
|
|
@ -33,7 +33,9 @@ void err_clear PROTO((void));
|
||||||
|
|
||||||
/* Predefined exceptions */
|
/* Predefined exceptions */
|
||||||
|
|
||||||
|
extern object *AccessError;
|
||||||
extern object *AttributeError;
|
extern object *AttributeError;
|
||||||
|
extern object *ConflictError;
|
||||||
extern object *EOFError;
|
extern object *EOFError;
|
||||||
extern object *IOError;
|
extern object *IOError;
|
||||||
extern object *ImportError;
|
extern object *ImportError;
|
||||||
|
@ -59,3 +61,5 @@ extern object *err_errno PROTO((object *));
|
||||||
extern void err_input PROTO((int));
|
extern void err_input PROTO((int));
|
||||||
|
|
||||||
extern void err_badcall PROTO((void));
|
extern void err_badcall PROTO((void));
|
||||||
|
|
||||||
|
extern object *err_getexc PROTO((void));
|
||||||
|
|
|
@ -24,6 +24,13 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
/* Function object interface */
|
/* Function object interface */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
OB_HEAD
|
||||||
|
object *func_code;
|
||||||
|
object *func_globals;
|
||||||
|
object *func_name;
|
||||||
|
} funcobject;
|
||||||
|
|
||||||
extern typeobject Functype;
|
extern typeobject Functype;
|
||||||
|
|
||||||
#define is_funcobject(op) ((op)->ob_type == &Functype)
|
#define is_funcobject(op) ((op)->ob_type == &Functype)
|
||||||
|
|
|
@ -21,31 +21,31 @@
|
||||||
#define raise_stmt 276
|
#define raise_stmt 276
|
||||||
#define import_stmt 277
|
#define import_stmt 277
|
||||||
#define global_stmt 278
|
#define global_stmt 278
|
||||||
#define compound_stmt 279
|
#define access_stmt 279
|
||||||
#define if_stmt 280
|
#define accesstype 280
|
||||||
#define while_stmt 281
|
#define compound_stmt 281
|
||||||
#define for_stmt 282
|
#define if_stmt 282
|
||||||
#define try_stmt 283
|
#define while_stmt 283
|
||||||
#define except_clause 284
|
#define for_stmt 284
|
||||||
#define suite 285
|
#define try_stmt 285
|
||||||
#define test 286
|
#define except_clause 286
|
||||||
#define and_test 287
|
#define suite 287
|
||||||
#define not_test 288
|
#define test 288
|
||||||
#define comparison 289
|
#define and_test 289
|
||||||
#define comp_op 290
|
#define not_test 290
|
||||||
#define expr 291
|
#define comparison 291
|
||||||
#define xor_expr 292
|
#define comp_op 292
|
||||||
#define and_expr 293
|
#define expr 293
|
||||||
#define shift_expr 294
|
#define xor_expr 294
|
||||||
#define arith_expr 295
|
#define and_expr 295
|
||||||
#define term 296
|
#define shift_expr 296
|
||||||
#define factor 297
|
#define arith_expr 297
|
||||||
#define atom 298
|
#define term 298
|
||||||
#define trailer 299
|
#define factor 299
|
||||||
#define subscript 300
|
#define atom 300
|
||||||
#define exprlist 301
|
#define trailer 301
|
||||||
#define testlist 302
|
#define subscript 302
|
||||||
#define dictmaker 303
|
#define exprlist 303
|
||||||
#define classdef 304
|
#define testlist 304
|
||||||
#define baselist 305
|
#define dictmaker 305
|
||||||
#define arguments 306
|
#define classdef 306
|
||||||
|
|
|
@ -22,22 +22,19 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
|
||||||
/*
|
/* Mapping object type -- mapping from hashable object to object */
|
||||||
Mapping object type -- mapping from object to object.
|
|
||||||
These functions set errno for errors. Functions mappingremove() and
|
|
||||||
mappinginsert() return nonzero for errors, getmappingsize() returns -1,
|
|
||||||
the others NULL. A successful call to mappinginsert() calls INCREF()
|
|
||||||
for the inserted item.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern typeobject Mappingtype;
|
extern typeobject Mappingtype;
|
||||||
|
|
||||||
#define is_mappingobject(op) ((op)->ob_type == &Mappingtype)
|
#define is_mappingobject(op) ((op)->ob_type == &Mappingtype)
|
||||||
|
|
||||||
extern object *newmappingobject PROTO((void));
|
extern object *newmappingobject PROTO((void));
|
||||||
extern object *mappinglookup PROTO((object *dp, object *key));
|
extern object *mappinglookup PROTO((object *mp, object *key));
|
||||||
extern int mappinginsert PROTO((object *dp, object *key, object *item));
|
extern int mappinginsert PROTO((object *mp, object *key, object *item));
|
||||||
extern int mappingremove PROTO((object *dp, object *key));
|
extern int mappingremove PROTO((object *mp, object *key));
|
||||||
extern int getmappingsize PROTO((object *dp));
|
extern void mappingclear PROTO((object *mp));
|
||||||
extern object *getmappingkey PROTO((object *dp, int i));
|
extern int mappinggetnext
|
||||||
extern object *getmappingkeys PROTO((object *dp));
|
PROTO((object *mp, int *pos, object **key, object **value));
|
||||||
|
extern object *getmappingkeys PROTO((object *mp));
|
||||||
|
extern object *getmappingvalues PROTO((object *mp));
|
||||||
|
extern object *getmappingitems PROTO((object *mp));
|
||||||
|
|
|
@ -100,6 +100,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#define COMPARE_OP 106 /* Comparison operator */
|
#define COMPARE_OP 106 /* Comparison operator */
|
||||||
#define IMPORT_NAME 107 /* Index in name list */
|
#define IMPORT_NAME 107 /* Index in name list */
|
||||||
#define IMPORT_FROM 108 /* Index in name list */
|
#define IMPORT_FROM 108 /* Index in name list */
|
||||||
|
#define ACCESS_MODE 109 /* Name (mode is int on top of stack) */
|
||||||
|
|
||||||
#define JUMP_FORWARD 110 /* Number of bytes to skip */
|
#define JUMP_FORWARD 110 /* Number of bytes to skip */
|
||||||
#define JUMP_IF_FALSE 111 /* "" */
|
#define JUMP_IF_FALSE 111 /* "" */
|
||||||
|
|
|
@ -33,7 +33,9 @@ void err_clear PROTO((void));
|
||||||
|
|
||||||
/* Predefined exceptions */
|
/* Predefined exceptions */
|
||||||
|
|
||||||
|
extern object *AccessError;
|
||||||
extern object *AttributeError;
|
extern object *AttributeError;
|
||||||
|
extern object *ConflictError;
|
||||||
extern object *EOFError;
|
extern object *EOFError;
|
||||||
extern object *IOError;
|
extern object *IOError;
|
||||||
extern object *ImportError;
|
extern object *ImportError;
|
||||||
|
@ -59,3 +61,5 @@ extern object *err_errno PROTO((object *));
|
||||||
extern void err_input PROTO((int));
|
extern void err_input PROTO((int));
|
||||||
|
|
||||||
extern void err_badcall PROTO((void));
|
extern void err_badcall PROTO((void));
|
||||||
|
|
||||||
|
extern object *err_getexc PROTO((void));
|
||||||
|
|
|
@ -29,9 +29,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
#include "ceval.h"
|
#include "ceval.h"
|
||||||
|
|
||||||
extern typeobject MappingInstancetype;
|
|
||||||
extern typeobject SequenceInstancetype;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
OB_HEAD
|
OB_HEAD
|
||||||
object *cl_bases; /* A tuple */
|
object *cl_bases; /* A tuple */
|
||||||
|
@ -102,7 +99,10 @@ class_getattr(op, name)
|
||||||
}
|
}
|
||||||
v = dictlookup(op->cl_methods, name);
|
v = dictlookup(op->cl_methods, name);
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
INCREF(v);
|
if (is_accessobject(v))
|
||||||
|
v = getaccessvalue(v, (object *)NULL);
|
||||||
|
else
|
||||||
|
INCREF(v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -126,6 +126,7 @@ class_setattr(op, name, v)
|
||||||
char *name;
|
char *name;
|
||||||
object *v;
|
object *v;
|
||||||
{
|
{
|
||||||
|
object *ac;
|
||||||
if (name[0] == '_' && name[1] == '_') {
|
if (name[0] == '_' && name[1] == '_') {
|
||||||
int n = strlen(name);
|
int n = strlen(name);
|
||||||
if (name[n-1] == '_' && name[n-2] == '_') {
|
if (name[n-1] == '_' && name[n-2] == '_') {
|
||||||
|
@ -133,6 +134,9 @@ class_setattr(op, name, v)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ac = dictlookup(op->cl_methods, name);
|
||||||
|
if (ac != NULL && is_accessobject(ac))
|
||||||
|
return setaccessvalue(ac, (object *)NULL, v);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
int rv = dictremove(op->cl_methods, name);
|
int rv = dictremove(op->cl_methods, name);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
|
@ -144,6 +148,20 @@ class_setattr(op, name, v)
|
||||||
return dictinsert(op->cl_methods, name, v);
|
return dictinsert(op->cl_methods, name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static object *
|
||||||
|
class_repr(op)
|
||||||
|
classobject *op;
|
||||||
|
{
|
||||||
|
char buf[140];
|
||||||
|
char *name;
|
||||||
|
if (op->cl_name == NULL || !is_stringobject(op->cl_name))
|
||||||
|
name = "?";
|
||||||
|
else
|
||||||
|
name = getstringvalue(op->cl_name);
|
||||||
|
sprintf(buf, "<class %.100s at %lx>", name, (long)op);
|
||||||
|
return newstringobject(buf);
|
||||||
|
}
|
||||||
|
|
||||||
typeobject Classtype = {
|
typeobject Classtype = {
|
||||||
OB_HEAD_INIT(&Typetype)
|
OB_HEAD_INIT(&Typetype)
|
||||||
0,
|
0,
|
||||||
|
@ -155,7 +173,7 @@ typeobject Classtype = {
|
||||||
class_getattr, /*tp_getattr*/
|
class_getattr, /*tp_getattr*/
|
||||||
class_setattr, /*tp_setattr*/
|
class_setattr, /*tp_setattr*/
|
||||||
0, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
0, /*tp_repr*/
|
class_repr, /*tp_repr*/
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
|
@ -170,12 +188,18 @@ typedef struct {
|
||||||
object *in_attr; /* A dictionary */
|
object *in_attr; /* A dictionary */
|
||||||
} instanceobject;
|
} instanceobject;
|
||||||
|
|
||||||
|
static object *instance_getattr PROTO((instanceobject *, char *));
|
||||||
|
|
||||||
object *
|
object *
|
||||||
newinstanceobject(class)
|
newinstanceobject(class, arg)
|
||||||
register object *class;
|
object *class;
|
||||||
|
object *arg;
|
||||||
{
|
{
|
||||||
register instanceobject *inst;
|
register instanceobject *inst;
|
||||||
object *v;
|
object *v;
|
||||||
|
object *init;
|
||||||
|
int pos;
|
||||||
|
object *key, *value;
|
||||||
if (!is_classobject(class)) {
|
if (!is_classobject(class)) {
|
||||||
err_badcall();
|
err_badcall();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -187,9 +211,52 @@ newinstanceobject(class)
|
||||||
inst->in_class = (classobject *)class;
|
inst->in_class = (classobject *)class;
|
||||||
inst->in_attr = newdictobject();
|
inst->in_attr = newdictobject();
|
||||||
if (inst->in_attr == NULL) {
|
if (inst->in_attr == NULL) {
|
||||||
|
error:
|
||||||
DECREF(inst);
|
DECREF(inst);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
pos = 0;
|
||||||
|
while (mappinggetnext(((classobject *)class)->cl_methods,
|
||||||
|
&pos, &key, &value)) {
|
||||||
|
if (is_accessobject(value)) {
|
||||||
|
object *ac = cloneaccessobject(value);
|
||||||
|
int err;
|
||||||
|
if (ac == NULL)
|
||||||
|
goto error;
|
||||||
|
err = dict2insert(inst->in_attr, key, ac);
|
||||||
|
DECREF(ac);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
init = instance_getattr(inst, "__init__");
|
||||||
|
if (init == NULL) {
|
||||||
|
err_clear();
|
||||||
|
if (arg != NULL && !(is_tupleobject(arg) &&
|
||||||
|
gettuplesize(arg) == 0)) {
|
||||||
|
err_setstr(TypeError,
|
||||||
|
"this classobject() takes no arguments");
|
||||||
|
DECREF(inst);
|
||||||
|
inst = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
object *res = call_object(init, arg);
|
||||||
|
DECREF(init);
|
||||||
|
if (res == NULL) {
|
||||||
|
DECREF(inst);
|
||||||
|
inst = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (res != None) {
|
||||||
|
err_setstr(TypeError,
|
||||||
|
"__init__() should return None");
|
||||||
|
DECREF(inst);
|
||||||
|
inst = NULL;
|
||||||
|
}
|
||||||
|
DECREF(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
return (object *)inst;
|
return (object *)inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,9 +266,29 @@ static void
|
||||||
instance_dealloc(inst)
|
instance_dealloc(inst)
|
||||||
register instanceobject *inst;
|
register instanceobject *inst;
|
||||||
{
|
{
|
||||||
|
object *error_type, *error_value;
|
||||||
|
object *del;
|
||||||
|
/* Call the __del__ method if it exists. First temporarily
|
||||||
|
revive the object and save the current exception, if any. */
|
||||||
|
INCREF(inst);
|
||||||
|
err_get(&error_type, &error_value);
|
||||||
|
if ((del = instance_getattr(inst, "__del__")) != NULL) {
|
||||||
|
object *args = newtupleobject(0);
|
||||||
|
object *res = args;
|
||||||
|
if (res != NULL)
|
||||||
|
res = call_object(del, args);
|
||||||
|
XDECREF(args);
|
||||||
|
DECREF(del);
|
||||||
|
XDECREF(res);
|
||||||
|
/* XXX If __del__ raised an exception, it is ignored! */
|
||||||
|
}
|
||||||
|
/* Restore the saved exception and undo the temporary revival */
|
||||||
|
err_setval(error_type, error_value);
|
||||||
|
/* Can't use DECREF here, it would cause a recursive call */
|
||||||
|
if (--inst->ob_refcnt > 0)
|
||||||
|
return; /* __del__ added a reference; don't delete now */
|
||||||
DECREF(inst->in_class);
|
DECREF(inst->in_class);
|
||||||
if (inst->in_attr != NULL)
|
XDECREF(inst->in_attr);
|
||||||
DECREF(inst->in_attr);
|
|
||||||
free((ANY *)inst);
|
free((ANY *)inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +308,10 @@ instance_getattr(inst, name)
|
||||||
}
|
}
|
||||||
v = dictlookup(inst->in_attr, name);
|
v = dictlookup(inst->in_attr, name);
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
INCREF(v);
|
if (is_accessobject(v))
|
||||||
|
v = getaccessvalue(v, (object *)NULL);
|
||||||
|
else
|
||||||
|
INCREF(v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
v = class_getattr(inst->in_class, name);
|
v = class_getattr(inst->in_class, name);
|
||||||
|
@ -243,6 +333,7 @@ instance_setattr(inst, name, v)
|
||||||
char *name;
|
char *name;
|
||||||
object *v;
|
object *v;
|
||||||
{
|
{
|
||||||
|
object *ac;
|
||||||
if (name[0] == '_' && name[1] == '_') {
|
if (name[0] == '_' && name[1] == '_') {
|
||||||
int n = strlen(name);
|
int n = strlen(name);
|
||||||
if (name[n-1] == '_' && name[n-2] == '_') {
|
if (name[n-1] == '_' && name[n-2] == '_') {
|
||||||
|
@ -250,6 +341,9 @@ instance_setattr(inst, name, v)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ac = dictlookup(inst->in_attr, name);
|
||||||
|
if (ac != NULL && is_accessobject(ac))
|
||||||
|
return setaccessvalue(ac, (object *)NULL, v);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
int rv = dictremove(inst->in_attr, name);
|
int rv = dictremove(inst->in_attr, name);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
|
@ -270,9 +364,15 @@ instance_repr(inst)
|
||||||
|
|
||||||
func = instance_getattr(inst, "__repr__");
|
func = instance_getattr(inst, "__repr__");
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
char buf[80];
|
char buf[140];
|
||||||
|
object *classname = inst->in_class->cl_name;
|
||||||
|
char *cname;
|
||||||
|
if (classname != NULL && is_stringobject(classname))
|
||||||
|
cname = getstringvalue(classname);
|
||||||
|
else
|
||||||
|
cname = "?";
|
||||||
err_clear();
|
err_clear();
|
||||||
sprintf(buf, "<instance object at %lx>", (long)inst);
|
sprintf(buf, "<%.100s instance at %lx>", cname, (long)inst);
|
||||||
return newstringobject(buf);
|
return newstringobject(buf);
|
||||||
}
|
}
|
||||||
res = call_object(func, (object *)NULL);
|
res = call_object(func, (object *)NULL);
|
||||||
|
@ -773,6 +873,7 @@ typeobject Instancetype = {
|
||||||
0,
|
0,
|
||||||
instance_dealloc, /*tp_dealloc*/
|
instance_dealloc, /*tp_dealloc*/
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
|
(object * (*) FPROTO((object *, char *)))
|
||||||
instance_getattr, /*tp_getattr*/
|
instance_getattr, /*tp_getattr*/
|
||||||
instance_setattr, /*tp_setattr*/
|
instance_setattr, /*tp_setattr*/
|
||||||
instance_compare, /*tp_compare*/
|
instance_compare, /*tp_compare*/
|
||||||
|
@ -879,6 +980,28 @@ instancemethod_compare(a, b)
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static object *
|
||||||
|
instancemethod_repr(a)
|
||||||
|
instancemethodobject *a;
|
||||||
|
{
|
||||||
|
char buf[240];
|
||||||
|
object *classname =
|
||||||
|
((instanceobject *)(a->im_self))->in_class->cl_name;
|
||||||
|
object *funcname = ((funcobject *)(a->im_func))->func_name;
|
||||||
|
char *cname, *fname;
|
||||||
|
if (classname != NULL && is_stringobject(classname))
|
||||||
|
cname = getstringvalue(classname);
|
||||||
|
else
|
||||||
|
cname = "?";
|
||||||
|
if (funcname != NULL && is_stringobject(funcname))
|
||||||
|
fname = getstringvalue(funcname);
|
||||||
|
else
|
||||||
|
fname = "?";
|
||||||
|
sprintf(buf, "<method %.100s of %.100s instance at %lx>",
|
||||||
|
fname, cname, (long)a->im_func);
|
||||||
|
return newstringobject(buf);
|
||||||
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
instancemethod_hash(a)
|
instancemethod_hash(a)
|
||||||
instancemethodobject *a;
|
instancemethodobject *a;
|
||||||
|
@ -904,7 +1027,7 @@ typeobject Instancemethodtype = {
|
||||||
instancemethod_getattr, /*tp_getattr*/
|
instancemethod_getattr, /*tp_getattr*/
|
||||||
0, /*tp_setattr*/
|
0, /*tp_setattr*/
|
||||||
instancemethod_compare, /*tp_compare*/
|
instancemethod_compare, /*tp_compare*/
|
||||||
0, /*tp_repr*/
|
instancemethod_repr, /*tp_repr*/
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
|
|
|
@ -307,39 +307,49 @@ mappingremove(op, key)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
getmappingsize(op)
|
mappingclear(op)
|
||||||
register object *op;
|
object *op;
|
||||||
{
|
{
|
||||||
if (!is_mappingobject(op)) {
|
int i;
|
||||||
err_badcall();
|
register mappingobject *mp;
|
||||||
return -1;
|
if (!is_mappingobject(op))
|
||||||
|
return;
|
||||||
|
mp = (mappingobject *)op;
|
||||||
|
for (i = 0; i < mp->ma_size; i++) {
|
||||||
|
XDECREF(mp->ma_table[i].me_key);
|
||||||
|
XDECREF(mp->ma_table[i].me_value);
|
||||||
|
mp->ma_table[i].me_key = NULL;
|
||||||
|
mp->ma_table[i].me_value = NULL;
|
||||||
}
|
}
|
||||||
return ((mappingobject *)op) -> ma_size;
|
mp->ma_used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
object *
|
int
|
||||||
getmappingkey(op, i)
|
mappinggetnext(op, ppos, pkey, pvalue)
|
||||||
object *op;
|
object *op;
|
||||||
register int i;
|
int *ppos;
|
||||||
|
object **pkey;
|
||||||
|
object **pvalue;
|
||||||
{
|
{
|
||||||
/* XXX This can't return errors since its callers assume
|
int i;
|
||||||
that NULL means there was no key at that point */
|
|
||||||
register mappingobject *mp;
|
register mappingobject *mp;
|
||||||
if (!is_mappingobject(op)) {
|
if (!is_dictobject(op))
|
||||||
/* err_badcall(); */
|
return 0;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
mp = (mappingobject *)op;
|
mp = (mappingobject *)op;
|
||||||
if (i < 0 || i >= mp->ma_size) {
|
i = *ppos;
|
||||||
/* err_badarg(); */
|
if (i < 0)
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
while (i < mp->ma_size && mp->ma_table[i].me_value == NULL)
|
||||||
if (mp->ma_table[i].me_value == NULL) {
|
i++;
|
||||||
/* Not an error! */
|
*ppos = i+1;
|
||||||
return NULL;
|
if (i >= mp->ma_size)
|
||||||
}
|
return 0;
|
||||||
return (object *) mp->ma_table[i].me_key;
|
if (pkey)
|
||||||
|
*pkey = mp->ma_table[i].me_key;
|
||||||
|
if (pvalue)
|
||||||
|
*pvalue = mp->ma_table[i].me_value;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
@ -488,6 +498,61 @@ mapping_keys(mp, args)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static object *
|
||||||
|
mapping_values(mp, args)
|
||||||
|
register mappingobject *mp;
|
||||||
|
object *args;
|
||||||
|
{
|
||||||
|
register object *v;
|
||||||
|
register int i, j;
|
||||||
|
if (!getnoarg(args))
|
||||||
|
return NULL;
|
||||||
|
v = newlistobject(mp->ma_used);
|
||||||
|
if (v == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0, j = 0; i < mp->ma_size; i++) {
|
||||||
|
if (mp->ma_table[i].me_value != NULL) {
|
||||||
|
object *value = mp->ma_table[i].me_value;
|
||||||
|
INCREF(value);
|
||||||
|
setlistitem(v, j, value);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static object *
|
||||||
|
mapping_items(mp, args)
|
||||||
|
register mappingobject *mp;
|
||||||
|
object *args;
|
||||||
|
{
|
||||||
|
register object *v;
|
||||||
|
register int i, j;
|
||||||
|
if (!getnoarg(args))
|
||||||
|
return NULL;
|
||||||
|
v = newlistobject(mp->ma_used);
|
||||||
|
if (v == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0, j = 0; i < mp->ma_size; i++) {
|
||||||
|
if (mp->ma_table[i].me_value != NULL) {
|
||||||
|
object *key = mp->ma_table[i].me_key;
|
||||||
|
object *value = mp->ma_table[i].me_value;
|
||||||
|
object *item = newtupleobject(2);
|
||||||
|
if (item == NULL) {
|
||||||
|
DECREF(v);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
INCREF(key);
|
||||||
|
settupleitem(item, 0, key);
|
||||||
|
INCREF(value);
|
||||||
|
settupleitem(item, 1, value);
|
||||||
|
setlistitem(v, j, item);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
object *
|
object *
|
||||||
getmappingkeys(mp)
|
getmappingkeys(mp)
|
||||||
object *mp;
|
object *mp;
|
||||||
|
@ -499,6 +564,28 @@ getmappingkeys(mp)
|
||||||
return mapping_keys((mappingobject *)mp, (object *)NULL);
|
return mapping_keys((mappingobject *)mp, (object *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object *
|
||||||
|
getmappingvalues(mp)
|
||||||
|
object *mp;
|
||||||
|
{
|
||||||
|
if (mp == NULL || !is_mappingobject(mp)) {
|
||||||
|
err_badcall();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return mapping_values((mappingobject *)mp, (object *)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
object *
|
||||||
|
getmappingitems(mp)
|
||||||
|
object *mp;
|
||||||
|
{
|
||||||
|
if (mp == NULL || !is_mappingobject(mp)) {
|
||||||
|
err_badcall();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return mapping_values((mappingobject *)mp, (object *)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mapping_compare(a, b)
|
mapping_compare(a, b)
|
||||||
mappingobject *a, *b;
|
mappingobject *a, *b;
|
||||||
|
@ -582,8 +669,10 @@ mapping_has_key(mp, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct methodlist mapp_methods[] = {
|
static struct methodlist mapp_methods[] = {
|
||||||
{"keys", mapping_keys},
|
|
||||||
{"has_key", mapping_has_key},
|
{"has_key", mapping_has_key},
|
||||||
|
{"items", mapping_items},
|
||||||
|
{"keys", mapping_keys},
|
||||||
|
{"values", mapping_values},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -697,14 +786,3 @@ dictremove(v, key)
|
||||||
}
|
}
|
||||||
return mappingremove(v, last_name_object);
|
return mappingremove(v, last_name_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
getdictkey(v, i)
|
|
||||||
object *v;
|
|
||||||
int i;
|
|
||||||
{
|
|
||||||
object *key = getmappingkey(v, i);
|
|
||||||
if (key == NULL)
|
|
||||||
return NULL;
|
|
||||||
return getstringvalue(key);
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,12 +28,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "compile.h"
|
#include "compile.h"
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
OB_HEAD
|
|
||||||
object *func_code;
|
|
||||||
object *func_globals;
|
|
||||||
} funcobject;
|
|
||||||
|
|
||||||
object *
|
object *
|
||||||
newfuncobject(code, globals)
|
newfuncobject(code, globals)
|
||||||
object *code;
|
object *code;
|
||||||
|
@ -45,6 +39,8 @@ newfuncobject(code, globals)
|
||||||
op->func_code = code;
|
op->func_code = code;
|
||||||
INCREF(globals);
|
INCREF(globals);
|
||||||
op->func_globals = globals;
|
op->func_globals = globals;
|
||||||
|
op->func_name = ((codeobject*)(op->func_code))->co_name;
|
||||||
|
INCREF(op->func_name);
|
||||||
}
|
}
|
||||||
return (object *)op;
|
return (object *)op;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +74,7 @@ getfuncglobals(op)
|
||||||
static struct memberlist func_memberlist[] = {
|
static struct memberlist func_memberlist[] = {
|
||||||
{"func_code", T_OBJECT, OFF(func_code), READONLY},
|
{"func_code", T_OBJECT, OFF(func_code), READONLY},
|
||||||
{"func_globals",T_OBJECT, OFF(func_globals), READONLY},
|
{"func_globals",T_OBJECT, OFF(func_globals), READONLY},
|
||||||
|
{"func_name", T_OBJECT, OFF(func_name), READONLY},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,7 +101,7 @@ func_repr(op)
|
||||||
{
|
{
|
||||||
char buf[140];
|
char buf[140];
|
||||||
sprintf(buf, "<function %.100s at %lx>",
|
sprintf(buf, "<function %.100s at %lx>",
|
||||||
getstringvalue(((codeobject*)(op->func_code))->co_name),
|
getstringvalue(op->func_name),
|
||||||
(long)op);
|
(long)op);
|
||||||
return newstringobject(buf);
|
return newstringobject(buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,39 +307,49 @@ mappingremove(op, key)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
getmappingsize(op)
|
mappingclear(op)
|
||||||
register object *op;
|
object *op;
|
||||||
{
|
{
|
||||||
if (!is_mappingobject(op)) {
|
int i;
|
||||||
err_badcall();
|
register mappingobject *mp;
|
||||||
return -1;
|
if (!is_mappingobject(op))
|
||||||
|
return;
|
||||||
|
mp = (mappingobject *)op;
|
||||||
|
for (i = 0; i < mp->ma_size; i++) {
|
||||||
|
XDECREF(mp->ma_table[i].me_key);
|
||||||
|
XDECREF(mp->ma_table[i].me_value);
|
||||||
|
mp->ma_table[i].me_key = NULL;
|
||||||
|
mp->ma_table[i].me_value = NULL;
|
||||||
}
|
}
|
||||||
return ((mappingobject *)op) -> ma_size;
|
mp->ma_used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
object *
|
int
|
||||||
getmappingkey(op, i)
|
mappinggetnext(op, ppos, pkey, pvalue)
|
||||||
object *op;
|
object *op;
|
||||||
register int i;
|
int *ppos;
|
||||||
|
object **pkey;
|
||||||
|
object **pvalue;
|
||||||
{
|
{
|
||||||
/* XXX This can't return errors since its callers assume
|
int i;
|
||||||
that NULL means there was no key at that point */
|
|
||||||
register mappingobject *mp;
|
register mappingobject *mp;
|
||||||
if (!is_mappingobject(op)) {
|
if (!is_dictobject(op))
|
||||||
/* err_badcall(); */
|
return 0;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
mp = (mappingobject *)op;
|
mp = (mappingobject *)op;
|
||||||
if (i < 0 || i >= mp->ma_size) {
|
i = *ppos;
|
||||||
/* err_badarg(); */
|
if (i < 0)
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
while (i < mp->ma_size && mp->ma_table[i].me_value == NULL)
|
||||||
if (mp->ma_table[i].me_value == NULL) {
|
i++;
|
||||||
/* Not an error! */
|
*ppos = i+1;
|
||||||
return NULL;
|
if (i >= mp->ma_size)
|
||||||
}
|
return 0;
|
||||||
return (object *) mp->ma_table[i].me_key;
|
if (pkey)
|
||||||
|
*pkey = mp->ma_table[i].me_key;
|
||||||
|
if (pvalue)
|
||||||
|
*pvalue = mp->ma_table[i].me_value;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
@ -488,6 +498,61 @@ mapping_keys(mp, args)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static object *
|
||||||
|
mapping_values(mp, args)
|
||||||
|
register mappingobject *mp;
|
||||||
|
object *args;
|
||||||
|
{
|
||||||
|
register object *v;
|
||||||
|
register int i, j;
|
||||||
|
if (!getnoarg(args))
|
||||||
|
return NULL;
|
||||||
|
v = newlistobject(mp->ma_used);
|
||||||
|
if (v == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0, j = 0; i < mp->ma_size; i++) {
|
||||||
|
if (mp->ma_table[i].me_value != NULL) {
|
||||||
|
object *value = mp->ma_table[i].me_value;
|
||||||
|
INCREF(value);
|
||||||
|
setlistitem(v, j, value);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static object *
|
||||||
|
mapping_items(mp, args)
|
||||||
|
register mappingobject *mp;
|
||||||
|
object *args;
|
||||||
|
{
|
||||||
|
register object *v;
|
||||||
|
register int i, j;
|
||||||
|
if (!getnoarg(args))
|
||||||
|
return NULL;
|
||||||
|
v = newlistobject(mp->ma_used);
|
||||||
|
if (v == NULL)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0, j = 0; i < mp->ma_size; i++) {
|
||||||
|
if (mp->ma_table[i].me_value != NULL) {
|
||||||
|
object *key = mp->ma_table[i].me_key;
|
||||||
|
object *value = mp->ma_table[i].me_value;
|
||||||
|
object *item = newtupleobject(2);
|
||||||
|
if (item == NULL) {
|
||||||
|
DECREF(v);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
INCREF(key);
|
||||||
|
settupleitem(item, 0, key);
|
||||||
|
INCREF(value);
|
||||||
|
settupleitem(item, 1, value);
|
||||||
|
setlistitem(v, j, item);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
object *
|
object *
|
||||||
getmappingkeys(mp)
|
getmappingkeys(mp)
|
||||||
object *mp;
|
object *mp;
|
||||||
|
@ -499,6 +564,28 @@ getmappingkeys(mp)
|
||||||
return mapping_keys((mappingobject *)mp, (object *)NULL);
|
return mapping_keys((mappingobject *)mp, (object *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object *
|
||||||
|
getmappingvalues(mp)
|
||||||
|
object *mp;
|
||||||
|
{
|
||||||
|
if (mp == NULL || !is_mappingobject(mp)) {
|
||||||
|
err_badcall();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return mapping_values((mappingobject *)mp, (object *)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
object *
|
||||||
|
getmappingitems(mp)
|
||||||
|
object *mp;
|
||||||
|
{
|
||||||
|
if (mp == NULL || !is_mappingobject(mp)) {
|
||||||
|
err_badcall();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return mapping_values((mappingobject *)mp, (object *)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mapping_compare(a, b)
|
mapping_compare(a, b)
|
||||||
mappingobject *a, *b;
|
mappingobject *a, *b;
|
||||||
|
@ -582,8 +669,10 @@ mapping_has_key(mp, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct methodlist mapp_methods[] = {
|
static struct methodlist mapp_methods[] = {
|
||||||
{"keys", mapping_keys},
|
|
||||||
{"has_key", mapping_has_key},
|
{"has_key", mapping_has_key},
|
||||||
|
{"items", mapping_items},
|
||||||
|
{"keys", mapping_keys},
|
||||||
|
{"values", mapping_values},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -697,14 +786,3 @@ dictremove(v, key)
|
||||||
}
|
}
|
||||||
return mappingremove(v, last_name_object);
|
return mappingremove(v, last_name_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
getdictkey(v, i)
|
|
||||||
object *v;
|
|
||||||
int i;
|
|
||||||
{
|
|
||||||
object *key = getmappingkey(v, i);
|
|
||||||
if (key == NULL)
|
|
||||||
return NULL;
|
|
||||||
return getstringvalue(key);
|
|
||||||
}
|
|
||||||
|
|
|
@ -109,8 +109,12 @@ module_getattr(m, name)
|
||||||
res = dictlookup(m->md_dict, name);
|
res = dictlookup(m->md_dict, name);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
err_setstr(AttributeError, name);
|
err_setstr(AttributeError, name);
|
||||||
else
|
else {
|
||||||
INCREF(res);
|
if (is_accessobject(res))
|
||||||
|
res = getaccessvalue(res, (object *)NULL);
|
||||||
|
else
|
||||||
|
INCREF(res);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,10 +124,17 @@ module_setattr(m, name, v)
|
||||||
char *name;
|
char *name;
|
||||||
object *v;
|
object *v;
|
||||||
{
|
{
|
||||||
if (strcmp(name, "__dict__") == 0 || strcmp(name, "__name__") == 0) {
|
object *ac;
|
||||||
err_setstr(TypeError, "read-only special attribute");
|
if (name[0] == '_' && name[1] == '_') {
|
||||||
return -1;
|
int n = strlen(name);
|
||||||
|
if (name[n-1] == '_' && name[n-2] == '_') {
|
||||||
|
err_setstr(TypeError, "read-only special attribute");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ac = dictlookup(m->md_dict, name);
|
||||||
|
if (ac != NULL && is_accessobject(ac))
|
||||||
|
return setaccessvalue(ac, (object *)NULL, v);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
int rv = dictremove(m->md_dict, name);
|
int rv = dictremove(m->md_dict, name);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
|
|
|
@ -796,7 +796,9 @@ getbuiltin(name)
|
||||||
|
|
||||||
/* Predefined exceptions */
|
/* Predefined exceptions */
|
||||||
|
|
||||||
|
object *AccessError;
|
||||||
object *AttributeError;
|
object *AttributeError;
|
||||||
|
object *ConflictError;
|
||||||
object *EOFError;
|
object *EOFError;
|
||||||
object *IOError;
|
object *IOError;
|
||||||
object *ImportError;
|
object *ImportError;
|
||||||
|
@ -827,7 +829,9 @@ newstdexception(name)
|
||||||
static void
|
static void
|
||||||
initerrors()
|
initerrors()
|
||||||
{
|
{
|
||||||
|
AccessError = newstdexception("AccessError");
|
||||||
AttributeError = newstdexception("AttributeError");
|
AttributeError = newstdexception("AttributeError");
|
||||||
|
ConflictError = newstdexception("ConflictError");
|
||||||
EOFError = newstdexception("EOFError");
|
EOFError = newstdexception("EOFError");
|
||||||
IOError = newstdexception("IOError");
|
IOError = newstdexception("IOError");
|
||||||
ImportError = newstdexception("ImportError");
|
ImportError = newstdexception("ImportError");
|
||||||
|
|
215
Python/ceval.c
215
Python/ceval.c
|
@ -84,9 +84,10 @@ static int cmp_exception PROTO((object *, object *));
|
||||||
static int cmp_member PROTO((object *, object *));
|
static int cmp_member PROTO((object *, object *));
|
||||||
static object *cmp_outcome PROTO((int, object *, object *));
|
static object *cmp_outcome PROTO((int, object *, object *));
|
||||||
static int import_from PROTO((object *, object *, object *));
|
static int import_from PROTO((object *, object *, object *));
|
||||||
static object *build_class PROTO((object *, object *));
|
static object *build_class PROTO((object *, object *, object *));
|
||||||
static void locals_2_fast PROTO((frameobject *, int));
|
static void locals_2_fast PROTO((frameobject *, int));
|
||||||
static void fast_2_locals PROTO((frameobject *));
|
static void fast_2_locals PROTO((frameobject *));
|
||||||
|
static int access_statement PROTO((object *, int, frameobject *));
|
||||||
|
|
||||||
|
|
||||||
/* Pointer to current frame, used to link new frames to */
|
/* Pointer to current frame, used to link new frames to */
|
||||||
|
@ -743,10 +744,12 @@ eval_code(co, globals, locals, arg)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BUILD_CLASS:
|
case BUILD_CLASS:
|
||||||
w = POP();
|
u = POP();
|
||||||
v = POP();
|
v = POP();
|
||||||
x = build_class(v, w);
|
w = POP();
|
||||||
|
x = build_class(u, v, w);
|
||||||
PUSH(x);
|
PUSH(x);
|
||||||
|
DECREF(u);
|
||||||
DECREF(v);
|
DECREF(v);
|
||||||
DECREF(w);
|
DECREF(w);
|
||||||
break;
|
break;
|
||||||
|
@ -754,12 +757,24 @@ eval_code(co, globals, locals, arg)
|
||||||
case STORE_NAME:
|
case STORE_NAME:
|
||||||
w = GETNAMEV(oparg);
|
w = GETNAMEV(oparg);
|
||||||
v = POP();
|
v = POP();
|
||||||
|
u = dict2lookup(f->f_locals, w);
|
||||||
|
if (u != NULL && is_accessobject(u)) {
|
||||||
|
err = setaccessvalue(u, (object *)NULL, v);
|
||||||
|
DECREF(v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
err = dict2insert(f->f_locals, w, v);
|
err = dict2insert(f->f_locals, w, v);
|
||||||
DECREF(v);
|
DECREF(v);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DELETE_NAME:
|
case DELETE_NAME:
|
||||||
w = GETNAMEV(oparg);
|
w = GETNAMEV(oparg);
|
||||||
|
u = dict2lookup(f->f_locals, w);
|
||||||
|
if (u != NULL && is_accessobject(u)) {
|
||||||
|
err = setaccessvalue(u, (object *)NULL,
|
||||||
|
(object *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if ((err = dict2remove(f->f_locals, w)) != 0)
|
if ((err = dict2remove(f->f_locals, w)) != 0)
|
||||||
err_setstr(NameError, getstringvalue(w));
|
err_setstr(NameError, getstringvalue(w));
|
||||||
break;
|
break;
|
||||||
|
@ -952,12 +967,24 @@ eval_code(co, globals, locals, arg)
|
||||||
case STORE_GLOBAL:
|
case STORE_GLOBAL:
|
||||||
w = GETNAMEV(oparg);
|
w = GETNAMEV(oparg);
|
||||||
v = POP();
|
v = POP();
|
||||||
|
u = dict2lookup(f->f_locals, w);
|
||||||
|
if (u != NULL && is_accessobject(u)) {
|
||||||
|
err = setaccessvalue(u, (object *)NULL, v);
|
||||||
|
DECREF(v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
err = dict2insert(f->f_globals, w, v);
|
err = dict2insert(f->f_globals, w, v);
|
||||||
DECREF(v);
|
DECREF(v);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DELETE_GLOBAL:
|
case DELETE_GLOBAL:
|
||||||
w = GETNAMEV(oparg);
|
w = GETNAMEV(oparg);
|
||||||
|
u = dict2lookup(f->f_locals, w);
|
||||||
|
if (u != NULL && is_accessobject(u)) {
|
||||||
|
err = setaccessvalue(u, (object *)NULL,
|
||||||
|
(object *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if ((err = dict2remove(f->f_globals, w)) != 0)
|
if ((err = dict2remove(f->f_globals, w)) != 0)
|
||||||
err_setstr(NameError, getstringvalue(w));
|
err_setstr(NameError, getstringvalue(w));
|
||||||
break;
|
break;
|
||||||
|
@ -984,6 +1011,11 @@ eval_code(co, globals, locals, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_accessobject(x)) {
|
||||||
|
x = getaccessvalue(x, (object *)NULL);
|
||||||
|
if (x == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
INCREF(x);
|
INCREF(x);
|
||||||
PUSH(x);
|
PUSH(x);
|
||||||
break;
|
break;
|
||||||
|
@ -1000,6 +1032,11 @@ eval_code(co, globals, locals, arg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_accessobject(x)) {
|
||||||
|
x = getaccessvalue(x, (object *)NULL);
|
||||||
|
if (x == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
INCREF(x);
|
INCREF(x);
|
||||||
PUSH(x);
|
PUSH(x);
|
||||||
break;
|
break;
|
||||||
|
@ -1011,6 +1048,11 @@ eval_code(co, globals, locals, arg)
|
||||||
err_setstr(NameError, getstringvalue(w));
|
err_setstr(NameError, getstringvalue(w));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (is_accessobject(x)) {
|
||||||
|
x = getaccessvalue(x, (object *)NULL);
|
||||||
|
if (x == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
INCREF(x);
|
INCREF(x);
|
||||||
PUSH(x);
|
PUSH(x);
|
||||||
break;
|
break;
|
||||||
|
@ -1041,15 +1083,25 @@ eval_code(co, globals, locals, arg)
|
||||||
"undefined local variable");
|
"undefined local variable");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (is_accessobject(x)) {
|
||||||
|
x = getaccessvalue(x, (object *)NULL);
|
||||||
|
if (x == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
INCREF(x);
|
INCREF(x);
|
||||||
PUSH(x);
|
PUSH(x);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STORE_FAST:
|
case STORE_FAST:
|
||||||
|
v = POP();
|
||||||
w = GETLISTITEM(fastlocals, oparg);
|
w = GETLISTITEM(fastlocals, oparg);
|
||||||
|
if (w != NULL && is_accessobject(w)) {
|
||||||
|
err = setaccessvalue(w, (object *)NULL, v);
|
||||||
|
DECREF(v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
XDECREF(w);
|
XDECREF(w);
|
||||||
w = POP();
|
GETLISTITEM(fastlocals, oparg) = v;
|
||||||
GETLISTITEM(fastlocals, oparg) = w;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DELETE_FAST:
|
case DELETE_FAST:
|
||||||
|
@ -1059,6 +1111,11 @@ eval_code(co, globals, locals, arg)
|
||||||
"undefined local variable");
|
"undefined local variable");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (w != NULL && is_accessobject(w)) {
|
||||||
|
err = setaccessvalue(w, (object *)NULL,
|
||||||
|
(object *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
DECREF(x);
|
DECREF(x);
|
||||||
GETLISTITEM(fastlocals, oparg) = NULL;
|
GETLISTITEM(fastlocals, oparg) = NULL;
|
||||||
break;
|
break;
|
||||||
|
@ -1124,6 +1181,13 @@ eval_code(co, globals, locals, arg)
|
||||||
err = import_from(f->f_locals, v, w);
|
err = import_from(f->f_locals, v, w);
|
||||||
locals_2_fast(f, 0);
|
locals_2_fast(f, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ACCESS_MODE:
|
||||||
|
v = POP();
|
||||||
|
w = GETNAMEV(oparg);
|
||||||
|
err = access_statement(w, (int)getintvalue(v), f);
|
||||||
|
DECREF(v);
|
||||||
|
break;
|
||||||
|
|
||||||
case JUMP_FORWARD:
|
case JUMP_FORWARD:
|
||||||
JUMPBY(oparg);
|
JUMPBY(oparg);
|
||||||
|
@ -1483,7 +1547,8 @@ fast_2_locals(f)
|
||||||
/* Merge f->f_fastlocals into f->f_locals */
|
/* Merge f->f_fastlocals into f->f_locals */
|
||||||
object *locals, *fast, *map;
|
object *locals, *fast, *map;
|
||||||
object *error_type, *error_value;
|
object *error_type, *error_value;
|
||||||
int i;
|
int pos;
|
||||||
|
object *key, *value;
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
return;
|
return;
|
||||||
locals = f->f_locals;
|
locals = f->f_locals;
|
||||||
|
@ -1495,16 +1560,10 @@ fast_2_locals(f)
|
||||||
!is_dictobject(map))
|
!is_dictobject(map))
|
||||||
return;
|
return;
|
||||||
err_get(&error_type, &error_value);
|
err_get(&error_type, &error_value);
|
||||||
i = getdictsize(map);
|
pos = 0;
|
||||||
while (--i >= 0) {
|
while (mappinggetnext(map, &pos, &key, &value)) {
|
||||||
object *key;
|
|
||||||
object *value;
|
|
||||||
int j;
|
int j;
|
||||||
key = getdict2key(map, i);
|
if (!is_intobject(value))
|
||||||
if (key == NULL)
|
|
||||||
continue;
|
|
||||||
value = dict2lookup(map, key);
|
|
||||||
if (value == NULL || !is_intobject(value))
|
|
||||||
continue;
|
continue;
|
||||||
j = getintvalue(value);
|
j = getintvalue(value);
|
||||||
value = getlistitem(fast, j);
|
value = getlistitem(fast, j);
|
||||||
|
@ -1529,7 +1588,8 @@ locals_2_fast(f, clear)
|
||||||
/* Merge f->f_locals into f->f_fastlocals */
|
/* Merge f->f_locals into f->f_fastlocals */
|
||||||
object *locals, *fast, *map;
|
object *locals, *fast, *map;
|
||||||
object *error_type, *error_value;
|
object *error_type, *error_value;
|
||||||
int i;
|
int pos;
|
||||||
|
object *key, *value;
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
return;
|
return;
|
||||||
locals = f->f_locals;
|
locals = f->f_locals;
|
||||||
|
@ -1541,16 +1601,10 @@ locals_2_fast(f, clear)
|
||||||
!is_dictobject(map))
|
!is_dictobject(map))
|
||||||
return;
|
return;
|
||||||
err_get(&error_type, &error_value);
|
err_get(&error_type, &error_value);
|
||||||
i = getdictsize(map);
|
pos = 0;
|
||||||
while (--i >= 0) {
|
while (mappinggetnext(map, &pos, &key, &value)) {
|
||||||
object *key;
|
|
||||||
object *value;
|
|
||||||
int j;
|
int j;
|
||||||
key = getdict2key(map, i);
|
if (!is_intobject(value))
|
||||||
if (key == NULL)
|
|
||||||
continue;
|
|
||||||
value = dict2lookup(map, key);
|
|
||||||
if (value == NULL || !is_intobject(value))
|
|
||||||
continue;
|
continue;
|
||||||
j = getintvalue(value);
|
j = getintvalue(value);
|
||||||
value = dict2lookup(locals, key);
|
value = dict2lookup(locals, key);
|
||||||
|
@ -1907,14 +1961,7 @@ call_builtin(func, arg)
|
||||||
return (*meth)(self, arg);
|
return (*meth)(self, arg);
|
||||||
}
|
}
|
||||||
if (is_classobject(func)) {
|
if (is_classobject(func)) {
|
||||||
if (arg != NULL &&
|
return newinstanceobject(func, arg);
|
||||||
!(is_tupleobject(arg) &&
|
|
||||||
gettuplesize(arg) == 0)) {
|
|
||||||
err_setstr(TypeError,
|
|
||||||
"classobject() allows no arguments");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return newinstanceobject(func);
|
|
||||||
}
|
}
|
||||||
err_setstr(TypeError, "call of non-function");
|
err_setstr(TypeError, "call of non-function");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2258,19 +2305,14 @@ import_from(locals, v, name)
|
||||||
object *w, *x;
|
object *w, *x;
|
||||||
w = getmoduledict(v);
|
w = getmoduledict(v);
|
||||||
if (getstringvalue(name)[0] == '*') {
|
if (getstringvalue(name)[0] == '*') {
|
||||||
int i;
|
int pos;
|
||||||
int n = getdictsize(w);
|
object *name, *value;
|
||||||
for (i = 0; i < n; i++) {
|
pos = 0;
|
||||||
name = getdict2key(w, i);
|
while (mappinggetnext(w, &pos, &name, &value)) {
|
||||||
if (name == NULL || getstringvalue(name)[0] == '_')
|
if (!is_stringobject(name) ||
|
||||||
|
getstringvalue(name)[0] == '_')
|
||||||
continue;
|
continue;
|
||||||
x = dict2lookup(w, name);
|
if (dict2insert(locals, name, value) != 0)
|
||||||
if (x == NULL) {
|
|
||||||
/* XXX can't happen? */
|
|
||||||
err_setstr(SystemError, getstringvalue(name));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (dict2insert(locals, name, x) != 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2290,27 +2332,74 @@ import_from(locals, v, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
static object *
|
static object *
|
||||||
build_class(v, w)
|
build_class(methods, bases, name)
|
||||||
object *v; /* None or tuple containing base classes */
|
object *methods; /* dictionary */
|
||||||
object *w; /* dictionary */
|
object *bases; /* tuple containing classes */
|
||||||
|
object *name; /* string */
|
||||||
{
|
{
|
||||||
if (is_tupleobject(v)) {
|
int i;
|
||||||
int i;
|
if (!is_tupleobject(bases)) {
|
||||||
for (i = gettuplesize(v); --i >= 0; ) {
|
err_setstr(SystemError, "build_class with non-tuple bases");
|
||||||
object *x = gettupleitem(v, i);
|
return NULL;
|
||||||
if (!is_classobject(x)) {
|
|
||||||
err_setstr(TypeError,
|
|
||||||
"base is not a class object");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
if (!is_dictobject(methods)) {
|
||||||
v = NULL;
|
|
||||||
}
|
|
||||||
if (!is_dictobject(w)) {
|
|
||||||
err_setstr(SystemError, "build_class with non-dictionary");
|
err_setstr(SystemError, "build_class with non-dictionary");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return newclassobject(v, w, (object *) NULL);
|
if (!is_stringobject(name)) {
|
||||||
|
err_setstr(SystemError, "build_class witn non-string name");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (i = gettuplesize(bases); --i >= 0; ) {
|
||||||
|
object *base = gettupleitem(bases, i);
|
||||||
|
if (!is_classobject(base)) {
|
||||||
|
err_setstr(TypeError,
|
||||||
|
"base is not a class object");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newclassobject(bases, methods, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
access_statement(name, mode, f)
|
||||||
|
object *name;
|
||||||
|
int mode;
|
||||||
|
frameobject *f;
|
||||||
|
{
|
||||||
|
object *value;
|
||||||
|
int i = -1;
|
||||||
|
object *ac;
|
||||||
|
int ret;
|
||||||
|
if (f->f_localmap == NULL)
|
||||||
|
value = dict2lookup(f->f_locals, name);
|
||||||
|
else {
|
||||||
|
value = dict2lookup(f->f_localmap, name);
|
||||||
|
if (value == NULL || !is_intobject(value))
|
||||||
|
value = NULL;
|
||||||
|
else {
|
||||||
|
i = getintvalue(value);
|
||||||
|
if (0 <= i && i < getlistsize(f->f_fastlocals))
|
||||||
|
value = getlistitem(f->f_fastlocals, i);
|
||||||
|
else {
|
||||||
|
value = NULL;
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value && is_accessobject(value)) {
|
||||||
|
err_setstr(AccessError, "can't override access");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
err_clear();
|
||||||
|
ac = newaccessobject(value, (object*)NULL, (typeobject*)NULL, mode);
|
||||||
|
if (ac == NULL)
|
||||||
|
return -1;
|
||||||
|
if (i >= 0)
|
||||||
|
ret = setlistitem(f->f_fastlocals, i, ac);
|
||||||
|
else {
|
||||||
|
ret = dict2insert(f->f_locals, name, ac);
|
||||||
|
DECREF(ac);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
137
Python/compile.c
137
Python/compile.c
|
@ -1408,6 +1408,65 @@ com_global_stmt(c, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define strequ(a, b) (strcmp((a), (b)) == 0)
|
||||||
|
|
||||||
|
static void
|
||||||
|
com_access_stmt(c, n)
|
||||||
|
struct compiling *c;
|
||||||
|
node *n;
|
||||||
|
{
|
||||||
|
int i, j, k, mode, imode;
|
||||||
|
object *vmode;
|
||||||
|
REQ(n, access_stmt);
|
||||||
|
/* 'access' NAME (',' NAME)* ':' accesstype (',' accesstype)*
|
||||||
|
accesstype: NAME+ */
|
||||||
|
|
||||||
|
/* Find where the colon is */
|
||||||
|
i = 1;
|
||||||
|
while (TYPE(CHILD(n,i-1)) != COLON)
|
||||||
|
i += 1;
|
||||||
|
|
||||||
|
/* Calculate the mode mask */
|
||||||
|
mode = 0;
|
||||||
|
for (j = i; j < NCH(n); j += 2) {
|
||||||
|
int r=0,w=0,p=0;
|
||||||
|
for (k=0; k<NCH(CHILD(n,j)); k++) {
|
||||||
|
if (strequ(STR(CHILD(CHILD(n,j),k)), "public"))
|
||||||
|
p = 0;
|
||||||
|
else if (strequ(STR(CHILD(CHILD(n,j),k)), "protected"))
|
||||||
|
p = 1;
|
||||||
|
else if (strequ(STR(CHILD(CHILD(n,j),k)), "private"))
|
||||||
|
p = 2;
|
||||||
|
else if (strequ(STR(CHILD(CHILD(n,j),k)), "read"))
|
||||||
|
r = 1;
|
||||||
|
else if (strequ(STR(CHILD(CHILD(n,j),k)), "write"))
|
||||||
|
w = 1;
|
||||||
|
else /* XXX should make this an exception */
|
||||||
|
fprintf(stderr, "bad access type %s\n",
|
||||||
|
STR(CHILD(CHILD(n,j),k)));
|
||||||
|
}
|
||||||
|
if (r == 0 && w == 0)
|
||||||
|
r =w = 1;
|
||||||
|
if (p == 0) {
|
||||||
|
if (r == 1) mode |= AC_R_PUBLIC;
|
||||||
|
if (w == 1) mode |= AC_W_PUBLIC;
|
||||||
|
} else if (p == 1) {
|
||||||
|
if (r == 1) mode |= AC_R_PROTECTED;
|
||||||
|
if (w == 1) mode |= AC_W_PROTECTED;
|
||||||
|
} else {
|
||||||
|
if (r == 1) mode |= AC_R_PRIVATE;
|
||||||
|
if (w == 1) mode |= AC_W_PRIVATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vmode = newintobject((long)mode);
|
||||||
|
imode = com_addconst(c, vmode);
|
||||||
|
XDECREF(vmode);
|
||||||
|
for (i = 1; TYPE(CHILD(n,i-1)) != COLON; i+=2) {
|
||||||
|
com_addoparg(c, LOAD_CONST, imode);
|
||||||
|
com_addopname(c, ACCESS_MODE, CHILD(n, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
com_if_stmt(c, n)
|
com_if_stmt(c, n)
|
||||||
struct compiling *c;
|
struct compiling *c;
|
||||||
|
@ -1726,23 +1785,7 @@ com_funcdef(c, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
com_oldbases(c, n)
|
com_bases(c, n)
|
||||||
struct compiling *c;
|
|
||||||
node *n;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
REQ(n, baselist);
|
|
||||||
/*
|
|
||||||
baselist: atom arguments (',' atom arguments)*
|
|
||||||
arguments: '(' ')'
|
|
||||||
*/
|
|
||||||
for (i = 0; i < NCH(n); i += 3)
|
|
||||||
com_node(c, CHILD(n, i));
|
|
||||||
com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
com_newbases(c, n)
|
|
||||||
struct compiling *c;
|
struct compiling *c;
|
||||||
node *n;
|
node *n;
|
||||||
{
|
{
|
||||||
|
@ -1759,46 +1802,28 @@ com_classdef(c, n)
|
||||||
struct compiling *c;
|
struct compiling *c;
|
||||||
node *n;
|
node *n;
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
object *v;
|
object *v;
|
||||||
REQ(n, classdef);
|
REQ(n, classdef);
|
||||||
/*
|
/* classdef: class NAME ['(' testlist ')'] ':' suite */
|
||||||
classdef: 'class' NAME
|
if ((v = newstringobject(STR(CHILD(n, 1)))) == NULL) {
|
||||||
['(' testlist ')' |'(' ')' ['=' baselist]] ':' suite
|
c->c_errors++;
|
||||||
baselist: atom arguments (',' atom arguments)*
|
return;
|
||||||
arguments: '(' ')'
|
}
|
||||||
*/
|
/* Push the class name on the stack */
|
||||||
/* This piece of code must push a tuple on the stack (the bases) */
|
i = com_addconst(c, v);
|
||||||
if (TYPE(CHILD(n, 2)) != LPAR) {
|
com_addoparg(c, LOAD_CONST, i);
|
||||||
/* New syntax without base classes:
|
DECREF(v);
|
||||||
class NAME ':' suite
|
/* Push the tuple of base classes on the stack */
|
||||||
___________^
|
if (TYPE(CHILD(n, 2)) != LPAR)
|
||||||
*/
|
|
||||||
com_addoparg(c, BUILD_TUPLE, 0);
|
com_addoparg(c, BUILD_TUPLE, 0);
|
||||||
}
|
else
|
||||||
else {
|
com_bases(c, CHILD(n, 3));
|
||||||
if (TYPE(CHILD(n, 3)) == RPAR) {
|
|
||||||
/* Old syntax with or without base classes:
|
|
||||||
class NAME '(' ')' ['=' baselist] ':' suite
|
|
||||||
_______________^....^...^
|
|
||||||
*/
|
|
||||||
if (TYPE(CHILD(n, 4)) == EQUAL)
|
|
||||||
com_oldbases(c, CHILD(n, 5));
|
|
||||||
else
|
|
||||||
com_addoparg(c, BUILD_TUPLE, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* New syntax with base classes:
|
|
||||||
class NAME '(' testlist ')' ':' suite
|
|
||||||
_______________^
|
|
||||||
*/
|
|
||||||
com_newbases(c, CHILD(n, 3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v = (object *)compile(n, c->c_filename);
|
v = (object *)compile(n, c->c_filename);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
c->c_errors++;
|
c->c_errors++;
|
||||||
else {
|
else {
|
||||||
int i = com_addconst(c, v);
|
i = com_addconst(c, v);
|
||||||
com_addoparg(c, LOAD_CONST, i);
|
com_addoparg(c, LOAD_CONST, i);
|
||||||
com_addbyte(c, BUILD_FUNCTION);
|
com_addbyte(c, BUILD_FUNCTION);
|
||||||
com_addbyte(c, UNARY_CALL);
|
com_addbyte(c, UNARY_CALL);
|
||||||
|
@ -1882,6 +1907,9 @@ com_node(c, n)
|
||||||
case global_stmt:
|
case global_stmt:
|
||||||
com_global_stmt(c, n);
|
com_global_stmt(c, n);
|
||||||
break;
|
break;
|
||||||
|
case access_stmt:
|
||||||
|
com_access_stmt(c, n);
|
||||||
|
break;
|
||||||
case if_stmt:
|
case if_stmt:
|
||||||
com_if_stmt(c, n);
|
com_if_stmt(c, n);
|
||||||
break;
|
break;
|
||||||
|
@ -2084,9 +2112,8 @@ compile_node(c, n)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case classdef: /* A class definition */
|
case classdef: /* A class definition */
|
||||||
/* classdef: 'class' NAME
|
/* classdef: 'class' NAME ['(' testlist ')'] ':' suite */
|
||||||
['(' testlist ')' |'(' ')' ['=' baselist]]
|
c->c_name = STR(CHILD(n, 1));
|
||||||
':' suite */
|
|
||||||
com_node(c, CHILD(n, NCH(n)-1)); /* The suite */
|
com_node(c, CHILD(n, NCH(n)-1)); /* The suite */
|
||||||
com_addbyte(c, LOAD_LOCALS);
|
com_addbyte(c, LOAD_LOCALS);
|
||||||
com_addbyte(c, RETURN_VALUE);
|
com_addbyte(c, RETURN_VALUE);
|
||||||
|
@ -2114,8 +2141,8 @@ compile_node(c, n)
|
||||||
|
|
||||||
There is one problem: 'from foo import *' introduces local variables
|
There is one problem: 'from foo import *' introduces local variables
|
||||||
that we can't know while compiling. If this is the case, wo don't
|
that we can't know while compiling. If this is the case, wo don't
|
||||||
optimize at all (this rarely happens, since import is mostly used
|
optimize at all (this rarely happens, since this form of import
|
||||||
at the module level).
|
statement is mostly used at the module level).
|
||||||
|
|
||||||
Note that, because of this optimization, code like the following
|
Note that, because of this optimization, code like the following
|
||||||
won't work:
|
won't work:
|
||||||
|
|
1026
Python/graminit.c
1026
Python/graminit.c
File diff suppressed because it is too large
Load Diff
|
@ -54,7 +54,7 @@ extern char *argv0;
|
||||||
|
|
||||||
/* Magic word to reject .pyc files generated by other Python versions */
|
/* Magic word to reject .pyc files generated by other Python versions */
|
||||||
|
|
||||||
#define MAGIC 0x99BE3AL
|
#define MAGIC 0x999901L /* Increment by one for each incompatible change */
|
||||||
|
|
||||||
static object *modules;
|
static object *modules;
|
||||||
|
|
||||||
|
@ -353,46 +353,27 @@ reload_module(m)
|
||||||
return get_module(m, getmodulename(m), (object **)NULL);
|
return get_module(m, getmodulename(m), (object **)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
cleardict(d)
|
|
||||||
object *d;
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = getdictsize(d); --i >= 0; ) {
|
|
||||||
char *k;
|
|
||||||
k = getdictkey(d, i);
|
|
||||||
if (k != NULL)
|
|
||||||
(void) dictremove(d, k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
doneimport()
|
doneimport()
|
||||||
{
|
{
|
||||||
if (modules != NULL) {
|
if (modules != NULL) {
|
||||||
int i;
|
int pos;
|
||||||
|
object *modname, *module;
|
||||||
/* Explicitly erase all modules; this is the safest way
|
/* Explicitly erase all modules; this is the safest way
|
||||||
to get rid of at least *some* circular dependencies */
|
to get rid of at least *some* circular dependencies */
|
||||||
for (i = getdictsize(modules); --i >= 0; ) {
|
pos = 0;
|
||||||
object *k;
|
while (mappinggetnext(modules, &pos, &modname, &module)) {
|
||||||
k = getdict2key(modules, i);
|
if (is_moduleobject(module)) {
|
||||||
if (k != NULL) {
|
object *dict;
|
||||||
object *m;
|
dict = getmoduledict(module);
|
||||||
m = dict2lookup(modules, k);
|
if (dict != NULL && is_dictobject(dict))
|
||||||
if (m == NULL)
|
mappingclear(dict);
|
||||||
err_clear();
|
|
||||||
else if (is_moduleobject(m)) {
|
|
||||||
object *d;
|
|
||||||
d = getmoduledict(m);
|
|
||||||
if (d != NULL && is_dictobject(d)) {
|
|
||||||
cleardict(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cleardict(modules);
|
mappingclear(modules);
|
||||||
}
|
}
|
||||||
DECREF(modules);
|
DECREF(modules);
|
||||||
|
modules = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -174,17 +174,14 @@ w_object(v, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (is_dictobject(v)) {
|
else if (is_dictobject(v)) {
|
||||||
|
int pos;
|
||||||
|
object *key, *value;
|
||||||
w_byte(TYPE_DICT, p);
|
w_byte(TYPE_DICT, p);
|
||||||
/* This one is NULL object terminated! */
|
/* This one is NULL object terminated! */
|
||||||
n = getdictsize(v);
|
pos = 0;
|
||||||
for (i = 0; i < n; i++) {
|
while (mappinggetnext(v, &pos, &key, &value)) {
|
||||||
object *key, *val;
|
w_object(key, p);
|
||||||
key = getdict2key(v, (int)i);
|
w_object(value, p);
|
||||||
if (key != NULL) {
|
|
||||||
val = dict2lookup(v, key); /* Can't be NULL */
|
|
||||||
w_object(key, p);
|
|
||||||
w_object(val, p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
w_object((object *)NULL, p);
|
w_object((object *)NULL, p);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue