+static int parListLen(struct Token* t)
+{
+ if(t->type != TOK_LPAR || !LEFT(t) || LEFT(t)->type != TOK_COMMA) return 0;
+ return countList(LEFT(t), TOK_COMMA);
+}
+
+static void genCommaList(struct Parser* p, struct Token* t)
+{
+ if(t->type != TOK_COMMA) { genExpr(p, t); return; }
+ genCommaList(p, RIGHT(t));
+ genExpr(p, LEFT(t));
+}
+
+static void genMultiLV(struct Parser* p, struct Token* t, int var)
+{
+ if(!var) { emit(p, genLValue(p, t, &var)); return; }
+ if(t->type != TOK_SYMBOL) naParseError(p, "bad lvalue", t->line);
+ genScalarConstant(p, t);
+ emit(p, OP_SETLOCAL);
+}
+
+static void genAssign(struct Parser* p, struct Token* t)
+{
+ struct Token *lv = LEFT(t), *rv = RIGHT(t);
+ int len, dummy, var=0;
+ if (!lv)
+ naParseError(p, "bad assignment, missing variable", t->line);
+ else
+ if(parListLen(lv) || (lv->type == TOK_VAR && parListLen(RIGHT(lv)))) {
+ if(lv->type == TOK_VAR) { lv = RIGHT(lv); var = 1; }
+ len = parListLen(lv);
+ if(rv->type == TOK_LPAR) {
+ if(len != parListLen(rv))
+ naParseError(p, "bad assignment count", rv->line);
+ genCommaList(p, LEFT(rv));
+ } else {
+ genExpr(p, rv);
+ emitImmediate(p, OP_UNPACK, len);
+ }
+ for(t = LEFT(lv); t && t->type == TOK_COMMA; t = RIGHT(t)) {
+ genMultiLV(p, LEFT(t), var);
+ emit(p, OP_POP);
+ }
+ genMultiLV(p, t, var);
+ } else {
+ genExpr(p, rv);
+ emit(p, genLValue(p, lv, &dummy));
+ }
+}
+
+static void genSlice(struct Parser* p, struct Token* t)
+{
+ if(!t || t->type==TOK_EMPTY) naParseError(p, "empty slice expression", -1);
+ if(t->type == TOK_COLON) {
+ if(LEFT(t)) genExpr(p, LEFT(t)); else emit(p, OP_PUSHNIL);
+ if(RIGHT(t)) genExpr(p, RIGHT(t)); else emit(p, OP_PUSHNIL);
+ emit(p, OP_SLICE2);
+ } else {
+ genExpr(p, t);
+ emit(p, OP_SLICE);
+ }
+}
+
+static void genExtract(struct Parser* p, struct Token* t)
+{
+ genExpr(p, LEFT(t));
+ if(countList(RIGHT(t), TOK_COMMA) == 1 && RIGHT(t)->type != TOK_COLON) {
+ genExpr(p, RIGHT(t));
+ emit(p, OP_EXTRACT);
+ } else {
+ emit(p, OP_NEWVEC);
+ for(t = RIGHT(t); t->type == TOK_COMMA; t = RIGHT(t))
+ genSlice(p, LEFT(t));
+ genSlice(p, t);
+ emit(p, OP_XCHG);
+ emit(p, OP_POP);
+ }
+}
+