Anonymous avatar Anonymous committed 5a92f85

Implement tuple targets correctly.

Comments (0)

Files changed (3)

 #include "arana.h"
 #include "_astmap.h"
 
+#define ON(n) case AR_AST_##n
 
 /* --- Factory functions for all the different nodes ------------------------ */
 
 }
 
 
+/* -- Parser Utilities ------------------------------------------------------ */
+
+/* since we can't directly assign Store context to unpacking assignments,
+   we have to do that here */
+void
+arana_ast_set_store_ctx(AR_SIG, ArExprNode *node)
+{
+    switch(node->type) {
+    ON(Tuple):
+        node->v.Tuple.ctx = AR_CTX_Store;
+        if (node->v.Tuple.items) {
+            for (int i = 0; i < node->v.Tuple.items->count; ++i)
+                arana_ast_set_store_ctx(AR_ISIG, node->v.Tuple.items->items[i]);
+        }
+        break;
+    ON(Name):
+        node->v.Name.ctx = AR_CTX_Store;
+        break;
+    ON(Attribute):
+        node->v.Attribute.ctx = AR_CTX_Store;
+        break;
+    ON(Subscript):
+        node->v.Subscript.ctx = AR_CTX_Store;
+        break;
+    default: {
+        char buf[100];
+        snprintf(buf, 100, "can't assign to %s", AR_ASTMAP[node->type]);
+        AR_RAISE(AR_SYNTAX_ERROR(buf, AR_STRING(node->filename), node->lineno, 0));
+    }
+    }
+}
+
+
 /* --- Generic visitor function --------------------------------------------- */
 
 void
     ArStmtNode *snode = (ArStmtNode *)node;
     ArExprNode *enode = (ArExprNode *)node;
 
-#define ON(n) case AR_AST_##n
 #define VISIT(n) if (n) arana_ast_visit(AR_ISIG, (ArAstNode *)(n), pre, post, closure)
 #define VISIT_SEQ(n) \
     if (n) { for (int i = 0; i < (n)->count; ++i) { VISIT((n)->items[i]); } }
 #define AR_AST_NODE_HEAD const char *filename; int lineno; ArAstType type;
 #define AR_AST_BINARY_HEAD AR_AST_NODE_HEAD; ArAstNode *left, ArAstNode *right;
 #define AR_AST(type, ...) arana_ast_##type(AR_ISIG, __VA_ARGS__)
+#define AR_AST_SET_STORE_CTX(node) arana_ast_set_store_ctx(AR_ISIG, node)
 #define AR_AST_TYPE(x) ((ArAstNode *)(x))->type
 #define AR_AST_IS(x, t) (AR_AST_TYPE(x) == AR_AST_##t)
 
 
 AR_API_FUNC(void) arana_ast_visit(AR_SIG, ArAstNode *node, ArAstVisitFunc pre,
                                   ArAstVisitFunc post, void *closure);
+AR_API_FUNC(void) arana_ast_set_store_ctx(AR_SIG, ArExprNode *node);
 AR_API_FUNC(void) arana_ast_set_filename(AR_SIG, ArAstNode *node,
                                          const char *filename);
 AR_API_FUNC(void) arana_ast_optimize(AR_SIG, ArAstNode *node);
 %type interp_item  { ArExprNode * }
 %type exprlist     { ArExprSeq * }
 %type exprlist1    { ArExprSeq * }
+%type simpletarget { ArExprNode * }
 %type target       { ArExprNode * }
+%type targetlist   { ArExprSeq * }
 
 module ::= statements(B) newlines END.          { ps->ast = AR_AST(Module, B); }
 
 
 // assignments
 expr(A) ::= target(B) ASSIGN expr(C).              { A = AR_AST(Assign, B, C); }
-expr(A) ::= target(B) ADDASSIGN expr(C).
+expr(A) ::= simpletarget(B) ADDASSIGN expr(C).
                                   { A = AR_AST(AugAssign, B, C, AR_ASTOP_ADD); }
-expr(A) ::= target(B) SUBASSIGN expr(C).
+expr(A) ::= simpletarget(B) SUBASSIGN expr(C).
                                   { A = AR_AST(AugAssign, B, C, AR_ASTOP_SUB); }
-expr(A) ::= target(B) MULASSIGN expr(C).
+expr(A) ::= simpletarget(B) MULASSIGN expr(C).
                                   { A = AR_AST(AugAssign, B, C, AR_ASTOP_MUL); }
-expr(A) ::= target(B) DIVASSIGN expr(C).
+expr(A) ::= simpletarget(B) DIVASSIGN expr(C).
                                   { A = AR_AST(AugAssign, B, C, AR_ASTOP_DIV); }
-expr(A) ::= target(B) MODASSIGN expr(C).
+expr(A) ::= simpletarget(B) MODASSIGN expr(C).
                                   { A = AR_AST(AugAssign, B, C, AR_ASTOP_MOD); }
-expr(A) ::= target(B) POWASSIGN expr(C).
+expr(A) ::= simpletarget(B) POWASSIGN expr(C).
                                   { A = AR_AST(AugAssign, B, C, AR_ASTOP_POW); }
 
 interp_items(A) ::= interp_items(B) interp_item(C).
 exprlist(A) ::= exprlist(B) COMMA expr(C).    { AR_AST_SEQ_ADD(Expr, A, B, C); }
 exprlist(A) ::= expr(B).                        { AR_AST_SEQ_NEW1(Expr, A, B); }
 
-target(A) ::= NAME(B).       { A = AR_AST(Name, AR_AS_CHARP(B), AR_CTX_Store); }
-target(A) ::= expr(B) DOT NAME(C).
+simpletarget(A) ::= NAME(B). { A = AR_AST(Name, AR_AS_CHARP(B), AR_CTX_Store); }
+simpletarget(A) ::= expr(B) DOT NAME(C).
                  { A = AR_AST(Attribute, B, AR_AST(Literal, C), AR_CTX_Store); }
-target(A) ::= expr(B) DOT LBRACKET expr(C) RBRACKET.
+simpletarget(A) ::= expr(B) DOT LBRACKET expr(C) RBRACKET.
                                   { A = AR_AST(Attribute, B, C, AR_CTX_Store); }
-target(A) ::= expr(B) LBRACKET expr(C) RBRACKET.
+simpletarget(A) ::= expr(B) LBRACKET expr(C) RBRACKET.
                                   { A = AR_AST(Subscript, B, C, AR_CTX_Store); }
-target(A) ::= LPAREN RPAREN.          { A = AR_AST(Tuple, NULL, AR_CTX_Store); }
+
+target(A) ::= simpletarget(B).                                        { A = B; }
 target(A) ::= LPAREN exprlist(B) RPAREN.
-                                     { AR_AST_MAYBE_TUPLE(A, B, AR_CTX_Store); }
+            { AR_AST_MAYBE_TUPLE(A, B, AR_CTX_Store); AR_AST_SET_STORE_CTX(A); }
 target(A) ::= LPAREN exprlist(B) COMMA RPAREN.
-                                         { A = AR_AST(Tuple, B, AR_CTX_Store); }
+                { A = AR_AST(Tuple, B, AR_CTX_Store); AR_AST_SET_STORE_CTX(A); }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.