Skip to content

Instantly share code, notes, and snippets.

@moriyoshi
Created May 2, 2010 08:27
Show Gist options
  • Save moriyoshi/a665fc505ef7132a70e1 to your computer and use it in GitHub Desktop.
Save moriyoshi/a665fc505ef7132a70e1 to your computer and use it in GitHub Desktop.
diff -ur Python-2.6.5~/Grammar/Grammar Python-2.6.5/Grammar/Grammar
--- Python-2.6.5~/Grammar/Grammar 2008-08-20 04:52:46.000000000 +0900
+++ Python-2.6.5/Grammar/Grammar 2010-05-02 17:23:23.000000000 +0900
@@ -45,9 +45,10 @@
stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt |
- import_stmt | global_stmt | exec_stmt | assert_stmt)
+ import_stmt | global_stmt | exec_stmt | assert_stmt | const_stmt)
expr_stmt: testlist (augassign (yield_expr|testlist) |
('=' (yield_expr|testlist))*)
+const_stmt: 'readonly' testlist ('=' (yield_expr|testlist))+
augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
# For normal assignments, additional restrictions enforced by the interpreter
diff -ur Python-2.6.5~/Include/symtable.h Python-2.6.5/Include/symtable.h
--- Python-2.6.5~/Include/symtable.h 2008-08-17 10:27:30.000000000 +0900
+++ Python-2.6.5/Include/symtable.h 2010-05-02 16:38:45.000000000 +0900
@@ -72,6 +72,7 @@
#define DEF_FREE_GLOBAL 2<<7 /* free variable is actually implicit global */
#define DEF_FREE_CLASS 2<<8 /* free variable from class's method */
#define DEF_IMPORT 2<<9 /* assignment occurred via import */
+#define DEF_CONST 2<<14 /* name is marked as constant */
#define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT)
diff -ur Python-2.6.5~/Modules/getbuildinfo.c Python-2.6.5/Modules/getbuildinfo.c
--- Python-2.6.5~/Modules/getbuildinfo.c 2009-05-24 04:35:33.000000000 +0900
+++ Python-2.6.5/Modules/getbuildinfo.c 2010-05-02 17:41:11.000000000 +0900
@@ -36,7 +36,7 @@
const char *sep = *revision ? ":" : "";
const char *branch = Py_SubversionShortBranch();
PyOS_snprintf(buildinfo, sizeof(buildinfo),
- "%s%s%s, %.20s, %.9s", branch, sep, revision,
+ "%s%s%s, 魔改造, %.20s, %.9s", branch, sep, revision,
DATE, TIME);
return buildinfo;
}
diff -ur Python-2.6.5~/Parser/Python.asdl Python-2.6.5/Parser/Python.asdl
--- Python-2.6.5~/Parser/Python.asdl 2008-03-30 15:40:17.000000000 +0900
+++ Python-2.6.5/Parser/Python.asdl 2010-05-02 15:53:17.000000000 +0900
@@ -80,7 +80,7 @@
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset)
- expr_context = Load | Store | Del | AugLoad | AugStore | Param
+ expr_context = Load | Store | Del | AugLoad | AugStore | Param | ConstStore
slice = Ellipsis | Slice(expr? lower, expr? upper, expr? step)
| ExtSlice(slice* dims)
diff -ur Python-2.6.5~/Python/ast.c Python-2.6.5/Python/ast.c
--- Python-2.6.5~/Python/ast.c 2009-11-20 08:01:36.000000000 +0900
+++ Python-2.6.5/Python/ast.c 2010-05-02 16:06:21.000000000 +0900
@@ -2181,6 +2181,52 @@
}
static stmt_ty
+ast_for_const_stmt(struct compiling *c, const node *n)
+{
+ int i;
+ asdl_seq *targets;
+ node *value;
+ expr_ty expression;
+
+ REQ(n, const_stmt);
+ /* const_stmt: 'const' testlist ('=' (yield_expr|testlist))+ */
+
+ /* a normal assignment */
+ REQ(CHILD(n, 0), NAME);
+ REQ(CHILD(n, 2), EQUAL);
+ targets = asdl_seq_new((NCH(n) - 2) / 2, c->c_arena);
+ if (!targets)
+ return NULL;
+ for (i = 1; i < NCH(n) - 2; i += 2) {
+ expr_ty e;
+ node *ch = CHILD(n, i);
+ if (TYPE(ch) == yield_expr) {
+ ast_error(ch, "assignment to yield expression not possible");
+ return NULL;
+ }
+ e = ast_for_testlist(c, ch);
+
+ /* set context to assign */
+ if (!e)
+ return NULL;
+
+ if (!set_context(c, e, ConstStore, ch))
+ return NULL;
+
+ asdl_seq_SET(targets, i / 2, e);
+ }
+ value = CHILD(n, NCH(n) - 1);
+ if (TYPE(value) == testlist)
+ expression = ast_for_testlist(c, value);
+ else
+ expression = ast_for_expr(c, value);
+ if (!expression)
+ return NULL;
+ return Assign(targets, expression, LINENO(n), n->n_col_offset,
+ c->c_arena);
+}
+
+static stmt_ty
ast_for_print_stmt(struct compiling *c, const node *n)
{
/* print_stmt: 'print' ( [ test (',' test)* [','] ]
@@ -3121,11 +3167,13 @@
n = CHILD(n, 0);
/* small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt
| flow_stmt | import_stmt | global_stmt | exec_stmt
- | assert_stmt
+ | assert_stmt | const_stmt
*/
switch (TYPE(n)) {
case expr_stmt:
return ast_for_expr_stmt(c, n);
+ case const_stmt:
+ return ast_for_const_stmt(c, n);
case print_stmt:
return ast_for_print_stmt(c, n);
case del_stmt:
diff -ur Python-2.6.5~/Python/compile.c Python-2.6.5/Python/compile.c
--- Python-2.6.5~/Python/compile.c 2009-11-29 01:37:36.000000000 +0900
+++ Python-2.6.5/Python/compile.c 2010-05-02 16:05:38.000000000 +0900
@@ -2337,7 +2337,7 @@
/* XXX AugStore isn't used anywhere! */
/* First check for assignment to __debug__. Param? */
- if ((ctx == Store || ctx == AugStore || ctx == Del)
+ if ((ctx == Store || ctx == ConstStore || ctx == AugStore || ctx == Del)
&& !strcmp(PyString_AS_STRING(name), "__debug__")) {
return compiler_error(c, "can not assign to __debug__");
}
@@ -2382,7 +2382,7 @@
case OP_DEREF:
switch (ctx) {
case Load: op = LOAD_DEREF; break;
- case Store: op = STORE_DEREF; break;
+ case Store: case ConstStore: op = STORE_DEREF; break;
case AugLoad:
case AugStore:
break;
@@ -2403,7 +2403,7 @@
case OP_FAST:
switch (ctx) {
case Load: op = LOAD_FAST; break;
- case Store: op = STORE_FAST; break;
+ case Store: case ConstStore: op = STORE_FAST; break;
case Del: op = DELETE_FAST; break;
case AugLoad:
case AugStore:
@@ -2420,7 +2420,7 @@
case OP_GLOBAL:
switch (ctx) {
case Load: op = LOAD_GLOBAL; break;
- case Store: op = STORE_GLOBAL; break;
+ case Store: case ConstStore: op = STORE_GLOBAL; break;
case Del: op = DELETE_GLOBAL; break;
case AugLoad:
case AugStore:
@@ -2435,7 +2435,7 @@
case OP_NAME:
switch (ctx) {
case Load: op = LOAD_NAME; break;
- case Store: op = STORE_NAME; break;
+ case Store: case ConstStore: op = STORE_NAME; break;
case Del: op = DELETE_NAME; break;
case AugLoad:
case AugStore:
@@ -3040,7 +3040,7 @@
case AugStore:
ADDOP(c, ROT_TWO);
/* Fall through to save */
- case Store:
+ case Store: case ConstStore:
ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names);
break;
case Del:
@@ -3066,7 +3066,7 @@
case AugStore:
VISIT_SLICE(c, e->v.Subscript.slice, AugStore);
break;
- case Store:
+ case Store: case ConstStore:
VISIT(c, expr, e->v.Subscript.value);
VISIT_SLICE(c, e->v.Subscript.slice, Store);
break;
@@ -3214,7 +3214,7 @@
case AugLoad: /* fall through to Load */
case Load: op = BINARY_SUBSCR; break;
case AugStore:/* fall through to Store */
- case Store: op = STORE_SUBSCR; break;
+ case ConstStore: case Store: op = STORE_SUBSCR; break;
case Del: op = DELETE_SUBSCR; break;
case Param:
PyErr_Format(PyExc_SystemError,
@@ -3299,7 +3299,7 @@
case AugLoad: /* fall through to Load */
case Load: op = SLICE; break;
case AugStore:/* fall through to Store */
- case Store: op = STORE_SLICE; break;
+ case Store: case ConstStore: op = STORE_SLICE; break;
case Del: op = DELETE_SLICE; break;
case Param:
default:
diff -ur Python-2.6.5~/Python/symtable.c Python-2.6.5/Python/symtable.c
--- Python-2.6.5~/Python/symtable.c 2009-11-20 10:19:48.000000000 +0900
+++ Python-2.6.5/Python/symtable.c 2010-05-02 17:35:20.000000000 +0900
@@ -11,6 +11,18 @@
#define GLOBAL_AFTER_USE \
"name '%.400s' is used prior to global declaration"
+#define CONST_AFTER_ASSIGN \
+"name '%.400s' is assigned to before readonly declaration"
+
+#define CONST_AFTER_PARAM \
+"name '%.400s' already appeared in function parameters"
+
+#define CONST_AFTER_USE \
+"name '%.400s' is used prior to readonly declaration"
+
+#define CONST_VARIABLE \
+"variable '%.400s' is read-only"
+
#define IMPORT_STAR_WARNING "import * only allowed at module level"
#define RETURN_VAL_IN_GENERATOR \
@@ -390,6 +402,15 @@
}
return 1;
}
+ if (flags & DEF_CONST) {
+ if (flags & DEF_PARAM) {
+ PyErr_Format(PyExc_SyntaxError, CONST_AFTER_PARAM,
+ PyString_AS_STRING(name));
+ PyErr_SyntaxLocation(ste->ste_table->st_filename,
+ ste->ste_lineno);
+ return 0;
+ }
+ }
if (flags & DEF_BOUND) {
SET_SCOPE(dict, name, LOCAL);
if (PyDict_SetItem(local, name, Py_None) < 0)
@@ -1285,11 +1306,52 @@
VISIT(st, expr, e->v.Subscript.value);
VISIT(st, slice, e->v.Subscript.slice);
break;
- case Name_kind:
- if (!symtable_add_def(st, e->v.Name.id,
- e->v.Name.ctx == Load ? USE : DEF_LOCAL))
- return 0;
+ case Name_kind: {
+ if (e->v.Name.ctx != Load) {
+ long cur = symtable_lookup(st, e->v.Name.id);
+ if (cur < 0)
+ return 0;
+ if (e->v.Name.ctx == ConstStore && cur & (DEF_LOCAL | USE)) {
+ char *c_name = PyString_AS_STRING(e->v.Name.id);
+ if (cur & DEF_LOCAL)
+ PyErr_Format(PyExc_SyntaxError,
+ CONST_AFTER_ASSIGN,
+ c_name);
+ else
+ PyErr_Format(PyExc_SyntaxError,
+ CONST_AFTER_USE,
+ c_name);
+ PyErr_SyntaxLocation(st->st_filename,
+ e->lineno);
+ return 0;
+ }
+ else if ((cur & DEF_CONST)) {
+ PyErr_Format(PyExc_SyntaxError,
+ CONST_VARIABLE,
+ PyString_AS_STRING(e->v.Name.id));
+ PyErr_SyntaxLocation(st->st_filename,
+ e->lineno);
+ return 0;
+ }
+ }
+ {
+ long flag = 0;
+ switch (e->v.Name.ctx) {
+ case Load:
+ flag = USE;
+ break;
+ case Store:
+ flag = DEF_LOCAL;
+ break;
+ case ConstStore:
+ flag = DEF_LOCAL | DEF_CONST;
+ break;
+ }
+ if (!symtable_add_def(st, e->v.Name.id, flag))
+ return 0;
+ }
break;
+ }
/* child nodes of List and Tuple will have expr_context set */
case List_kind:
VISIT_SEQ(st, expr, e->v.List.elts);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment