[Swfdec-commits] 38 commits - vivified/code

Pekka Lampila medar at kemper.freedesktop.org
Sun May 18 09:59:58 PDT 2008


 vivified/code/Makefile.am                                          |    8 
 vivified/code/decompiler.c                                         |    1 
 vivified/code/test/compiler/Makefile.am                            |   42 
 vivified/code/test/compiler/array_literal_empty.as                 |    1 
 vivified/code/test/compiler/array_literal_empty.as.expect          |    7 
 vivified/code/test/compiler/array_literal_missing_values.as        |    6 
 vivified/code/test/compiler/array_literal_missing_values.as.expect |   22 
 vivified/code/test/compiler/asm_default.as                         |   85 +
 vivified/code/test/compiler/asm_default.as.expect                  |   86 +
 vivified/code/test/compiler/asm_label.as                           |    5 
 vivified/code/test/compiler/asm_label.as.expect                    |    7 
 vivified/code/test/compiler/assignment_member.as                   |    2 
 vivified/code/test/compiler/assignment_member.as.expect            |   14 
 vivified/code/test/compiler/assignment_member_value.as             |    2 
 vivified/code/test/compiler/assignment_member_value.as.expect      |   20 
 vivified/code/test/compiler/assignment_value.as                    |    1 
 vivified/code/test/compiler/assignment_value.as.expect             |   10 
 vivified/code/test/compiler/decrement.as                           |    2 
 vivified/code/test/compiler/decrement.as.expect                    |   14 
 vivified/code/test/compiler/do_while.as                            |    3 
 vivified/code/test/compiler/do_while.as.expect                     |   10 
 vivified/code/test/compiler/enumerate.as                           |    3 
 vivified/code/test/compiler/enumerate.as.expect                    |   23 
 vivified/code/test/compiler/enumerate_local.as                     |    3 
 vivified/code/test/compiler/enumerate_local.as.expect              |   23 
 vivified/code/test/compiler/enumerate_member.as                    |    6 
 vivified/code/test/compiler/enumerate_member.as.expect             |   49 
 vivified/code/test/compiler/for.as                                 |    3 
 vivified/code/test/compiler/for.as.expect                          |   23 
 vivified/code/test/compiler/for_local.as                           |    3 
 vivified/code/test/compiler/for_local.as.expect                    |   23 
 vivified/code/test/compiler/increment.as                           |    2 
 vivified/code/test/compiler/increment.as.expect                    |   14 
 vivified/code/test/compiler/increment_member.as                    |    4 
 vivified/code/test/compiler/increment_member.as.expect             |   44 
 vivified/code/test/compiler/increment_member_value.as              |    4 
 vivified/code/test/compiler/increment_member_value.as.expect       |   58 
 vivified/code/test/compiler/increment_value.as                     |    2 
 vivified/code/test/compiler/increment_value.as.expect              |   20 
 vivified/code/test/compiler/label.as                               |    2 
 vivified/code/test/compiler/label.as.expect                        |    2 
 vivified/code/test/compiler/object_literal_empty.as                |    1 
 vivified/code/test/compiler/object_literal_empty.as.expect         |    7 
 vivified/code/test/compiler/operator_precedence.as                 |   43 
 vivified/code/test/compiler/operator_precedence.as.expect          |  205 ++
 vivified/code/test/compiler/var.as                                 |    1 
 vivified/code/test/compiler/var.as.expect                          |   10 
 vivified/code/vivi_code_and.c                                      |   31 
 vivified/code/vivi_code_assignment.c                               |   88 -
 vivified/code/vivi_code_assignment.h                               |   16 
 vivified/code/vivi_code_binary.c                                   |   21 
 vivified/code/vivi_code_boolean.c                                  |   18 
 vivified/code/vivi_code_builtin_call.c                             |   23 
 vivified/code/vivi_code_builtin_statement.c                        |    5 
 vivified/code/vivi_code_builtin_value_call.c                       |   29 
 vivified/code/vivi_code_builtin_value_statement.c                  |    5 
 vivified/code/vivi_code_compiler.c                                 |   31 
 vivified/code/vivi_code_compiler.h                                 |    6 
 vivified/code/vivi_code_concat.c                                   |   23 
 vivified/code/vivi_code_enumerate.c                                |  232 +++
 vivified/code/vivi_code_enumerate.h                                |   66 
 vivified/code/vivi_code_function.c                                 |   21 
 vivified/code/vivi_code_function_call.c                            |   18 
 vivified/code/vivi_code_function_declaration.c                     |    6 
 vivified/code/vivi_code_get.c                                      |   22 
 vivified/code/vivi_code_get.h                                      |    3 
 vivified/code/vivi_code_get_url.c                                  |    6 
 vivified/code/vivi_code_goto.c                                     |    6 
 vivified/code/vivi_code_if.c                                       |   24 
 vivified/code/vivi_code_inc_dec.c                                  |  269 +++
 vivified/code/vivi_code_inc_dec.h                                  |   66 
 vivified/code/vivi_code_init_array.c                               |   26 
 vivified/code/vivi_code_init_object.c                              |   20 
 vivified/code/vivi_code_label.c                                    |    7 
 vivified/code/vivi_code_loop.c                                     |   40 
 vivified/code/vivi_code_loop.h                                     |    4 
 vivified/code/vivi_code_null.c                                     |   13 
 vivified/code/vivi_code_number.c                                   |   18 
 vivified/code/vivi_code_or.c                                       |   27 
 vivified/code/vivi_code_printer.c                                  |   13 
 vivified/code/vivi_code_return.c                                   |    8 
 vivified/code/vivi_code_string.c                                   |   18 
 vivified/code/vivi_code_substring.c                                |   24 
 vivified/code/vivi_code_throw.c                                    |    6 
 vivified/code/vivi_code_unary.c                                    |   19 
 vivified/code/vivi_code_undefined.c                                |   15 
 vivified/code/vivi_code_value.c                                    |   27 
 vivified/code/vivi_code_value.h                                    |   13 
 vivified/code/vivi_code_value_statement.c                          |  103 -
 vivified/code/vivi_code_value_statement.h                          |   59 
 vivified/code/vivi_code_variable.c                                 |  152 ++
 vivified/code/vivi_code_variable.h                                 |   62 
 vivified/code/vivi_decompiler.c                                    |   39 
 vivified/code/vivi_decompiler_block.c                              |    4 
 vivified/code/vivi_parser.c                                        |  690 +++-------
 vivified/code/vivi_parser_scanner.c                                |    4 
 vivified/code/vivi_parser_scanner.h                                |    4 
 vivified/code/vivi_parser_scanner_lex.l                            |    6 
 98 files changed, 2377 insertions(+), 1005 deletions(-)

New commits:
commit 12fb26f53baf7af0f3a88a24a282146c20ad8e57
Merge: f9d04e0... 9cb9548...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun May 18 19:58:23 2008 +0300

    Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec

commit f9d04e0b823eb21e8e9f489c4e7ff8f60b76893b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 19:41:54 2008 +0300

    Rename vivi-compile's for test to for_local and add new for test

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index f275bc5..84445fa 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -62,6 +62,8 @@ EXTRA_DIST = \
 	enumerate_member.as.expect \
 	for.as \
 	for.as.expect \
+	for_local.as \
+	for_local.as.expect \
 	function_declaration.as \
 	function_declaration.as.expect \
 	function_expression.as \
diff --git a/vivified/code/test/compiler/for.as b/vivified/code/test/compiler/for.as
index fd88467..bd1919f 100644
--- a/vivified/code/test/compiler/for.as
+++ b/vivified/code/test/compiler/for.as
@@ -1,3 +1,3 @@
-for (var i = 0; i < 5; i++) {
+for (i = 0; i < 5; i++) {
   play ();
 }
diff --git a/vivified/code/test/compiler/for.as.expect b/vivified/code/test/compiler/for.as.expect
index 63ffb69..bee691c 100644
--- a/vivified/code/test/compiler/for.as.expect
+++ b/vivified/code/test/compiler/for.as.expect
@@ -1,7 +1,7 @@
 asm {
   pool "i"
   push pool 0, 0
-  define_local
+  set_variable
 
 loop_start_0001:
   push pool 0
diff --git a/vivified/code/test/compiler/for_local.as b/vivified/code/test/compiler/for_local.as
new file mode 100644
index 0000000..fd88467
--- /dev/null
+++ b/vivified/code/test/compiler/for_local.as
@@ -0,0 +1,3 @@
+for (var i = 0; i < 5; i++) {
+  play ();
+}
diff --git a/vivified/code/test/compiler/for_local.as.expect b/vivified/code/test/compiler/for_local.as.expect
new file mode 100644
index 0000000..63ffb69
--- /dev/null
+++ b/vivified/code/test/compiler/for_local.as.expect
@@ -0,0 +1,23 @@
+asm {
+  pool "i"
+  push pool 0, 0
+  define_local
+
+loop_start_0001:
+  push pool 0
+  get_variable
+  push 5
+  less2
+  not
+  if loop_end_0002
+  play
+  push pool 0
+  push_duplicate
+  get_variable
+  increment
+  set_variable
+  jump loop_start_0001
+
+loop_end_0002:
+  end
+}
commit 37c4ad9e630eb2043de774405dcdf2970bad5ea9
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 19:37:37 2008 +0300

    Add support for post conditions for ViviCodeLoop, and use it for do while loops
    
    Added a vivi-compile test for do while

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 42e3529..f275bc5 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -46,6 +46,8 @@ EXTRA_DIST = \
 	comment.as.expect \
 	decrement.as \
 	decrement.as.expect \
+	do_while.as \
+	do_while.as.expect \
 	empty.as \
 	empty.as.expect \
 	empty_block.as \
diff --git a/vivified/code/test/compiler/do_while.as b/vivified/code/test/compiler/do_while.as
new file mode 100644
index 0000000..5b078db
--- /dev/null
+++ b/vivified/code/test/compiler/do_while.as
@@ -0,0 +1,3 @@
+do {
+  play ();
+} while (a);
diff --git a/vivified/code/test/compiler/do_while.as.expect b/vivified/code/test/compiler/do_while.as.expect
new file mode 100644
index 0000000..f9de291
--- /dev/null
+++ b/vivified/code/test/compiler/do_while.as.expect
@@ -0,0 +1,10 @@
+asm {
+  pool "a"
+
+loop_start_0001:
+  play
+  push pool 0
+  get_variable
+  if loop_start_0001
+  end
+}
diff --git a/vivified/code/vivi_code_loop.c b/vivified/code/vivi_code_loop.c
index fc6b77f..61f969a 100644
--- a/vivified/code/vivi_code_loop.c
+++ b/vivified/code/vivi_code_loop.c
@@ -84,22 +84,33 @@ vivi_code_loop_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   label_start = vivi_code_compiler_create_label (compiler, "loop_start");
   vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_start));
 
+  if (loop->post_condition && loop->statement)
+    vivi_code_compiler_compile_statement (compiler, loop->statement);
+
   if (loop->condition) {
     vivi_code_compiler_compile_value (compiler, loop->condition);
 
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
-
-    label_end = vivi_code_compiler_create_label (compiler, "loop_end");
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_if_new (label_end));
+    if (!loop->post_condition) {
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
+      label_end = vivi_code_compiler_create_label (compiler, "loop_end");
+      vivi_code_compiler_take_code (compiler,
+	  vivi_code_asm_if_new (label_end));
+    }
   }
 
-  if (loop->statement)
+  if (!loop->post_condition && loop->statement)
     vivi_code_compiler_compile_statement (compiler, loop->statement);
 
-  vivi_code_compiler_take_code (compiler, vivi_code_asm_jump_new (label_start));
+  if (loop->post_condition) {
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_if_new (label_start));
+  } else {
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_jump_new (label_start));
+  }
   g_object_unref (label_start);
 
-  if (loop->condition)
+  if (loop->condition && !loop->post_condition)
     vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
 }
 
@@ -127,7 +138,8 @@ vivi_code_loop_new (void)
 }
 
 void
-vivi_code_loop_set_condition (ViviCodeLoop *loop, ViviCodeValue *condition)
+vivi_code_loop_set_condition (ViviCodeLoop *loop, ViviCodeValue *condition,
+    gboolean post_condition)
 {
   g_return_if_fail (VIVI_IS_CODE_LOOP (loop));
   g_return_if_fail (VIVI_IS_CODE_VALUE (condition));
@@ -137,6 +149,7 @@ vivi_code_loop_set_condition (ViviCodeLoop *loop, ViviCodeValue *condition)
   if (loop->condition)
     g_object_unref (loop->condition);
   loop->condition = condition;
+  loop->post_condition = post_condition;
 }
 
 void
diff --git a/vivified/code/vivi_code_loop.h b/vivified/code/vivi_code_loop.h
index 1453f9a..7a1a15d 100644
--- a/vivified/code/vivi_code_loop.h
+++ b/vivified/code/vivi_code_loop.h
@@ -41,6 +41,7 @@ struct _ViviCodeLoop
   ViviCodeStatement	parent;
 
   ViviCodeValue *	condition;
+  gboolean		post_condition;
   ViviCodeStatement *	statement;
 };
 
@@ -53,7 +54,8 @@ GType			vivi_code_loop_get_type   	(void);
 
 ViviCodeStatement *	vivi_code_loop_new		(void);
 void			vivi_code_loop_set_condition	(ViviCodeLoop *		loop,
-							 ViviCodeValue *	condition);
+							 ViviCodeValue *	condition,
+							 gboolean		post_condition);
 void			vivi_code_loop_set_statement	(ViviCodeLoop *		loop,
 							 ViviCodeStatement *	statement);
 
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index a8d383c..9412807 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -1351,11 +1351,11 @@ vivi_decompiler_merge_loops (GList **list)
 	value = vivi_code_unary_new (vivi_decompiler_block_get_branch_condition (start), '!');
 	opt = vivi_code_value_optimize (value, SWFDEC_AS_TYPE_BOOLEAN);
 	g_object_unref (value);
-	vivi_code_loop_set_condition (VIVI_CODE_LOOP (loop), opt);
+	vivi_code_loop_set_condition (VIVI_CODE_LOOP (loop), opt, FALSE);
 	g_object_unref (opt);
       } else {
 	vivi_code_loop_set_condition (VIVI_CODE_LOOP (loop), 
-	    vivi_decompiler_block_get_branch_condition (start));
+	    vivi_decompiler_block_get_branch_condition (start), FALSE);
 	vivi_decompiler_block_set_next (start,
 	    vivi_decompiler_block_get_branch (start));
       }
@@ -1376,7 +1376,7 @@ vivi_decompiler_merge_loops (GList **list)
 	value = vivi_code_unary_new (vivi_decompiler_block_get_branch_condition (start), '!');
 	opt = vivi_code_value_optimize (value, SWFDEC_AS_TYPE_BOOLEAN);
 	g_object_unref (value);
-	vivi_code_loop_set_condition (VIVI_CODE_LOOP (loop), opt);
+	vivi_code_loop_set_condition (VIVI_CODE_LOOP (loop), opt, FALSE);
 	g_object_unref (opt);
 	vivi_decompiler_block_set_next (block, vivi_decompiler_block_get_branch (start));
 	vivi_decompiler_block_set_branch (start, NULL, NULL);
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index ff25720..2db3047 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -2403,7 +2403,7 @@ parse_iteration_statement (ParseData *data)
   ViviCodeValue *condition, *enumerate_variable;
   ViviCodeStatement *statement;
   ViviCodeStatement *pre_statement, *loop_statement;
-  gboolean enumerate, enumerate_local;
+  gboolean post_condition, enumerate, enumerate_local;
 
   enumerate = FALSE;
   enumerate_local = FALSE;
@@ -2415,15 +2415,17 @@ parse_iteration_statement (ParseData *data)
     parse_token (data, TOKEN_WHILE);
     parse_token (data, TOKEN_PARENTHESIS_LEFT);
     condition = parse_expression (data);
+    post_condition = TRUE;
     parse_token (data, TOKEN_PARENTHESIS_RIGHT);
     parse_automatic_semicolon (data);
 
-    pre_statement = g_object_ref (loop_statement);
+    pre_statement = NULL;
   }
   else if (try_parse_token (data, TOKEN_WHILE))
   {
     parse_token (data, TOKEN_PARENTHESIS_LEFT);
     condition = parse_expression (data);
+    post_condition = FALSE;
     parse_token (data, TOKEN_PARENTHESIS_RIGHT);
     loop_statement = parse_statement (data);
 
@@ -2470,8 +2472,10 @@ parse_iteration_statement (ParseData *data)
 
       if (try_parse_token (data, TOKEN_SEMICOLON)) {
 	condition = vivi_code_boolean_new (TRUE);
+	post_condition = FALSE;
       } else {
 	condition = parse_expression (data);
+	post_condition = FALSE;
 	parse_token (data, TOKEN_SEMICOLON);
       }
 
@@ -2493,6 +2497,7 @@ parse_iteration_statement (ParseData *data)
       }
 
       condition = parse_expression (data);
+      post_condition = FALSE;
       post_statement = NULL;
       enumerate = TRUE;
     } else {
@@ -2506,6 +2511,7 @@ parse_iteration_statement (ParseData *data)
       }
 
       condition = vivi_code_undefined_new ();
+      post_condition = FALSE;
       post_statement = NULL;
 
       if (enumerate_variable != NULL)
@@ -2533,13 +2539,15 @@ parse_iteration_statement (ParseData *data)
 
     enumerate = FALSE;
     condition = vivi_code_undefined_new ();
+    post_condition = FALSE;
     pre_statement = NULL;
     loop_statement = vivi_compiler_empty_statement_new ();
   }
 
   if (enumerate) {
-    g_assert (pre_statement == NULL);
     g_assert (VIVI_IS_CODE_GET (enumerate_variable));
+    g_assert (pre_statement == NULL);
+    g_assert (post_condition == FALSE);
 
     statement = vivi_code_enumerate_new (condition,
 	VIVI_CODE_GET (enumerate_variable)->from,
@@ -2550,13 +2558,12 @@ parse_iteration_statement (ParseData *data)
   }
 
   statement = vivi_code_loop_new ();
-  vivi_code_loop_set_condition (VIVI_CODE_LOOP (statement), condition);
+  vivi_code_loop_set_condition (VIVI_CODE_LOOP (statement), condition,
+      post_condition);
   g_object_unref (condition);
   vivi_code_loop_set_statement (VIVI_CODE_LOOP (statement), loop_statement);
   g_object_unref (loop_statement);
 
-  // can't use join_statements here
-  // because we don't want to put statement inside pre_statement
   if (pre_statement != NULL) {
     ViviCodeStatement *block = vivi_code_block_new ();
     vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), pre_statement);
commit 7e53005d7519e16c1d6611dbcc02f192768a15ac
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 17:52:39 2008 +0300

    Add some vivi-compile tests for enumerate loops

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 98e7c5f..42e3529 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -52,6 +52,12 @@ EXTRA_DIST = \
 	empty_block.as.expect \
 	empty_statement.as \
 	empty_statement.as.expect \
+	enumerate.as \
+	enumerate.as.expect \
+	enumerate_local.as \
+	enumerate_local.as.expect \
+	enumerate_member.as \
+	enumerate_member.as.expect \
 	for.as \
 	for.as.expect \
 	function_declaration.as \
diff --git a/vivified/code/test/compiler/enumerate.as b/vivified/code/test/compiler/enumerate.as
new file mode 100644
index 0000000..5427be6
--- /dev/null
+++ b/vivified/code/test/compiler/enumerate.as
@@ -0,0 +1,3 @@
+for (x in a) {
+  trace (x);
+}
diff --git a/vivified/code/test/compiler/enumerate.as.expect b/vivified/code/test/compiler/enumerate.as.expect
new file mode 100644
index 0000000..5f52248
--- /dev/null
+++ b/vivified/code/test/compiler/enumerate.as.expect
@@ -0,0 +1,23 @@
+asm {
+  pool "a", "x"
+  push pool 0
+  get_variable
+  enumerate2
+
+enumerate_start_0001:
+  push_duplicate
+  push null
+  equals2
+  if enumerate_end_0002
+  push pool 1
+  swap
+  set_variable
+  push pool 1
+  get_variable
+  trace
+  jump enumerate_start_0001
+
+enumerate_end_0002:
+  pop
+  end
+}
diff --git a/vivified/code/test/compiler/enumerate_local.as b/vivified/code/test/compiler/enumerate_local.as
new file mode 100644
index 0000000..2d145b1
--- /dev/null
+++ b/vivified/code/test/compiler/enumerate_local.as
@@ -0,0 +1,3 @@
+for (var x in a) {
+  trace (x);
+}
diff --git a/vivified/code/test/compiler/enumerate_local.as.expect b/vivified/code/test/compiler/enumerate_local.as.expect
new file mode 100644
index 0000000..ec65002
--- /dev/null
+++ b/vivified/code/test/compiler/enumerate_local.as.expect
@@ -0,0 +1,23 @@
+asm {
+  pool "a", "x"
+  push pool 0
+  get_variable
+  enumerate2
+
+enumerate_start_0001:
+  push_duplicate
+  push null
+  equals2
+  if enumerate_end_0002
+  push pool 1
+  swap
+  define_local
+  push pool 1
+  get_variable
+  trace
+  jump enumerate_start_0001
+
+enumerate_end_0002:
+  pop
+  end
+}
diff --git a/vivified/code/test/compiler/enumerate_member.as b/vivified/code/test/compiler/enumerate_member.as
new file mode 100644
index 0000000..7c87c63
--- /dev/null
+++ b/vivified/code/test/compiler/enumerate_member.as
@@ -0,0 +1,6 @@
+for (x.y in a) {
+  trace (x.y);
+}
+for (x[y] in a) {
+  trace (x[y]);
+}
diff --git a/vivified/code/test/compiler/enumerate_member.as.expect b/vivified/code/test/compiler/enumerate_member.as.expect
new file mode 100644
index 0000000..7843030
--- /dev/null
+++ b/vivified/code/test/compiler/enumerate_member.as.expect
@@ -0,0 +1,49 @@
+asm {
+  pool "a", "x", "y"
+  push pool 0
+  get_variable
+  enumerate2
+
+enumerate_start_0001:
+  store 0
+  push null
+  equals2
+  if enumerate_end_0002
+  push pool 1
+  get_variable
+  push pool 2, reg 0
+  set_member
+  push pool 1
+  get_variable
+  push pool 2
+  get_member
+  trace
+  jump enumerate_start_0001
+
+enumerate_end_0002:
+  push pool 0
+  get_variable
+  enumerate2
+
+enumerate_start_0003:
+  store 0
+  push null
+  equals2
+  if enumerate_end_0004
+  push pool 1
+  get_variable
+  push pool 2
+  get_variable
+  push reg 0
+  set_member
+  push pool 1
+  get_variable
+  push pool 2
+  get_variable
+  get_member
+  trace
+  jump enumerate_start_0003
+
+enumerate_end_0004:
+  end
+}
commit ff5f50e2e83988d5bafac26c2836217497113059
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 17:47:23 2008 +0300

    Fix assert and not freed reference in ViviCodeEnumerate

diff --git a/vivified/code/vivi_code_enumerate.c b/vivified/code/vivi_code_enumerate.c
index f4e7f87..03b20f0 100644
--- a/vivified/code/vivi_code_enumerate.c
+++ b/vivified/code/vivi_code_enumerate.c
@@ -41,6 +41,8 @@ vivi_code_enumerate_dispose (GObject *object)
   ViviCodeEnumerate *enumerate = VIVI_CODE_ENUMERATE (object);
 
   g_object_unref (enumerate->target);
+  if (enumerate->from)
+    g_object_unref (enumerate->from);
   g_object_unref (enumerate->name);
   if (enumerate->statement)
     g_object_unref (enumerate->statement);
@@ -206,7 +208,8 @@ vivi_code_enumerate_new (ViviCodeValue *target, ViviCodeValue *from,
   enumerate = g_object_new (VIVI_TYPE_CODE_ENUMERATE, NULL);
 
   enumerate->target = g_object_ref (target);
-  enumerate->from = g_object_ref (from);
+  if (from != NULL)
+    enumerate->from = g_object_ref (from);
   enumerate->name = g_object_ref (name);
   enumerate->local = local;
 
commit 9ca7645826c1a6ccb8360f2ac57c175f97f81809
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 17:44:01 2008 +0300

    Fix printing of variable names in ViviCodeEnumerate

diff --git a/vivified/code/vivi_code_enumerate.c b/vivified/code/vivi_code_enumerate.c
index 7d7ced2..f4e7f87 100644
--- a/vivified/code/vivi_code_enumerate.c
+++ b/vivified/code/vivi_code_enumerate.c
@@ -53,17 +53,45 @@ vivi_code_enumerate_print (ViviCodeToken *token, ViviCodePrinter *printer)
 {
   ViviCodeEnumerate *enumerate= VIVI_CODE_ENUMERATE (token);
   gboolean needs_braces;
+  char *varname;
 
   needs_braces = enumerate->statement &&
     vivi_code_statement_needs_braces (enumerate->statement);
 
-  // FIXME: member
-
   vivi_code_printer_print (printer, "while (");
-  if (enumerate->local)
-    vivi_code_printer_print (printer, "var ");
-  vivi_code_printer_print_value (printer, enumerate->name,
-      VIVI_PRECEDENCE_MIN);
+
+  // FIXME: duplicated code from ViviAssignment
+  if (VIVI_IS_CODE_CONSTANT (enumerate->name)) {
+    varname = vivi_code_constant_get_variable_name (
+	VIVI_CODE_CONSTANT (enumerate->name));
+  } else {
+    varname = NULL;
+  }
+
+  if (enumerate->from) {
+    g_assert (enumerate->local == FALSE);
+    vivi_code_printer_print_value (printer, enumerate->from,
+	VIVI_PRECEDENCE_MEMBER);
+    if (varname) {
+      vivi_code_printer_print (printer, ".");
+      vivi_code_printer_print (printer, varname);
+    } else {
+      vivi_code_printer_print (printer, "[");
+      vivi_code_printer_print_value (printer, enumerate->name,
+	  VIVI_PRECEDENCE_MIN);
+      vivi_code_printer_print (printer, "]");
+    }
+  } else {
+    if (enumerate->local)
+      vivi_code_printer_print (printer, "var ");
+    if (varname) {
+      vivi_code_printer_print (printer, varname);
+    } else {
+      // FIXME
+      g_assert_not_reached ();
+    }
+  }
+
   vivi_code_printer_print (printer, " in ");
   vivi_code_printer_print_value (printer, enumerate->target,
       VIVI_PRECEDENCE_MIN);
commit 3007b5fb96943076c8d57c901dc34313ed4b855c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 17:39:16 2008 +0300

    Implement compilation of the for/in statements (enumeration)

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index d18ddc3..89e09ec 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -60,6 +60,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_constant.c \
 	vivi_code_continue.c \
 	vivi_code_emitter.c \
+	vivi_code_enumerate.c \
 	vivi_code_error.c \
 	vivi_code_function.c \
 	vivi_code_function_call.c \
@@ -137,6 +138,7 @@ noinst_HEADERS = \
 	vivi_code_continue.h \
 	vivi_code_defaults.h \
 	vivi_code_emitter.h \
+	vivi_code_enumerate.h \
 	vivi_code_error.h \
 	vivi_code_function.h \
 	vivi_code_function_call.h \
diff --git a/vivified/code/vivi_code_enumerate.c b/vivified/code/vivi_code_enumerate.c
new file mode 100644
index 0000000..7d7ced2
--- /dev/null
+++ b/vivified/code/vivi_code_enumerate.c
@@ -0,0 +1,201 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_code_enumerate.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_get.h"
+#include "vivi_code_string.h"
+#include "vivi_code_compiler.h"
+#include "vivi_code_label.h"
+#include "vivi_code_asm_if.h"
+#include "vivi_code_asm_jump.h"
+#include "vivi_code_asm_push.h"
+#include "vivi_code_asm_store.h"
+#include "vivi_code_asm_code_default.h"
+
+G_DEFINE_TYPE (ViviCodeEnumerate, vivi_code_enumerate, VIVI_TYPE_CODE_STATEMENT)
+
+static void
+vivi_code_enumerate_dispose (GObject *object)
+{
+  ViviCodeEnumerate *enumerate = VIVI_CODE_ENUMERATE (object);
+
+  g_object_unref (enumerate->target);
+  g_object_unref (enumerate->name);
+  if (enumerate->statement)
+    g_object_unref (enumerate->statement);
+
+  G_OBJECT_CLASS (vivi_code_enumerate_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_enumerate_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  ViviCodeEnumerate *enumerate= VIVI_CODE_ENUMERATE (token);
+  gboolean needs_braces;
+
+  needs_braces = enumerate->statement &&
+    vivi_code_statement_needs_braces (enumerate->statement);
+
+  // FIXME: member
+
+  vivi_code_printer_print (printer, "while (");
+  if (enumerate->local)
+    vivi_code_printer_print (printer, "var ");
+  vivi_code_printer_print_value (printer, enumerate->name,
+      VIVI_PRECEDENCE_MIN);
+  vivi_code_printer_print (printer, " in ");
+  vivi_code_printer_print_value (printer, enumerate->target,
+      VIVI_PRECEDENCE_MIN);
+  vivi_code_printer_print (printer, ")");
+
+  if (needs_braces)
+    vivi_code_printer_print (printer, " {");
+  vivi_code_printer_new_line (printer, FALSE);
+  vivi_code_printer_push_indentation (printer);
+
+  if (enumerate->statement) {
+    vivi_code_printer_print_token (printer,
+	VIVI_CODE_TOKEN (enumerate->statement));
+  } else {
+    vivi_code_printer_print (printer, ";");
+  }
+
+  vivi_code_printer_pop_indentation (printer);
+  if (needs_braces) {
+    vivi_code_printer_print (printer, "}");
+    vivi_code_printer_new_line (printer, FALSE);
+  }
+}
+
+static void
+vivi_code_enumerate_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+{
+  ViviCodeEnumerate *enumerate = VIVI_CODE_ENUMERATE (token);
+  ViviCodeLabel *label_start, *label_end = NULL;
+  ViviCodeAsm *push;
+
+  vivi_code_compiler_compile_value (compiler, enumerate->target);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_enumerate2_new ());
+
+  label_start = vivi_code_compiler_create_label (compiler, "enumerate_start");
+  vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_start));
+
+  if (enumerate->from) {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+  } else {
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_push_duplicate_new ());
+  }
+  push = vivi_code_asm_push_new ();
+  vivi_code_asm_push_add_null (VIVI_CODE_ASM_PUSH (push));
+  vivi_code_compiler_take_code (compiler, push);
+
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_equals2_new ());
+  label_end = vivi_code_compiler_create_label (compiler, "enumerate_end");
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_if_new (label_end));
+
+  if (enumerate->from) {
+    vivi_code_compiler_compile_value (compiler, enumerate->from);
+    vivi_code_compiler_compile_value (compiler, enumerate->name);
+    push = vivi_code_asm_push_new ();
+    vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+    vivi_code_compiler_take_code (compiler, push);
+    g_assert (enumerate->local == FALSE);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
+  } else {
+    vivi_code_compiler_compile_value (compiler, enumerate->name);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
+    if (enumerate->local) {
+      vivi_code_compiler_take_code (compiler,
+	  vivi_code_asm_define_local_new ());
+    } else {
+      vivi_code_compiler_take_code (compiler,
+	  vivi_code_asm_set_variable_new ());
+    }
+  }
+
+  if (enumerate->statement)
+    vivi_code_compiler_compile_statement (compiler, enumerate->statement);
+
+  vivi_code_compiler_take_code (compiler,
+      vivi_code_asm_jump_new (label_start));
+  g_object_unref (label_start);
+
+  vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
+  if (!enumerate->from)
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_pop_new ());
+}
+
+static void
+vivi_code_enumerate_class_init (ViviCodeEnumerateClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+
+  object_class->dispose = vivi_code_enumerate_dispose;
+
+  token_class->print = vivi_code_enumerate_print;
+  token_class->compile = vivi_code_enumerate_compile;
+}
+
+static void
+vivi_code_enumerate_init (ViviCodeEnumerate *token)
+{
+}
+
+ViviCodeStatement *
+vivi_code_enumerate_new (ViviCodeValue *target, ViviCodeValue *from,
+    ViviCodeValue *name, gboolean local)
+{
+  ViviCodeEnumerate *enumerate;
+
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (target), NULL);
+  g_return_val_if_fail (from == NULL || VIVI_IS_CODE_VALUE (from), NULL);
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (name), NULL);
+  g_return_val_if_fail (local == FALSE || from == NULL, NULL);
+
+  enumerate = g_object_new (VIVI_TYPE_CODE_ENUMERATE, NULL);
+
+  enumerate->target = g_object_ref (target);
+  enumerate->from = g_object_ref (from);
+  enumerate->name = g_object_ref (name);
+  enumerate->local = local;
+
+  return VIVI_CODE_STATEMENT (enumerate);
+}
+
+void
+vivi_code_enumerate_set_statement (ViviCodeEnumerate *enumerate,
+    ViviCodeStatement *statement)
+{
+  g_return_if_fail (VIVI_IS_CODE_ENUMERATE (enumerate));
+  g_return_if_fail (VIVI_IS_CODE_STATEMENT (statement));
+
+  if (statement)
+    g_object_ref (statement);
+  if (enumerate->statement)
+    g_object_unref (enumerate->statement);
+  enumerate->statement = statement;
+}
+
diff --git a/vivified/code/vivi_code_enumerate.h b/vivified/code/vivi_code_enumerate.h
new file mode 100644
index 0000000..ccd02c9
--- /dev/null
+++ b/vivified/code/vivi_code_enumerate.h
@@ -0,0 +1,66 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_CODE_ENUMERATE_H_
+#define _VIVI_CODE_ENUMERATE_H_
+
+#include <vivified/code/vivi_code_statement.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeEnumerate ViviCodeEnumerate;
+typedef struct _ViviCodeEnumerateClass ViviCodeEnumerateClass;
+
+#define VIVI_TYPE_CODE_ENUMERATE                    (vivi_code_enumerate_get_type())
+#define VIVI_IS_CODE_ENUMERATE(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_ENUMERATE))
+#define VIVI_IS_CODE_ENUMERATE_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_ENUMERATE))
+#define VIVI_CODE_ENUMERATE(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_ENUMERATE, ViviCodeEnumerate))
+#define VIVI_CODE_ENUMERATE_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_ENUMERATE, ViviCodeEnumerateClass))
+#define VIVI_CODE_ENUMERATE_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_ENUMERATE, ViviCodeEnumerateClass))
+
+struct _ViviCodeEnumerate
+{
+  ViviCodeStatement	parent;
+
+  ViviCodeValue *	target;
+  ViviCodeValue *	from;
+  ViviCodeValue *	name;
+  gboolean		local;
+  ViviCodeStatement *	statement;
+};
+
+struct _ViviCodeEnumerateClass
+{
+  ViviCodeStatementClass	statement_class;
+};
+
+GType			vivi_code_enumerate_get_type		(void);
+
+ViviCodeStatement *	vivi_code_enumerate_new			(ViviCodeValue *		target,
+								 ViviCodeValue *		from,
+								 ViviCodeValue *		name,
+								 gboolean			local);
+void			vivi_code_enumerate_set_statement	(ViviCodeEnumerate *		enumerate,
+								 ViviCodeStatement *		statement);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index e390a4c..ff25720 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -42,6 +42,7 @@
 #include "vivi_code_concat.h"
 #include "vivi_code_constant.h"
 #include "vivi_code_continue.h"
+#include "vivi_code_enumerate.h"
 #include "vivi_code_function.h"
 #include "vivi_code_function_call.h"
 #include "vivi_code_function_declaration.h"
@@ -2399,9 +2400,14 @@ peek_iteration_statement (ParseData *data)
 static ViviCodeStatement *
 parse_iteration_statement (ParseData *data)
 {
-  ViviCodeValue *condition;
+  ViviCodeValue *condition, *enumerate_variable;
   ViviCodeStatement *statement;
   ViviCodeStatement *pre_statement, *loop_statement;
+  gboolean enumerate, enumerate_local;
+
+  enumerate = FALSE;
+  enumerate_local = FALSE;
+  enumerate_variable = NULL;
 
   if (try_parse_token (data, TOKEN_DO))
   {
@@ -2425,7 +2431,6 @@ parse_iteration_statement (ParseData *data)
   }
   else if (try_parse_token (data, TOKEN_FOR))
   {
-    ViviCodeValue *pre_value;
     ViviCodeStatement *post_statement;
 
     parse_token (data, TOKEN_PARENTHESIS_LEFT);
@@ -2434,31 +2439,34 @@ parse_iteration_statement (ParseData *data)
       // FIXME: no in
       pre_statement = parse_statement_list (data, peek_variable_declaration,
 	  parse_variable_declaration, TOKEN_COMMA);
-      // FIXME: ugly
-      // If there was only one VariableDeclaration, get the name for pre_value
+      // FIXME: ugly... if there was only one VariableDeclaration,
+      // get the name for enumerate_variable
       g_assert (VIVI_IS_CODE_BLOCK (pre_statement));
       if (vivi_code_block_get_n_statements (VIVI_CODE_BLOCK (pre_statement))
 	  == 1) {
 	ViviCodeVariable *variable = VIVI_CODE_VARIABLE (
 	    vivi_code_block_get_statement (VIVI_CODE_BLOCK (pre_statement), 0));
-	pre_value = vivi_code_get_new (NULL, variable->name);
+	enumerate_variable = vivi_code_get_new (NULL, variable->name);
+	enumerate_local = TRUE;
       } else {
-	pre_value = NULL;
+	enumerate_variable = NULL;
       }
     } else {
       if (try_parse_token (data, TOKEN_SEMICOLON)) {
-	pre_value = NULL;
+	enumerate_variable = NULL;
 	pre_statement = NULL;
       } else {
 	// FIXME: no in
-	pre_value = parse_expression (data);
-	pre_statement = NULL;
+	enumerate_variable = parse_expression (data);
+	enumerate_local = FALSE;
+	pre_statement =
+	  g_object_ref (VIVI_CODE_STATEMENT (enumerate_variable));
       }
     }
 
     if (try_parse_token (data, TOKEN_SEMICOLON)) {
-      if (pre_value != NULL)
-	g_object_unref (pre_value);
+      if (enumerate_variable != NULL)
+	g_object_unref (enumerate_variable);
 
       if (try_parse_token (data, TOKEN_SEMICOLON)) {
 	condition = vivi_code_boolean_new (TRUE);
@@ -2472,21 +2480,25 @@ parse_iteration_statement (ParseData *data)
       } else {
 	post_statement = NULL;
       }
-    } else if (pre_value != NULL && try_parse_token (data, TOKEN_IN)) {
+    } else if (enumerate_variable != NULL && try_parse_token (data, TOKEN_IN)) {
       // FIXME: correct?
-      if (!vivi_parser_value_is_left_hand_side (pre_value))
+      if (!vivi_parser_value_is_left_hand_side (enumerate_variable)) {
 	vivi_parser_error (data, "Invalid left-hand side expression for in");
+	enumerate_variable = vivi_code_string_new ("undefined");
+      }
 
-      g_object_unref (pre_value);
-      if (pre_statement != NULL)
+      if (pre_statement != NULL) {
 	g_object_unref (pre_statement);
+	pre_statement = NULL;
+      }
 
-      vivi_parser_error (data, "for (... in ...) has not been implemented yet");
-
-      condition = vivi_code_undefined_new ();
+      condition = parse_expression (data);
       post_statement = NULL;
+      enumerate = TRUE;
     } else {
-      if (pre_value != NULL) {
+      enumerate = FALSE;
+
+      if (enumerate_variable != NULL) {
 	vivi_parser_error_unexpected_or (data, TOKEN_SEMICOLON, TOKEN_IN,
 	    TOKEN_NONE);
       } else {
@@ -2496,8 +2508,8 @@ parse_iteration_statement (ParseData *data)
       condition = vivi_code_undefined_new ();
       post_statement = NULL;
 
-      if (pre_value != NULL)
-	g_object_unref (pre_value);
+      if (enumerate_variable != NULL)
+	g_object_unref (enumerate_variable);
       if (pre_statement != NULL)
 	g_object_unref (pre_statement);
     }
@@ -2519,11 +2531,24 @@ parse_iteration_statement (ParseData *data)
   {
     vivi_parser_error_unexpected (data, ERROR_TOKEN_ITERATION_STATEMENT);
 
+    enumerate = FALSE;
     condition = vivi_code_undefined_new ();
     pre_statement = NULL;
     loop_statement = vivi_compiler_empty_statement_new ();
   }
 
+  if (enumerate) {
+    g_assert (pre_statement == NULL);
+    g_assert (VIVI_IS_CODE_GET (enumerate_variable));
+
+    statement = vivi_code_enumerate_new (condition,
+	VIVI_CODE_GET (enumerate_variable)->from,
+	VIVI_CODE_GET (enumerate_variable)->name, enumerate_local);
+    vivi_code_enumerate_set_statement (VIVI_CODE_ENUMERATE (statement),
+	loop_statement);
+    return statement;
+  }
+
   statement = vivi_code_loop_new ();
   vivi_code_loop_set_condition (VIVI_CODE_LOOP (statement), condition);
   g_object_unref (condition);
commit 4acc6aae0a2edff1bb7f510b157e1fbf7dc6c101
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 14:01:22 2008 +0300

    Rename TOKEN_EQUAL_OR_GREATER_THAN to TOKEN_GREATER_THAN_OR_EQUAL

diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 0350eec..e390a4c 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -1946,9 +1946,8 @@ parse_operator_expression (ParseData *data,
     { TOKEN_STRICT_EQUAL, vivi_code_strict_equals_new },
     { TOKEN_NOT_STRICT_EQUAL, vivi_code_strict_equals_new },
     { TOKEN_GREATER_THAN, vivi_code_greater_new },
-    { TOKEN_EQUAL_OR_GREATER_THAN, vivi_code_less2_new },
+    { TOKEN_GREATER_THAN_OR_EQUAL, vivi_code_less2_new },
     { TOKEN_INSTANCEOF, vivi_code_instance_of_new },
-//    { TOKEN_, vivi_code_string_greater_new },
     { TOKEN_LOGICAL_AND, vivi_code_and_new },
     { TOKEN_LOGICAL_OR, vivi_code_or_new }
   };
@@ -1977,7 +1976,7 @@ again:
 	if (tokens[i] == TOKEN_NOT_EQUAL ||
 	    tokens[i] == TOKEN_NOT_STRICT_EQUAL ||
 	    tokens[i] == TOKEN_LESS_THAN_OR_EQUAL ||
-	    tokens[i] == TOKEN_EQUAL_OR_GREATER_THAN) {
+	    tokens[i] == TOKEN_GREATER_THAN_OR_EQUAL) {
 	  left = vivi_code_unary_new (value, '!');
 	  g_object_unref (value);
 	  value = left;
@@ -2056,7 +2055,7 @@ parse_relational_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_LESS_THAN,
     TOKEN_GREATER_THAN, TOKEN_LESS_THAN_OR_EQUAL,
-    TOKEN_EQUAL_OR_GREATER_THAN, TOKEN_INSTANCEOF, /*TOKEN_IN,*/ TOKEN_NONE };
+    TOKEN_GREATER_THAN_OR_EQUAL, TOKEN_INSTANCEOF, /*TOKEN_IN,*/ TOKEN_NONE };
 
   return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_shift_expression);
diff --git a/vivified/code/vivi_parser_scanner.c b/vivified/code/vivi_parser_scanner.c
index 2cb8eff..dcbdb07 100644
--- a/vivified/code/vivi_parser_scanner.c
+++ b/vivified/code/vivi_parser_scanner.c
@@ -105,7 +105,7 @@ static const struct {
   { TOKEN_LESS_THAN, "<" },
   { TOKEN_GREATER_THAN, ">" },
   { TOKEN_LESS_THAN_OR_EQUAL, "<=" },
-  { TOKEN_EQUAL_OR_GREATER_THAN, ">=" },
+  { TOKEN_GREATER_THAN_OR_EQUAL, ">=" },
 
   // equality
   { TOKEN_EQUAL, "==" },
diff --git a/vivified/code/vivi_parser_scanner.h b/vivified/code/vivi_parser_scanner.h
index 3750052..8dd31b9 100644
--- a/vivified/code/vivi_parser_scanner.h
+++ b/vivified/code/vivi_parser_scanner.h
@@ -49,7 +49,7 @@ typedef enum {
   TOKEN_LESS_THAN,
   TOKEN_GREATER_THAN,
   TOKEN_LESS_THAN_OR_EQUAL,
-  TOKEN_EQUAL_OR_GREATER_THAN,
+  TOKEN_GREATER_THAN_OR_EQUAL,
 
   // equality
   TOKEN_EQUAL,
diff --git a/vivified/code/vivi_parser_scanner_lex.l b/vivified/code/vivi_parser_scanner_lex.l
index c99d836..ab3a99f 100644
--- a/vivified/code/vivi_parser_scanner_lex.l
+++ b/vivified/code/vivi_parser_scanner_lex.l
@@ -107,7 +107,7 @@ identifier_part		[$_a-zA-Z0-9]
 "<"			{ return TOKEN_LESS_THAN; }
 ">"			{ return TOKEN_GREATER_THAN; }
 "<="			{ return TOKEN_LESS_THAN_OR_EQUAL; }
-">="			{ return TOKEN_EQUAL_OR_GREATER_THAN; }
+">="			{ return TOKEN_GREATER_THAN_OR_EQUAL; }
 
 "=="			{ return TOKEN_EQUAL; }
 "!="			{ return TOKEN_NOT_EQUAL; }
commit a817a1e77c8c2cbac11f15ef71d8b6248bef5e6e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 11:50:51 2008 +0300

    Add an operator precedence test for vivi-compile

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 1afa7fb..98e7c5f 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -74,6 +74,8 @@ EXTRA_DIST = \
 	label.as.expect \
 	operator.as \
 	operator.as.expect \
+	operator_precedence.as \
+	operator_precedence.as.expect \
 	object_literal.as \
 	object_literal.as.expect \
 	object_literal_empty.as \
diff --git a/vivified/code/test/compiler/operator_precedence.as b/vivified/code/test/compiler/operator_precedence.as
new file mode 100644
index 0000000..dd72f22
--- /dev/null
+++ b/vivified/code/test/compiler/operator_precedence.as
@@ -0,0 +1,43 @@
+// equal precedence
+trace (1 == 2 != 3 === 4 !== 5);
+trace (1 !== 2 === 3 != 4 == 5);
+
+trace (1 < 2 > 3 <= 4 >= 5 instanceof a);
+trace (1 instanceof a >= 3 <= 4 > 5 < 6);
+
+trace (1 << 2 >> 3 >>> 4);
+trace (1 >>> 2 >> 3 << 4);
+
+trace (1 + 2 - 3);
+trace (1 - 2 + 3);
+
+trace (1 * 2 / 3 % 4);
+trace (1 % 2 / 3 * 4);
+
+// different precedence
+trace (1 && 2 || 3);
+trace (1 || 2 && 3);
+
+trace (1 | 2 && 3);
+trace (1 && 2 | 3);
+
+trace (1 ^ 2 | 3);
+trace (1 | 2 ^ 3);
+
+trace (1 & 2 ^ 3);
+trace (1 ^ 2 & 3);
+
+trace (1 == 2 & 3);
+trace (1 & 2 == 3);
+
+trace (1 < 2 == 3);
+trace (1 == 2 < 3);
+
+trace (1 << 2 < 3);
+trace (1 < 2 << 3);
+
+trace (1 + 2 << 3);
+trace (1 << 2 + 3);
+
+trace (1 * 2 + 3);
+trace (1 + 2 * 3);
diff --git a/vivified/code/test/compiler/operator_precedence.as.expect b/vivified/code/test/compiler/operator_precedence.as.expect
new file mode 100644
index 0000000..44f85dc
--- /dev/null
+++ b/vivified/code/test/compiler/operator_precedence.as.expect
@@ -0,0 +1,205 @@
+asm {
+  pool "a"
+  push 1, 2
+  equals2
+  push 3
+  equals2
+  not
+  push 4
+  strict_equals
+  push 5
+  strict_equals
+  not
+  trace
+  push 1, 2
+  strict_equals
+  not
+  push 3
+  strict_equals
+  push 4
+  equals2
+  not
+  push 5
+  equals2
+  trace
+  push 1, 2
+  less2
+  push 3
+  greater
+  push 4
+  greater
+  not
+  push 5
+  less2
+  not
+  push pool 0
+  get_variable
+  instance_of
+  trace
+  push 1, pool 0
+  get_variable
+  instance_of
+  push 3
+  less2
+  not
+  push 4
+  greater
+  not
+  push 5
+  greater
+  push 6
+  less2
+  trace
+  push 1, 2
+  bit_lshift
+  push 3
+  bit_rshift
+  push 4
+  bit_urshift
+  trace
+  push 1, 2
+  bit_urshift
+  push 3
+  bit_rshift
+  push 4
+  bit_lshift
+  trace
+  push 1, 2
+  add2
+  push 3
+  subtract
+  trace
+  push 1, 2
+  subtract
+  push 3
+  add2
+  trace
+  push 1, 2
+  multiply
+  push 3
+  divide
+  push 4
+  modulo
+  trace
+  push 1, 2
+  modulo
+  push 3
+  divide
+  push 4
+  multiply
+  trace
+  push 1
+  push_duplicate
+  not
+  if and_end_0001
+  pop
+  push 2
+
+and_end_0001:
+  push_duplicate
+  if or_end_0002
+  pop
+  push 3
+
+or_end_0002:
+  trace
+  push 1
+  push_duplicate
+  if or_end_0003
+  pop
+  push 2
+  push_duplicate
+  not
+  if and_end_0004
+  pop
+  push 3
+
+and_end_0004:
+
+or_end_0003:
+  trace
+  push 1, 2
+  bit_or
+  push_duplicate
+  not
+  if and_end_0005
+  pop
+  push 3
+
+and_end_0005:
+  trace
+  push 1
+  push_duplicate
+  not
+  if and_end_0006
+  pop
+  push 2, 3
+  bit_or
+
+and_end_0006:
+  trace
+  push 1, 2
+  bit_xor
+  push 3
+  bit_or
+  trace
+  push 1, 2, 3
+  bit_xor
+  bit_or
+  trace
+  push 1, 2
+  bit_and
+  push 3
+  bit_xor
+  trace
+  push 1, 2, 3
+  bit_and
+  bit_xor
+  trace
+  push 1, 2
+  equals2
+  push 3
+  bit_and
+  trace
+  push 1, 2, 3
+  equals2
+  bit_and
+  trace
+  push 1, 2
+  less2
+  push 3
+  equals2
+  trace
+  push 1, 2, 3
+  less2
+  equals2
+  trace
+  push 1, 2
+  bit_lshift
+  push 3
+  less2
+  trace
+  push 1, 2, 3
+  bit_lshift
+  less2
+  trace
+  push 1, 2
+  add2
+  push 3
+  bit_lshift
+  trace
+  push 1, 2, 3
+  add2
+  bit_lshift
+  trace
+  push 1, 2
+  multiply
+  push 3
+  add2
+  trace
+  push 1, 2, 3
+  multiply
+  add2
+  trace
+  end
+}
commit 49fd56565932c8dbbcae9b519c383dd923210b66
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 16 11:38:50 2008 +0300

    Don't print extra lines at the end in the vivi-decompiler

diff --git a/vivified/code/decompiler.c b/vivified/code/decompiler.c
index a8ebf8f..a9cd6f6 100644
--- a/vivified/code/decompiler.c
+++ b/vivified/code/decompiler.c
@@ -74,7 +74,6 @@ decode_script (gpointer scriptp, gpointer use_asm)
   printer = vivi_code_text_printer_new ();
 
   vivi_code_printer_print_token (printer, token);
-  g_print ("\n\n");
 
   g_object_unref (printer);
   g_object_unref (token);
commit bdc780f9dd36695b847bf03ce3e396dec380d91c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 14:27:53 2008 +0300

    Add vivi-compile tests for empty array and object literals
    
    Also added a test for empty values inside array literal

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index fa5e589..1afa7fb 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -18,6 +18,10 @@ EXTRA_DIST = \
 	and.as.expect \
 	array_literal.as \
 	array_literal.as.expect \
+	array_literal_empty.as \
+	array_literal_empty.as.expect \
+	array_literal_missing_values.as \
+	array_literal_missing_values.as.expect \
 	asm_empty.as \
 	asm_empty.as.expect \
 	asm_default.as \
@@ -72,6 +76,8 @@ EXTRA_DIST = \
 	operator.as.expect \
 	object_literal.as \
 	object_literal.as.expect \
+	object_literal_empty.as \
+	object_literal_empty.as.expect \
 	or.as \
 	or.as.expect \
 	trace.as \
diff --git a/vivified/code/test/compiler/array_literal_empty.as b/vivified/code/test/compiler/array_literal_empty.as
new file mode 100644
index 0000000..05c572f
--- /dev/null
+++ b/vivified/code/test/compiler/array_literal_empty.as
@@ -0,0 +1 @@
+a = [];
diff --git a/vivified/code/test/compiler/array_literal_empty.as.expect b/vivified/code/test/compiler/array_literal_empty.as.expect
new file mode 100644
index 0000000..434b800
--- /dev/null
+++ b/vivified/code/test/compiler/array_literal_empty.as.expect
@@ -0,0 +1,7 @@
+asm {
+  pool "a"
+  push pool 0, 0
+  init_array
+  set_variable
+  end
+}
diff --git a/vivified/code/test/compiler/array_literal_missing_values.as b/vivified/code/test/compiler/array_literal_missing_values.as
new file mode 100644
index 0000000..28df163
--- /dev/null
+++ b/vivified/code/test/compiler/array_literal_missing_values.as
@@ -0,0 +1,6 @@
+a = [,];
+a = [,,];
+a = [1,,];
+a = [,1,];
+a = [,,1];
+a = [1,,1];
diff --git a/vivified/code/test/compiler/array_literal_missing_values.as.expect b/vivified/code/test/compiler/array_literal_missing_values.as.expect
new file mode 100644
index 0000000..1c9c229
--- /dev/null
+++ b/vivified/code/test/compiler/array_literal_missing_values.as.expect
@@ -0,0 +1,22 @@
+asm {
+  pool "a"
+  push pool 0, undefined, 1
+  init_array
+  set_variable
+  push pool 0, undefined, undefined, 2
+  init_array
+  set_variable
+  push pool 0, undefined, 1, 2
+  init_array
+  set_variable
+  push pool 0, 1, undefined, 2
+  init_array
+  set_variable
+  push pool 0, 1, undefined, undefined, 3
+  init_array
+  set_variable
+  push pool 0, 1, undefined, 1, 3
+  init_array
+  set_variable
+  end
+}
diff --git a/vivified/code/test/compiler/object_literal_empty.as b/vivified/code/test/compiler/object_literal_empty.as
new file mode 100644
index 0000000..c483b75
--- /dev/null
+++ b/vivified/code/test/compiler/object_literal_empty.as
@@ -0,0 +1 @@
+o = {};
diff --git a/vivified/code/test/compiler/object_literal_empty.as.expect b/vivified/code/test/compiler/object_literal_empty.as.expect
new file mode 100644
index 0000000..74a70cc
--- /dev/null
+++ b/vivified/code/test/compiler/object_literal_empty.as.expect
@@ -0,0 +1,7 @@
+asm {
+  pool "o"
+  push pool 0, 0
+  init_object
+  set_variable
+  end
+}
commit f788ba190a6e1dab3d4e0ca2eab64100dab1012b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 14:26:47 2008 +0300

    Fix parsing of array literals adding extra elements sometimes

diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index f791ef0..0350eec 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -859,12 +859,8 @@ parse_array_literal (ParseData *data)
 
   parse_token (data, TOKEN_BRACKET_LEFT);
 
-  while (TRUE) {
-    if (try_parse_token (data, TOKEN_BRACKET_RIGHT)) {
-      vivi_code_init_array_add_variable (VIVI_CODE_INIT_ARRAY (value),
-	 vivi_code_undefined_new ());
-      break;
-    } else if (try_parse_token (data, TOKEN_COMMA)) {
+  while (!try_parse_token (data, TOKEN_BRACKET_RIGHT)) {
+    if (try_parse_token (data, TOKEN_COMMA)) {
       vivi_code_init_array_add_variable (VIVI_CODE_INIT_ARRAY (value),
 	 vivi_code_undefined_new ());
     }
commit fcdac26ffcffa44bed64bd425226f9384cfe4d50
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 14:13:45 2008 +0300

    Add a vivi-compile test for decrement

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 4fb710e..fa5e589 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -40,6 +40,8 @@ EXTRA_DIST = \
 	call_function.as.expect \
 	comment.as \
 	comment.as.expect \
+	decrement.as \
+	decrement.as.expect \
 	empty.as \
 	empty.as.expect \
 	empty_block.as \
diff --git a/vivified/code/test/compiler/decrement.as b/vivified/code/test/compiler/decrement.as
new file mode 100644
index 0000000..091a1f0
--- /dev/null
+++ b/vivified/code/test/compiler/decrement.as
@@ -0,0 +1,2 @@
+i--;
+--i;
diff --git a/vivified/code/test/compiler/decrement.as.expect b/vivified/code/test/compiler/decrement.as.expect
new file mode 100644
index 0000000..fea15f4
--- /dev/null
+++ b/vivified/code/test/compiler/decrement.as.expect
@@ -0,0 +1,14 @@
+asm {
+  pool "i"
+  push pool 0
+  push_duplicate
+  get_variable
+  decrement
+  set_variable
+  push pool 0
+  push_duplicate
+  get_variable
+  decrement
+  set_variable
+  end
+}
commit 678947f5257b4678b0e2e0e14a7e8ba4c4c25532
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 14:12:14 2008 +0300

    Add a vivi-compile test for increment of members

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 8cf35e1..4fb710e 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -58,6 +58,10 @@ EXTRA_DIST = \
 	if_else.as.expect \
 	increment.as \
 	increment.as.expect \
+	increment_member.as \
+	increment_member.as.expect \
+	increment_member_value.as \
+	increment_member_value.as.expect \
 	increment_value.as \
 	increment_value.as.expect \
 	label.as \
diff --git a/vivified/code/test/compiler/increment_member.as b/vivified/code/test/compiler/increment_member.as
new file mode 100644
index 0000000..f43f60c
--- /dev/null
+++ b/vivified/code/test/compiler/increment_member.as
@@ -0,0 +1,4 @@
+a.b++;
+a[b]++;
+++a.b;
+++a[b];
diff --git a/vivified/code/test/compiler/increment_member.as.expect b/vivified/code/test/compiler/increment_member.as.expect
new file mode 100644
index 0000000..0a3caad
--- /dev/null
+++ b/vivified/code/test/compiler/increment_member.as.expect
@@ -0,0 +1,44 @@
+asm {
+  pool "a", "b"
+  push pool 0
+  get_variable
+  push_duplicate
+  push pool 1
+  get_member
+  increment
+  push pool 1
+  swap
+  set_member
+  push pool 0
+  get_variable
+  push_duplicate
+  push pool 1
+  get_variable
+  store 0
+  get_member
+  increment
+  push reg 0
+  swap
+  set_member
+  push pool 0
+  get_variable
+  push_duplicate
+  push pool 1
+  get_member
+  increment
+  push pool 1
+  swap
+  set_member
+  push pool 0
+  get_variable
+  push_duplicate
+  push pool 1
+  get_variable
+  store 0
+  get_member
+  increment
+  push reg 0
+  swap
+  set_member
+  end
+}
diff --git a/vivified/code/test/compiler/increment_member_value.as b/vivified/code/test/compiler/increment_member_value.as
new file mode 100644
index 0000000..21950c7
--- /dev/null
+++ b/vivified/code/test/compiler/increment_member_value.as
@@ -0,0 +1,4 @@
+trace (a.b++);
+trace (a[b]++);
+trace (++a.b);
+trace (++a[b]);
diff --git a/vivified/code/test/compiler/increment_member_value.as.expect b/vivified/code/test/compiler/increment_member_value.as.expect
new file mode 100644
index 0000000..ca70c78
--- /dev/null
+++ b/vivified/code/test/compiler/increment_member_value.as.expect
@@ -0,0 +1,58 @@
+asm {
+  pool "a", "b"
+  push pool 0
+  get_variable
+  push_duplicate
+  push pool 1
+  swap
+  push pool 1
+  get_member
+  store 0
+  increment
+  set_member
+  push reg 0
+  trace
+  push pool 1
+  get_variable
+  push pool 0
+  get_variable
+  store 0
+  swap
+  push_duplicate
+  push reg 0
+  swap
+  get_member
+  store 0
+  increment
+  set_member
+  push reg 0
+  trace
+  push pool 0
+  get_variable
+  push_duplicate
+  push pool 1
+  swap
+  push pool 1
+  get_member
+  increment
+  store 0
+  set_member
+  push reg 0
+  trace
+  push pool 1
+  get_variable
+  push pool 0
+  get_variable
+  store 0
+  swap
+  push_duplicate
+  push reg 0
+  swap
+  get_member
+  increment
+  store 0
+  set_member
+  push reg 0
+  trace
+  end
+}
commit 3372c43836fc839c31abe1856c0acf891622d5d7
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 14:02:40 2008 +0300

    Add vivi-compile tests for increment of variable (not member)

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index c414d92..8cf35e1 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -56,6 +56,10 @@ EXTRA_DIST = \
 	if.as.expect \
 	if_else.as \
 	if_else.as.expect \
+	increment.as \
+	increment.as.expect \
+	increment_value.as \
+	increment_value.as.expect \
 	label.as \
 	label.as.expect \
 	operator.as \
diff --git a/vivified/code/test/compiler/increment.as b/vivified/code/test/compiler/increment.as
new file mode 100644
index 0000000..b63a491
--- /dev/null
+++ b/vivified/code/test/compiler/increment.as
@@ -0,0 +1,2 @@
+i++;
+++i;
diff --git a/vivified/code/test/compiler/increment.as.expect b/vivified/code/test/compiler/increment.as.expect
new file mode 100644
index 0000000..a27d25c
--- /dev/null
+++ b/vivified/code/test/compiler/increment.as.expect
@@ -0,0 +1,14 @@
+asm {
+  pool "i"
+  push pool 0
+  push_duplicate
+  get_variable
+  increment
+  set_variable
+  push pool 0
+  push_duplicate
+  get_variable
+  increment
+  set_variable
+  end
+}
diff --git a/vivified/code/test/compiler/increment_value.as b/vivified/code/test/compiler/increment_value.as
new file mode 100644
index 0000000..cc998f5
--- /dev/null
+++ b/vivified/code/test/compiler/increment_value.as
@@ -0,0 +1,2 @@
+trace (i++);
+trace (++i);
diff --git a/vivified/code/test/compiler/increment_value.as.expect b/vivified/code/test/compiler/increment_value.as.expect
new file mode 100644
index 0000000..7340a91
--- /dev/null
+++ b/vivified/code/test/compiler/increment_value.as.expect
@@ -0,0 +1,20 @@
+asm {
+  pool "i"
+  push pool 0
+  get_variable
+  push_duplicate
+  increment
+  push pool 0
+  swap
+  set_variable
+  trace
+  push pool 0
+  get_variable
+  increment
+  push_duplicate
+  push pool 0
+  swap
+  set_variable
+  trace
+  end
+}
commit ecd325e13f4cbce6d4a7db0c8198a8a4615ad3a2
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 14:01:34 2008 +0300

    Compile IncDec better when from != NULL and name is constant

diff --git a/vivified/code/vivi_code_inc_dec.c b/vivified/code/vivi_code_inc_dec.c
index 2c9560c..d00638b 100644
--- a/vivified/code/vivi_code_inc_dec.c
+++ b/vivified/code/vivi_code_inc_dec.c
@@ -145,16 +145,25 @@ vivi_code_inc_dec_compile_value (ViviCodeValue *value,
   ViviCodeAsm *push;
 
   if (inc_dec->from) {
-    // FIXME: optimize the VIVI_IS_CODE_CONSTANT (inc_dec->name) case
-    vivi_code_compiler_compile_value (compiler, inc_dec->name);
-    vivi_code_compiler_compile_value (compiler, inc_dec->from);
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
-    vivi_code_compiler_take_code (compiler,
-	vivi_code_asm_push_duplicate_new ());
-    push = vivi_code_asm_push_new ();
-    vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
-    vivi_code_compiler_take_code (compiler, push);
+    if (VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
+      vivi_code_compiler_compile_value (compiler, inc_dec->from);
+      vivi_code_compiler_take_code (compiler,
+	  vivi_code_asm_push_duplicate_new ());
+      vivi_code_compiler_compile_value (compiler, inc_dec->name);
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
+      vivi_code_compiler_compile_value (compiler, inc_dec->name);
+    } else {
+      vivi_code_compiler_compile_value (compiler, inc_dec->name);
+      vivi_code_compiler_compile_value (compiler, inc_dec->from);
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
+      vivi_code_compiler_take_code (compiler,
+	  vivi_code_asm_push_duplicate_new ());
+      push = vivi_code_asm_push_new ();
+      vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+      vivi_code_compiler_take_code (compiler, push);
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
+    }
     vivi_code_compiler_take_code (compiler, vivi_code_asm_get_member_new ());
 
     if (!inc_dec->pre_assignment)
commit 26a44086f5d3ef2bf1a8bf64536ec563a64b1748
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 13:30:47 2008 +0300

    Require name to be constant in IncDec if from is NULL

diff --git a/vivified/code/vivi_code_inc_dec.c b/vivified/code/vivi_code_inc_dec.c
index 31edda5..2c9560c 100644
--- a/vivified/code/vivi_code_inc_dec.c
+++ b/vivified/code/vivi_code_inc_dec.c
@@ -24,6 +24,7 @@
 #include "vivi_code_inc_dec.h"
 #include "vivi_code_printer.h"
 #include "vivi_code_constant.h"
+#include "vivi_code_string.h"
 #include "vivi_code_compiler.h"
 #include "vivi_code_asm_code_default.h"
 #include "vivi_code_asm_push.h"
@@ -175,19 +176,11 @@ vivi_code_inc_dec_compile_value (ViviCodeValue *value,
     vivi_code_compiler_take_code (compiler, push);
   } else {
     vivi_code_compiler_compile_value (compiler, inc_dec->name);
-    if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
-      vivi_code_compiler_take_code (compiler,
-	  vivi_code_asm_push_duplicate_new ());
-    }
     vivi_code_compiler_take_code (compiler, vivi_code_asm_get_variable_new ());
 
     if (!inc_dec->pre_assignment) {
-      if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
-	vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
-      } else {
-	vivi_code_compiler_take_code (compiler,
-	    vivi_code_asm_push_duplicate_new ());
-      }
+      vivi_code_compiler_take_code (compiler,
+	  vivi_code_asm_push_duplicate_new ());
     }
 
     if (inc_dec->increment) {
@@ -197,12 +190,8 @@ vivi_code_inc_dec_compile_value (ViviCodeValue *value,
     }
 
     if (inc_dec->pre_assignment) {
-      if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
-	vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
-      } else {
-	vivi_code_compiler_take_code (compiler,
-	    vivi_code_asm_push_duplicate_new ());
-      }
+      vivi_code_compiler_take_code (compiler,
+	  vivi_code_asm_push_duplicate_new ());
     }
 
     if (VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
@@ -211,12 +200,6 @@ vivi_code_inc_dec_compile_value (ViviCodeValue *value,
     }
 
     vivi_code_compiler_take_code (compiler, vivi_code_asm_set_variable_new ());
-
-    if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
-      push = vivi_code_asm_push_new ();
-      vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
-      vivi_code_compiler_take_code (compiler, push);
-    }
   }
 }
 
@@ -248,6 +231,7 @@ vivi_code_inc_dec_new (ViviCodeValue *from, ViviCodeValue *name,
 
   g_return_val_if_fail (from == NULL || VIVI_IS_CODE_VALUE (from), NULL);
   g_return_val_if_fail (VIVI_IS_CODE_VALUE (name), NULL);
+  g_return_val_if_fail (from != NULL || VIVI_IS_CODE_CONSTANT (name), NULL);
 
   inc_dec = g_object_new (VIVI_TYPE_CODE_INC_DEC, NULL);
   if (from != NULL)
@@ -258,3 +242,19 @@ vivi_code_inc_dec_new (ViviCodeValue *from, ViviCodeValue *name,
 
   return VIVI_CODE_VALUE (inc_dec);
 }
+
+ViviCodeValue *
+vivi_code_inc_dec_new_name (const char *name, gboolean increment,
+    gboolean pre_assignment)
+{
+  ViviCodeValue *name_value, *inc_dec;
+
+  g_return_val_if_fail (name != NULL, NULL);
+
+  name_value = vivi_code_string_new (name);
+  inc_dec =
+    vivi_code_inc_dec_new (NULL, name_value, increment, pre_assignment);
+  g_object_unref (name_value);
+
+  return inc_dec;
+}
diff --git a/vivified/code/vivi_code_inc_dec.h b/vivified/code/vivi_code_inc_dec.h
index 910576c..3f430cd 100644
--- a/vivified/code/vivi_code_inc_dec.h
+++ b/vivified/code/vivi_code_inc_dec.h
@@ -57,6 +57,9 @@ ViviCodeValue *		vivi_code_inc_dec_new			(ViviCodeValue *	name,
 								 ViviCodeValue *	from,
 								 gboolean		increment,
 								 gboolean		pre_assignment);
+ViviCodeValue *		vivi_code_inc_dec_new_name		(const char *		name,
+								 gboolean		increment,
+								 gboolean		pre_assignment);
 
 
 G_END_DECLS
commit 061e97af1d1d886a8ea65bfda6a3acfb9a6e676b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 13:20:24 2008 +0300

    More work on compiling IncDec

diff --git a/vivified/code/vivi_code_inc_dec.c b/vivified/code/vivi_code_inc_dec.c
index a49ffc6..31edda5 100644
--- a/vivified/code/vivi_code_inc_dec.c
+++ b/vivified/code/vivi_code_inc_dec.c
@@ -105,7 +105,8 @@ vivi_code_inc_dec_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
     vivi_code_compiler_take_code (compiler,
 	vivi_code_asm_push_duplicate_new ());
     vivi_code_compiler_compile_value (compiler, inc_dec->name);
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+    if (!VIVI_IS_CODE_CONSTANT (inc_dec->name))
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
     vivi_code_compiler_take_code (compiler, vivi_code_asm_get_member_new ());
   } else {
     vivi_code_compiler_compile_value (compiler, inc_dec->name);
@@ -121,9 +122,13 @@ vivi_code_inc_dec_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   }
 
   if (inc_dec->from) {
-    ViviCodeAsm *push = vivi_code_asm_push_new ();
-    vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
-    vivi_code_compiler_take_code (compiler, push);
+    if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
+      ViviCodeAsm *push = vivi_code_asm_push_new ();
+      vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+      vivi_code_compiler_take_code (compiler, push);
+    } else {
+      vivi_code_compiler_compile_value (compiler, inc_dec->name);
+    }
     vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
     vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
   } else {
@@ -139,41 +144,80 @@ vivi_code_inc_dec_compile_value (ViviCodeValue *value,
   ViviCodeAsm *push;
 
   if (inc_dec->from) {
+    // FIXME: optimize the VIVI_IS_CODE_CONSTANT (inc_dec->name) case
+    vivi_code_compiler_compile_value (compiler, inc_dec->name);
     vivi_code_compiler_compile_value (compiler, inc_dec->from);
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_get_variable_new ());
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
     vivi_code_compiler_take_code (compiler,
 	vivi_code_asm_push_duplicate_new ());
-    vivi_code_compiler_compile_value (compiler, inc_dec->name);
+    push = vivi_code_asm_push_new ();
+    vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+    vivi_code_compiler_take_code (compiler, push);
     vivi_code_compiler_take_code (compiler, vivi_code_asm_get_member_new ());
+
+    if (!inc_dec->pre_assignment)
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+
+    if (inc_dec->increment) {
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_increment_new ());
+    } else {
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_decrement_new ());
+    }
+
+    if (inc_dec->pre_assignment)
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
+
+    push = vivi_code_asm_push_new ();
+    vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+    vivi_code_compiler_take_code (compiler, push);
   } else {
     vivi_code_compiler_compile_value (compiler, inc_dec->name);
-    vivi_code_compiler_take_code (compiler,
-	vivi_code_asm_push_duplicate_new ());
+    if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
+      vivi_code_compiler_take_code (compiler,
+	  vivi_code_asm_push_duplicate_new ());
+    }
     vivi_code_compiler_take_code (compiler, vivi_code_asm_get_variable_new ());
-  }
 
-  if (!inc_dec->pre_assignment)
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+    if (!inc_dec->pre_assignment) {
+      if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
+	vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+      } else {
+	vivi_code_compiler_take_code (compiler,
+	    vivi_code_asm_push_duplicate_new ());
+      }
+    }
 
-  if (inc_dec->increment) {
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_increment_new ());
-  } else {
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_decrement_new ());
-  }
+    if (inc_dec->increment) {
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_increment_new ());
+    } else {
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_decrement_new ());
+    }
 
-  if (inc_dec->pre_assignment)
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+    if (inc_dec->pre_assignment) {
+      if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
+	vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+      } else {
+	vivi_code_compiler_take_code (compiler,
+	    vivi_code_asm_push_duplicate_new ());
+      }
+    }
+
+    if (VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
+      vivi_code_compiler_compile_value (compiler, inc_dec->name);
+      vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
+    }
 
-  if (inc_dec->from) {
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
-  } else {
     vivi_code_compiler_take_code (compiler, vivi_code_asm_set_variable_new ());
-  }
 
-  push = vivi_code_asm_push_new ();
-  vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
-  vivi_code_compiler_take_code (compiler, push);
+    if (!VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
+      push = vivi_code_asm_push_new ();
+      vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+      vivi_code_compiler_take_code (compiler, push);
+    }
+  }
 }
 
 static void
commit fae01c75e5eb776406555b5ec403565516345ca2
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 11:54:32 2008 +0300

    Fixes to IncDec parsing and compiling

diff --git a/vivified/code/vivi_code_inc_dec.c b/vivified/code/vivi_code_inc_dec.c
index 2e97a47..a49ffc6 100644
--- a/vivified/code/vivi_code_inc_dec.c
+++ b/vivified/code/vivi_code_inc_dec.c
@@ -102,10 +102,10 @@ vivi_code_inc_dec_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 
   if (inc_dec->from) {
     vivi_code_compiler_compile_value (compiler, inc_dec->from);
-    vivi_code_compiler_take_code (compiler, vivi_code_asm_get_variable_new ());
     vivi_code_compiler_take_code (compiler,
 	vivi_code_asm_push_duplicate_new ());
     vivi_code_compiler_compile_value (compiler, inc_dec->name);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
     vivi_code_compiler_take_code (compiler, vivi_code_asm_get_member_new ());
   } else {
     vivi_code_compiler_compile_value (compiler, inc_dec->name);
@@ -121,6 +121,9 @@ vivi_code_inc_dec_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   }
 
   if (inc_dec->from) {
+    ViviCodeAsm *push = vivi_code_asm_push_new ();
+    vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+    vivi_code_compiler_take_code (compiler, push);
     vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
     vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
   } else {
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 5f7f279..f791ef0 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -351,25 +351,6 @@ vivi_parser_assignment_new (ViviCodeValue *left, ViviCodeValue *right)
   return vivi_code_assignment_new (from, name, right);
 }
 
-static ViviCodeValue *
-vivi_parser_inc_dec_new (ViviCodeValue *left, gboolean increment,
-    gboolean pre_assignment)
-{
-  ViviCodeValue *from, *name;
-
-  if (VIVI_IS_CODE_GET (left)) {
-    ViviCodeGet *get = VIVI_CODE_GET (left);
-
-    from = get->from;
-    name = get->name;
-  } else {
-    from = NULL;
-    name = left;
-  }
-
-  return vivi_code_inc_dec_new (from, name, increment, pre_assignment);
-}
-
 static gboolean
 vivi_parser_value_is_left_hand_side (ViviCodeValue *value)
 {
@@ -1776,7 +1757,8 @@ peek_postfix_expression (ParseData *data)
 static ViviCodeValue *
 parse_postfix_expression (ParseData *data)
 {
-  ViviCodeValue *value, *operation;
+  ViviCodeValue *value;
+  ViviCodeGet *get;
   gboolean add;
 
   vivi_parser_start_code_token (data);
@@ -1801,13 +1783,17 @@ parse_postfix_expression (ParseData *data)
   if (!vivi_parser_value_is_left_hand_side (value)) {
     vivi_parser_error (data,
 	"Invalid left-hand side expression for INCREASE/DECREASE");
+    g_object_unref (value);
+    value = vivi_code_get_new_name (NULL, "undefined");
   }
 
-  operation = vivi_parser_inc_dec_new (value, add, FALSE);
+  get = VIVI_CODE_GET (value);
+  value = vivi_code_inc_dec_new (get->from, get->name, add, FALSE);
+  g_object_unref (get);
 
-  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (operation));
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
 
-  return operation;
+  return value;
 }
 
 static gboolean
@@ -1835,6 +1821,7 @@ static ViviCodeValue *
 parse_unary_expression (ParseData *data)
 {
   ViviCodeValue *value, *tmp;
+  ViviCodeGet *get;
   gboolean increment = FALSE;
 
   switch ((guint) vivi_parser_scanner_peek_next_token (data->scanner)) {
@@ -1854,11 +1841,13 @@ parse_unary_expression (ParseData *data)
       if (!vivi_parser_value_is_left_hand_side (value)) {
 	vivi_parser_error (data,
 	    "Invalid left-hand side expression for INCREASE/DECREASE");
+	g_object_unref (value);
+	value = vivi_code_get_new_name (NULL, "undefined");
       }
 
-      tmp = value;
-      value = vivi_parser_inc_dec_new (tmp, increment, TRUE);
-      g_object_unref (tmp);
+      get = VIVI_CODE_GET (value);
+      value = vivi_code_inc_dec_new (get->from, get->name, increment, TRUE);
+      g_object_unref (get);
 
       vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
       break;
commit 6d64e5067a13db2802b6ed63c05a1ea5b24f9446
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 11:02:15 2008 +0300

    Improve the vivi-compile test label.as, add a test for label in asm block

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 9123e2f..c414d92 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -22,6 +22,8 @@ EXTRA_DIST = \
 	asm_empty.as.expect \
 	asm_default.as \
 	asm_default.as.expect \
+	asm_label.as \
+	asm_label.as.expect \
 	assignment.as \
 	assignment.as.expect \
 	assignment_member.as \
diff --git a/vivified/code/test/compiler/asm_label.as b/vivified/code/test/compiler/asm_label.as
new file mode 100644
index 0000000..4fdbb41
--- /dev/null
+++ b/vivified/code/test/compiler/asm_label.as
@@ -0,0 +1,5 @@
+asm {
+  play
+hello:
+  stop
+}
diff --git a/vivified/code/test/compiler/asm_label.as.expect b/vivified/code/test/compiler/asm_label.as.expect
new file mode 100644
index 0000000..5990cff
--- /dev/null
+++ b/vivified/code/test/compiler/asm_label.as.expect
@@ -0,0 +1,7 @@
+asm {
+  play
+
+hello:
+  stop
+  end
+}
diff --git a/vivified/code/test/compiler/label.as b/vivified/code/test/compiler/label.as
index 8507427..6857728 100644
--- a/vivified/code/test/compiler/label.as
+++ b/vivified/code/test/compiler/label.as
@@ -1 +1,3 @@
+play ();
 hello:
+stop ();
diff --git a/vivified/code/test/compiler/label.as.expect b/vivified/code/test/compiler/label.as.expect
index bb3700b..63e6efe 100644
--- a/vivified/code/test/compiler/label.as.expect
+++ b/vivified/code/test/compiler/label.as.expect
@@ -1,5 +1,7 @@
 asm {
+  play
 
 hello_0001:
+  stop
   end
 }
commit 161e7b3f298b2799f14287da011bc7ed6c153c83
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 10:54:22 2008 +0300

    Fix parsing of for statements. Add a test

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index f713808..9123e2f 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -44,6 +44,8 @@ EXTRA_DIST = \
 	empty_block.as.expect \
 	empty_statement.as \
 	empty_statement.as.expect \
+	for.as \
+	for.as.expect \
 	function_declaration.as \
 	function_declaration.as.expect \
 	function_expression.as \
diff --git a/vivified/code/test/compiler/for.as b/vivified/code/test/compiler/for.as
new file mode 100644
index 0000000..fd88467
--- /dev/null
+++ b/vivified/code/test/compiler/for.as
@@ -0,0 +1,3 @@
+for (var i = 0; i < 5; i++) {
+  play ();
+}
diff --git a/vivified/code/test/compiler/for.as.expect b/vivified/code/test/compiler/for.as.expect
new file mode 100644
index 0000000..63ffb69
--- /dev/null
+++ b/vivified/code/test/compiler/for.as.expect
@@ -0,0 +1,23 @@
+asm {
+  pool "i"
+  push pool 0, 0
+  define_local
+
+loop_start_0001:
+  push pool 0
+  get_variable
+  push 5
+  less2
+  not
+  if loop_end_0002
+  play
+  push pool 0
+  push_duplicate
+  get_variable
+  increment
+  set_variable
+  jump loop_start_0001
+
+loop_end_0002:
+  end
+}
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index ec9034b..5f7f279 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -2442,6 +2442,7 @@ parse_iteration_statement (ParseData *data)
   else if (try_parse_token (data, TOKEN_FOR))
   {
     ViviCodeValue *pre_value;
+    ViviCodeStatement *post_statement;
 
     parse_token (data, TOKEN_PARENTHESIS_LEFT);
 
@@ -2483,8 +2484,9 @@ parse_iteration_statement (ParseData *data)
       }
 
       if (!peek_token (data, TOKEN_PARENTHESIS_RIGHT)) {
-	pre_value = parse_expression (data);
-	g_object_unref (pre_value);
+	post_statement = VIVI_CODE_STATEMENT (parse_expression (data));
+      } else {
+	post_statement = NULL;
       }
     } else if (pre_value != NULL && try_parse_token (data, TOKEN_IN)) {
       // FIXME: correct?
@@ -2498,6 +2500,7 @@ parse_iteration_statement (ParseData *data)
       vivi_parser_error (data, "for (... in ...) has not been implemented yet");
 
       condition = vivi_code_undefined_new ();
+      post_statement = NULL;
     } else {
       if (pre_value != NULL) {
 	vivi_parser_error_unexpected_or (data, TOKEN_SEMICOLON, TOKEN_IN,
@@ -2507,6 +2510,7 @@ parse_iteration_statement (ParseData *data)
       }
 
       condition = vivi_code_undefined_new ();
+      post_statement = NULL;
 
       if (pre_value != NULL)
 	g_object_unref (pre_value);
@@ -2516,6 +2520,16 @@ parse_iteration_statement (ParseData *data)
 
     parse_token (data, TOKEN_PARENTHESIS_RIGHT);
     loop_statement = parse_statement (data);
+
+    if (post_statement != NULL) {
+      ViviCodeStatement *block = vivi_code_block_new ();
+      vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), loop_statement);
+      g_object_unref (loop_statement);
+      vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), post_statement);
+      g_object_unref (post_statement);
+
+      loop_statement = block;
+    }
   }
   else
   {
commit 867cc3828a126f443bd32cec666b9901c0ab3ea4
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 10:37:42 2008 +0300

    Fix an assert in parse_iteration_statement

diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 1183c79..ec9034b 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -2454,10 +2454,9 @@ parse_iteration_statement (ParseData *data)
       g_assert (VIVI_IS_CODE_BLOCK (pre_statement));
       if (vivi_code_block_get_n_statements (VIVI_CODE_BLOCK (pre_statement))
 	  == 1) {
-	ViviCodeAssignment *assignment = VIVI_CODE_ASSIGNMENT (
+	ViviCodeVariable *variable = VIVI_CODE_VARIABLE (
 	    vivi_code_block_get_statement (VIVI_CODE_BLOCK (pre_statement), 0));
-	g_assert (assignment->from == NULL);
-	pre_value = vivi_code_get_new (NULL, assignment->name);
+	pre_value = vivi_code_get_new (NULL, variable->name);
       } else {
 	pre_value = NULL;
       }
commit cc11056592ec0e7886b6f06e8a88443d412d0bab
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 10:31:34 2008 +0300

    Implement the compiling of member assignments as values. Add a test

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index cd48baa..f713808 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -26,6 +26,8 @@ EXTRA_DIST = \
 	assignment.as.expect \
 	assignment_member.as \
 	assignment_member.as.expect \
+	assignment_member_value.as \
+	assignment_member_value.as.expect \
 	assignment_operator.as \
 	assignment_operator.as.expect \
 	assignment_value.as \
diff --git a/vivified/code/test/compiler/assignment_member_value.as b/vivified/code/test/compiler/assignment_member_value.as
new file mode 100644
index 0000000..d82171a
--- /dev/null
+++ b/vivified/code/test/compiler/assignment_member_value.as
@@ -0,0 +1,2 @@
+trace (a.b = 1);
+trace (a[b] = 1);
diff --git a/vivified/code/test/compiler/assignment_member_value.as.expect b/vivified/code/test/compiler/assignment_member_value.as.expect
new file mode 100644
index 0000000..1445ed3
--- /dev/null
+++ b/vivified/code/test/compiler/assignment_member_value.as.expect
@@ -0,0 +1,20 @@
+asm {
+  pool "a", "b"
+  push pool 0
+  get_variable
+  push pool 1, 1
+  store 0
+  set_member
+  push reg 0
+  trace
+  push pool 0
+  get_variable
+  push pool 1
+  get_variable
+  push 1
+  store 0
+  set_member
+  push reg 0
+  trace
+  end
+}
diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index 00cb882..ba383b4 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -28,6 +28,8 @@
 #include "vivi_code_undefined.h"
 #include "vivi_code_compiler.h"
 #include "vivi_code_asm_code_default.h"
+#include "vivi_code_asm_push.h"
+#include "vivi_code_asm_store.h"
 
 G_DEFINE_TYPE (ViviCodeAssignment, vivi_code_assignment, VIVI_TYPE_CODE_VALUE)
 
@@ -111,12 +113,16 @@ vivi_code_assignment_compile_value (ViviCodeValue *value,
   ViviCodeAssignment *assignment = VIVI_CODE_ASSIGNMENT (value);
 
   if (assignment->from) {
-    // TODO
+    ViviCodeAsm *push;
+
     vivi_code_compiler_compile_value (compiler, assignment->from);
     vivi_code_compiler_compile_value (compiler, assignment->name);
     vivi_code_compiler_compile_value (compiler, assignment->value);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
     vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
-    g_assert_not_reached ();
+    push = vivi_code_asm_push_new ();
+    vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+    vivi_code_compiler_take_code (compiler, push);
   } else {
     vivi_code_compiler_compile_value (compiler, assignment->value);
     vivi_code_compiler_take_code (compiler,
diff --git a/vivified/code/vivi_code_inc_dec.c b/vivified/code/vivi_code_inc_dec.c
index f86b158..2e97a47 100644
--- a/vivified/code/vivi_code_inc_dec.c
+++ b/vivified/code/vivi_code_inc_dec.c
@@ -26,6 +26,8 @@
 #include "vivi_code_constant.h"
 #include "vivi_code_compiler.h"
 #include "vivi_code_asm_code_default.h"
+#include "vivi_code_asm_push.h"
+#include "vivi_code_asm_store.h"
 
 G_DEFINE_TYPE (ViviCodeIncDec, vivi_code_inc_dec, VIVI_TYPE_CODE_VALUE)
 
@@ -130,10 +132,45 @@ static void
 vivi_code_inc_dec_compile_value (ViviCodeValue *value,
     ViviCodeCompiler *compiler)
 {
-  //ViviCodeIncDec *inc_dec = VIVI_CODE_INC_DEC (value);
+  ViviCodeIncDec *inc_dec = VIVI_CODE_INC_DEC (value);
+  ViviCodeAsm *push;
+
+  if (inc_dec->from) {
+    vivi_code_compiler_compile_value (compiler, inc_dec->from);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_get_variable_new ());
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_push_duplicate_new ());
+    vivi_code_compiler_compile_value (compiler, inc_dec->name);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_get_member_new ());
+  } else {
+    vivi_code_compiler_compile_value (compiler, inc_dec->name);
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_push_duplicate_new ());
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_get_variable_new ());
+  }
+
+  if (!inc_dec->pre_assignment)
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+
+  if (inc_dec->increment) {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_increment_new ());
+  } else {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_decrement_new ());
+  }
+
+  if (inc_dec->pre_assignment)
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_store_new (0));
+
+  if (inc_dec->from) {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
+  } else {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_variable_new ());
+  }
 
-  // TODO
-  g_printerr ("Implement inc_dec_compile_value\n");
+  push = vivi_code_asm_push_new ();
+  vivi_code_asm_push_add_register (VIVI_CODE_ASM_PUSH (push), 0);
+  vivi_code_compiler_take_code (compiler, push);
 }
 
 static void
commit 8f188fa5154254c595260edd173632b65ea159e1
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 15 10:27:03 2008 +0300

    Fix compiling of assignments to members. Add a test

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index d47bb0e..cd48baa 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -24,6 +24,8 @@ EXTRA_DIST = \
 	asm_default.as.expect \
 	assignment.as \
 	assignment.as.expect \
+	assignment_member.as \
+	assignment_member.as.expect \
 	assignment_operator.as \
 	assignment_operator.as.expect \
 	assignment_value.as \
diff --git a/vivified/code/test/compiler/assignment_member.as b/vivified/code/test/compiler/assignment_member.as
new file mode 100644
index 0000000..cf79571
--- /dev/null
+++ b/vivified/code/test/compiler/assignment_member.as
@@ -0,0 +1,2 @@
+a.b = 1;
+a[b] = 1;
diff --git a/vivified/code/test/compiler/assignment_member.as.expect b/vivified/code/test/compiler/assignment_member.as.expect
new file mode 100644
index 0000000..2cdd902
--- /dev/null
+++ b/vivified/code/test/compiler/assignment_member.as.expect
@@ -0,0 +1,14 @@
+asm {
+  pool "a", "b"
+  push pool 0
+  get_variable
+  push pool 1, 1
+  set_member
+  push pool 0
+  get_variable
+  push pool 1
+  get_variable
+  push 1
+  set_member
+  end
+}
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 811471c..1183c79 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -331,7 +331,7 @@ vivi_parser_function_call_new (ViviCodeValue *name)
 static ViviCodeValue *
 vivi_parser_assignment_new (ViviCodeValue *left, ViviCodeValue *right)
 {
-  ViviCodeValue *from;
+  ViviCodeValue *from, *name;
 
   g_return_val_if_fail (VIVI_IS_CODE_VALUE (left), NULL);
   g_return_val_if_fail (VIVI_IS_CODE_VALUE (right), NULL);
@@ -341,20 +341,14 @@ vivi_parser_assignment_new (ViviCodeValue *left, ViviCodeValue *right)
   if (VIVI_IS_CODE_GET (left)) {
     ViviCodeGet *get = VIVI_CODE_GET (left);
 
-    if (get->from != NULL) {
-      from = g_object_ref (get->from);
-      left = g_object_ref (get->name);
-    }
-  }
-
-  if (VIVI_IS_CODE_GET (left)) {
-    ViviCodeGet *get = VIVI_CODE_GET (left);
-
-    if (get->from == NULL)
-      left = g_object_ref (get->name);
+    from = get->from;
+    name = get->name;
+  } else {
+    from = NULL;
+    name = left;
   }
 
-  return vivi_code_assignment_new (from, left, right);
+  return vivi_code_assignment_new (from, name, right);
 }
 
 static ViviCodeValue *
commit 855130ab5c8727d96193b995332b64554f2fa42c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 22:24:04 2008 +0300

    Create ViviCodeIncDec class for ++ and -- operators including the assignment
    
    Removed ViviCodeIncrement of course

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index f001408..d18ddc3 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -69,7 +69,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_get_url.c \
 	vivi_code_goto.c \
 	vivi_code_if.c \
-	vivi_code_increment.c \
+	vivi_code_inc_dec.c \
 	vivi_code_init_array.c \
 	vivi_code_init_object.c \
 	vivi_code_label.c \
@@ -146,7 +146,7 @@ noinst_HEADERS = \
 	vivi_code_get_url.h \
 	vivi_code_goto.h \
 	vivi_code_if.h \
-	vivi_code_increment.h \
+	vivi_code_inc_dec.h \
 	vivi_code_init_array.h \
 	vivi_code_init_object.h \
 	vivi_code_label.h \
diff --git a/vivified/code/vivi_code_inc_dec.c b/vivified/code/vivi_code_inc_dec.c
new file mode 100644
index 0000000..f86b158
--- /dev/null
+++ b/vivified/code/vivi_code_inc_dec.c
@@ -0,0 +1,176 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_code_inc_dec.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_constant.h"
+#include "vivi_code_compiler.h"
+#include "vivi_code_asm_code_default.h"
+
+G_DEFINE_TYPE (ViviCodeIncDec, vivi_code_inc_dec, VIVI_TYPE_CODE_VALUE)
+
+static void
+vivi_code_inc_dec_dispose (GObject *object)
+{
+  ViviCodeIncDec *inc_dec = VIVI_CODE_INC_DEC (object);
+
+  g_object_unref (inc_dec->name);
+
+  G_OBJECT_CLASS (vivi_code_inc_dec_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_inc_dec_print_value (ViviCodeValue *value,
+    ViviCodePrinter *printer)
+{
+  ViviCodeIncDec *inc_dec = VIVI_CODE_INC_DEC (value);
+  char *varname;
+
+  if (inc_dec->pre_assignment) {
+    if (inc_dec->increment) {
+      vivi_code_printer_print (printer, "++");
+    } else {
+      vivi_code_printer_print (printer, "--");
+    }
+  }
+
+  // FIXME this is code duplication from ViviCodeAssignment
+  if (VIVI_IS_CODE_CONSTANT (inc_dec->name)) {
+    varname = vivi_code_constant_get_variable_name (
+	VIVI_CODE_CONSTANT (inc_dec->name));
+  } else {
+    varname = NULL;
+  }
+
+  if (inc_dec->from) {
+    vivi_code_printer_print_value (printer, inc_dec->from,
+	VIVI_PRECEDENCE_MEMBER);
+    if (varname) {
+      vivi_code_printer_print (printer, ".");
+      vivi_code_printer_print (printer, varname);
+    } else {
+      vivi_code_printer_print (printer, "[");
+      vivi_code_printer_print_value (printer, inc_dec->name,
+	  VIVI_PRECEDENCE_MIN);
+      vivi_code_printer_print (printer, "]");
+    }
+  } else {
+    if (varname) {
+      vivi_code_printer_print (printer, varname);
+    } else {
+      // FIXME
+      g_assert_not_reached ();
+      return;
+    }
+  }
+
+  if (!inc_dec->pre_assignment) {
+    if (inc_dec->increment) {
+      vivi_code_printer_print (printer, "++");
+    } else {
+      vivi_code_printer_print (printer, "--");
+    }
+  }
+}
+
+static void
+vivi_code_inc_dec_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+{
+  ViviCodeIncDec *inc_dec = VIVI_CODE_INC_DEC (token);
+
+  if (inc_dec->from) {
+    vivi_code_compiler_compile_value (compiler, inc_dec->from);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_get_variable_new ());
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_push_duplicate_new ());
+    vivi_code_compiler_compile_value (compiler, inc_dec->name);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_get_member_new ());
+  } else {
+    vivi_code_compiler_compile_value (compiler, inc_dec->name);
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_push_duplicate_new ());
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_get_variable_new ());
+  }
+
+  if (inc_dec->increment) {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_increment_new ());
+  } else {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_decrement_new ());
+  }
+
+  if (inc_dec->from) {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
+  } else {
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_variable_new ());
+  }
+}
+
+static void
+vivi_code_inc_dec_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
+{
+  //ViviCodeIncDec *inc_dec = VIVI_CODE_INC_DEC (value);
+
+  // TODO
+  g_printerr ("Implement inc_dec_compile_value\n");
+}
+
+static void
+vivi_code_inc_dec_class_init (ViviCodeIncDecClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
+
+  object_class->dispose = vivi_code_inc_dec_dispose;
+
+  token_class->compile = vivi_code_inc_dec_compile;
+
+  value_class->print_value = vivi_code_inc_dec_print_value;
+  value_class->compile_value = vivi_code_inc_dec_compile_value;
+}
+
+static void
+vivi_code_inc_dec_init (ViviCodeIncDec *inc_dec)
+{
+}
+
+ViviCodeValue *
+vivi_code_inc_dec_new (ViviCodeValue *from, ViviCodeValue *name,
+    gboolean increment, gboolean pre_assignment)
+{
+  ViviCodeIncDec *inc_dec;
+
+  g_return_val_if_fail (from == NULL || VIVI_IS_CODE_VALUE (from), NULL);
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (name), NULL);
+
+  inc_dec = g_object_new (VIVI_TYPE_CODE_INC_DEC, NULL);
+  if (from != NULL)
+    inc_dec->from = g_object_ref (from);
+  inc_dec->name = g_object_ref (name);
+  inc_dec->increment = increment;
+  inc_dec->pre_assignment = pre_assignment;
+
+  return VIVI_CODE_VALUE (inc_dec);
+}
diff --git a/vivified/code/vivi_code_inc_dec.h b/vivified/code/vivi_code_inc_dec.h
new file mode 100644
index 0000000..910576c
--- /dev/null
+++ b/vivified/code/vivi_code_inc_dec.h
@@ -0,0 +1,63 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_CODE_INC_DEC_H_
+#define _VIVI_CODE_INC_DEC_H_
+
+#include <vivified/code/vivi_code_value.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeIncDec ViviCodeIncDec;
+typedef struct _ViviCodeIncDecClass ViviCodeIncDecClass;
+
+#define VIVI_TYPE_CODE_INC_DEC                    (vivi_code_inc_dec_get_type())
+#define VIVI_IS_CODE_INC_DEC(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_INC_DEC))
+#define VIVI_IS_CODE_INC_DEC_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_INC_DEC))
+#define VIVI_CODE_INC_DEC(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_INC_DEC, ViviCodeIncDec))
+#define VIVI_CODE_INC_DEC_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_INC_DEC, ViviCodeIncDecClass))
+#define VIVI_CODE_INC_DEC_INC_DEC_CLASS(obj)          (G_TYPE_INSTANCE_INC_DEC_CLASS ((obj), VIVI_TYPE_CODE_INC_DEC, ViviCodeIncDecClass))
+
+struct _ViviCodeIncDec
+{
+  ViviCodeValue		token;
+
+  ViviCodeValue *	from;
+  ViviCodeValue *	name;
+  gboolean		increment;
+  gboolean		pre_assignment;
+};
+
+struct _ViviCodeIncDecClass
+{
+  ViviCodeValueClass	value_class;
+};
+
+GType			vivi_code_inc_dec_get_type		(void);
+
+ViviCodeValue *		vivi_code_inc_dec_new			(ViviCodeValue *	name,
+								 ViviCodeValue *	from,
+								 gboolean		increment,
+								 gboolean		pre_assignment);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_code_increment.c b/vivified/code/vivi_code_increment.c
deleted file mode 100644
index c8d9b83..0000000
--- a/vivified/code/vivi_code_increment.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "vivi_code_increment.h"
-#include "vivi_code_printer.h"
-#include "vivi_code_compiler.h"
-#include "vivi_code_asm_code_default.h"
-
-G_DEFINE_TYPE (ViviCodeIncrement, vivi_code_increment, VIVI_TYPE_CODE_VALUE)
-
-static void
-vivi_code_increment_dispose (GObject *object)
-{
-  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (object);
-
-  g_object_unref (increment->value);
-
-  G_OBJECT_CLASS (vivi_code_increment_parent_class)->dispose (object);
-}
-
-static void
-vivi_code_increment_print_value (ViviCodeValue *value,
-    ViviCodePrinter *printer)
-{
-  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (value);
-
-  vivi_code_printer_print_value (printer, increment->value,
-      VIVI_PRECEDENCE_INCREMENT);
-  vivi_code_printer_print (printer, "++");
-  vivi_code_printer_new_line (printer, FALSE);
-}
-
-static void
-vivi_code_increment_compile_value (ViviCodeValue *value,
-    ViviCodeCompiler *compiler)
-{
-  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (value);
-
-  vivi_code_compiler_compile_value (compiler, increment->value);
-  vivi_code_compiler_take_code (compiler, vivi_code_asm_increment_new ());
-}
-
-static void
-vivi_code_increment_class_init (ViviCodeIncrementClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
-
-  object_class->dispose = vivi_code_increment_dispose;
-
-  value_class->print_value = vivi_code_increment_print_value;
-  value_class->compile_value = vivi_code_increment_compile_value;
-}
-
-static void
-vivi_code_increment_init (ViviCodeIncrement *increment)
-{
-}
-
-ViviCodeValue *
-vivi_code_increment_new (ViviCodeValue *value)
-{
-  ViviCodeIncrement *increment;
-
-  g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
-
-  increment = g_object_new (VIVI_TYPE_CODE_INCREMENT, NULL);
-  increment->value = g_object_ref (value);
-
-  return VIVI_CODE_VALUE (increment);
-}
diff --git a/vivified/code/vivi_code_increment.h b/vivified/code/vivi_code_increment.h
deleted file mode 100644
index f163cef..0000000
--- a/vivified/code/vivi_code_increment.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _VIVI_CODE_INCREMENT_H_
-#define _VIVI_CODE_INCREMENT_H_
-
-#include <vivified/code/vivi_code_value.h>
-#include <vivified/code/vivi_code_value.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _ViviCodeIncrement ViviCodeIncrement;
-typedef struct _ViviCodeIncrementClass ViviCodeIncrementClass;
-
-#define VIVI_TYPE_CODE_INCREMENT                    (vivi_code_increment_get_type())
-#define VIVI_IS_CODE_INCREMENT(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_INCREMENT))
-#define VIVI_IS_CODE_INCREMENT_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_INCREMENT))
-#define VIVI_CODE_INCREMENT(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_INCREMENT, ViviCodeIncrement))
-#define VIVI_CODE_INCREMENT_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_INCREMENT, ViviCodeIncrementClass))
-#define VIVI_CODE_INCREMENT_INCREMENT_CLASS(obj)          (G_TYPE_INSTANCE_INCREMENT_CLASS ((obj), VIVI_TYPE_CODE_INCREMENT, ViviCodeIncrementClass))
-
-struct _ViviCodeIncrement
-{
-  ViviCodeValue		token;
-
-  ViviCodeValue *	value;
-};
-
-struct _ViviCodeIncrementClass
-{
-  ViviCodeValueClass	value_class;
-};
-
-GType			vivi_code_increment_get_type		(void);
-
-ViviCodeValue *	vivi_code_increment_new				(ViviCodeValue *	value);
-
-
-G_END_DECLS
-#endif
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index f70d6d4..811471c 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -50,7 +50,7 @@
 #include "vivi_code_get_url.h"
 #include "vivi_code_goto.h"
 #include "vivi_code_if.h"
-#include "vivi_code_increment.h"
+#include "vivi_code_inc_dec.h"
 #include "vivi_code_init_array.h"
 #include "vivi_code_init_object.h"
 #include "vivi_code_loop.h"
@@ -357,6 +357,25 @@ vivi_parser_assignment_new (ViviCodeValue *left, ViviCodeValue *right)
   return vivi_code_assignment_new (from, left, right);
 }
 
+static ViviCodeValue *
+vivi_parser_inc_dec_new (ViviCodeValue *left, gboolean increment,
+    gboolean pre_assignment)
+{
+  ViviCodeValue *from, *name;
+
+  if (VIVI_IS_CODE_GET (left)) {
+    ViviCodeGet *get = VIVI_CODE_GET (left);
+
+    from = get->from;
+    name = get->name;
+  } else {
+    from = NULL;
+    name = left;
+  }
+
+  return vivi_code_inc_dec_new (from, name, increment, pre_assignment);
+}
+
 static gboolean
 vivi_parser_value_is_left_hand_side (ViviCodeValue *value)
 {
@@ -1763,7 +1782,7 @@ peek_postfix_expression (ParseData *data)
 static ViviCodeValue *
 parse_postfix_expression (ParseData *data)
 {
-  ViviCodeValue *assignment, *value, *operation, *one;
+  ViviCodeValue *value, *operation;
   gboolean add;
 
   vivi_parser_start_code_token (data);
@@ -1790,20 +1809,11 @@ parse_postfix_expression (ParseData *data)
 	"Invalid left-hand side expression for INCREASE/DECREASE");
   }
 
-  one = vivi_code_number_new (1);
-  operation = (add ? vivi_code_increment_new (value) : vivi_code_subtract_new (value, one));
-  g_object_unref (one);
+  operation = vivi_parser_inc_dec_new (value, add, FALSE);
 
-  vivi_parser_duplicate_code_token (data);
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (operation));
 
-  assignment = vivi_parser_assignment_new (value, operation);
-  g_object_unref (operation);
-  g_object_unref (value);
-
-  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (assignment));
-
-  return assignment;
+  return operation;
 }
 
 static gboolean
@@ -1830,7 +1840,7 @@ peek_unary_expression (ParseData *data)
 static ViviCodeValue *
 parse_unary_expression (ParseData *data)
 {
-  ViviCodeValue *value, *tmp, *one;
+  ViviCodeValue *value, *tmp;
   gboolean increment = FALSE;
 
   switch ((guint) vivi_parser_scanner_peek_next_token (data->scanner)) {
@@ -1852,17 +1862,11 @@ parse_unary_expression (ParseData *data)
 	    "Invalid left-hand side expression for INCREASE/DECREASE");
       }
 
-      one = vivi_code_number_new (1);
-      tmp = (increment ? vivi_code_increment_new (value) :
-	  vivi_code_subtract_new (value, one));
-      g_object_unref (one);
-
-      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (tmp));
-
-      one = vivi_parser_assignment_new (value, tmp);
+      tmp = value;
+      value = vivi_parser_inc_dec_new (tmp, increment, TRUE);
       g_object_unref (tmp);
-      g_object_unref (value);
-      value = one;
+
+      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
       break;
     case TOKEN_PLUS:
       vivi_parser_scanner_get_next_token (data->scanner);
commit c9e7b1733eedaa36c78454b37d2f19b56e768087
Merge: 023d330... f38ea83...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 19:00:17 2008 +0300

    Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec

commit 023d330cfbdce498a1ee7b35008c5bbdba32a72a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 18:04:46 2008 +0300

    Fixes to parsing of member gets

diff --git a/vivified/code/vivi_code_get.c b/vivified/code/vivi_code_get.c
index dc9bb40..800e366 100644
--- a/vivified/code/vivi_code_get.c
+++ b/vivified/code/vivi_code_get.c
@@ -150,14 +150,15 @@ vivi_code_get_new (ViviCodeValue *from, ViviCodeValue *name)
 }
 
 ViviCodeValue *
-vivi_code_get_new_name (const char *name)
+vivi_code_get_new_name (ViviCodeValue *from, const char *name)
 {
   ViviCodeValue *result, *constant;
 
+  g_return_val_if_fail (from == NULL || VIVI_IS_CODE_VALUE (from), NULL);
   g_return_val_if_fail (name != NULL, NULL);
 
   constant = vivi_code_string_new (name);
-  result = vivi_code_get_new (NULL, constant);
+  result = vivi_code_get_new (from, constant);
   g_object_unref (constant);
   return result;
 }
diff --git a/vivified/code/vivi_code_get.h b/vivified/code/vivi_code_get.h
index 896c600..39d9e82 100644
--- a/vivified/code/vivi_code_get.h
+++ b/vivified/code/vivi_code_get.h
@@ -52,7 +52,8 @@ GType			vivi_code_get_get_type   	(void);
 
 ViviCodeValue *		vivi_code_get_new		(ViviCodeValue *	from,
 							 ViviCodeValue *	name);
-ViviCodeValue *		vivi_code_get_new_name		(const char *		name);
+ViviCodeValue *		vivi_code_get_new_name		(ViviCodeValue *	from,
+							 const char *		name);
 
 char *			vivi_code_get_get_variable_name	(ViviCodeGet *		get);
 
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index 8f95b4f..a8d383c 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -634,7 +634,7 @@ vivi_decompile_store_register (ViviDecompilerBlock *block, ViviDecompilerState *
     g_object_unref (assign);
 
     g_object_unref (value);
-    value = vivi_code_get_new_name (name);
+    value = vivi_code_get_new_name (NULL, name);
     g_free (name);
   }
   vivi_decompiler_state_set_register (state, data[0], value);
@@ -1562,7 +1562,7 @@ vivi_decompiler_preload (ViviDecompilerState *state, SwfdecScript *script)
 
   for (i = 0; i < script->n_arguments; i++) {
     if (script->arguments[i].preload) {
-      ViviCodeValue *value = vivi_code_get_new_name (script->arguments[i].name);
+      ViviCodeValue *value = vivi_code_get_new_name (NULL, script->arguments[i].name);
       vivi_decompiler_state_set_register (state, script->arguments[i].preload, value);
       g_object_unref (value);
     }
@@ -1570,7 +1570,7 @@ vivi_decompiler_preload (ViviDecompilerState *state, SwfdecScript *script)
   reg = 1;
   for (i = 0; i < G_N_ELEMENTS (preloads); i++) {
     if (script->flags & preloads[i].flag) {
-      ViviCodeValue *value = vivi_code_get_new_name (preloads[i].name);
+      ViviCodeValue *value = vivi_code_get_new_name (NULL, preloads[i].name);
       vivi_decompiler_state_set_register (state, reg++, value);
       g_object_unref (value);
     }
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index c21428f..f70d6d4 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -357,22 +357,6 @@ vivi_parser_assignment_new (ViviCodeValue *left, ViviCodeValue *right)
   return vivi_code_assignment_new (from, left, right);
 }
 
-static ViviCodeValue *
-vivi_parser_get_new (ViviCodeValue *from, ViviCodeValue *name)
-{
-  g_return_val_if_fail (VIVI_IS_CODE_VALUE (from), NULL);
-  g_return_val_if_fail (VIVI_IS_CODE_VALUE (name), NULL);
-
-  if (VIVI_IS_CODE_GET (name)) {
-    ViviCodeGet *get = VIVI_CODE_GET (name);
-
-    if (get->from == NULL)
-      name = g_object_ref (get->name);
-  }
-
-  return vivi_code_get_new (from, name);
-}
-
 static gboolean
 vivi_parser_value_is_left_hand_side (ViviCodeValue *value)
 {
@@ -825,7 +809,7 @@ parse_identifier (ParseData *data)
 
   vivi_parser_start_code_token (data);
 
-  value = vivi_code_get_new_name (parse_identifier_value (data));
+  value = vivi_code_get_new_name (NULL, parse_identifier_value (data));
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
 
@@ -1616,7 +1600,7 @@ parse_primary_expression (ParseData *data)
   vivi_parser_start_code_token (data);
 
   if (try_parse_token (data, TOKEN_THIS)) {
-    value = vivi_code_get_new_name ("this");
+    value = vivi_code_get_new_name (NULL, "this");
     vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
     return value;
   }
@@ -1658,7 +1642,7 @@ peek_member_expression (ParseData *data)
 static ViviCodeValue *
 parse_member_expression (ParseData *data)
 {
-  ViviCodeValue *value, *member;
+  ViviCodeValue *value;
 
   vivi_parser_start_code_token (data);
 
@@ -1679,20 +1663,21 @@ parse_member_expression (ParseData *data)
     ViviCodeValue *tmp;
 
     if (try_parse_token (data, TOKEN_BRACKET_LEFT)) {
-      member = parse_expression (data);
+      ViviCodeValue *member = parse_expression (data);
+      tmp = value;
+      value = vivi_code_get_new (tmp, member);
+      g_object_unref (tmp);
+      g_object_unref (member);
       parse_token (data, TOKEN_BRACKET_RIGHT);
     } else if (try_parse_token (data, TOKEN_DOT)) {
-      member = parse_identifier (data);
+      tmp = value;
+      value = vivi_code_get_new_name (tmp, parse_identifier_value (data));
+      g_object_unref (tmp);
     } else {
       vivi_parser_end_code_token (data, NULL);
       return value;
     }
 
-    tmp = value;
-    value = vivi_parser_get_new (tmp, member);
-    g_object_unref (tmp);
-    g_object_unref (member);
-
     vivi_parser_duplicate_code_token (data);
     vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
   }
commit f6d45de3678a41449f408aa1425c19b20dfe8ab1
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 17:22:40 2008 +0300

    Fix compiling non-member assignment as a value. Add a test

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 41fae08..d47bb0e 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -26,6 +26,8 @@ EXTRA_DIST = \
 	assignment.as.expect \
 	assignment_operator.as \
 	assignment_operator.as.expect \
+	assignment_value.as \
+	assignment_value.as.expect \
 	builtin_statement.as \
 	builtin_statement.as.expect \
 	call_function.as \
diff --git a/vivified/code/test/compiler/assignment_value.as b/vivified/code/test/compiler/assignment_value.as
new file mode 100644
index 0000000..2758c35
--- /dev/null
+++ b/vivified/code/test/compiler/assignment_value.as
@@ -0,0 +1 @@
+trace (a = 1);
diff --git a/vivified/code/test/compiler/assignment_value.as.expect b/vivified/code/test/compiler/assignment_value.as.expect
new file mode 100644
index 0000000..a9b7d8d
--- /dev/null
+++ b/vivified/code/test/compiler/assignment_value.as.expect
@@ -0,0 +1,10 @@
+asm {
+  pool "a"
+  push 1
+  push_duplicate
+  push pool 0
+  swap
+  set_variable
+  trace
+  end
+}
diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index b0ff354..00cb882 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -110,19 +110,18 @@ vivi_code_assignment_compile_value (ViviCodeValue *value,
 {
   ViviCodeAssignment *assignment = VIVI_CODE_ASSIGNMENT (value);
 
-  if (assignment->from)
-    vivi_code_compiler_compile_value (compiler, assignment->from);
-  vivi_code_compiler_compile_value (compiler, assignment->name);
-  vivi_code_compiler_compile_value (compiler, assignment->value);
-
-
   if (assignment->from) {
     // TODO
+    vivi_code_compiler_compile_value (compiler, assignment->from);
+    vivi_code_compiler_compile_value (compiler, assignment->name);
+    vivi_code_compiler_compile_value (compiler, assignment->value);
     vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
     g_assert_not_reached ();
   } else {
+    vivi_code_compiler_compile_value (compiler, assignment->value);
     vivi_code_compiler_take_code (compiler,
 	vivi_code_asm_push_duplicate_new ());
+    vivi_code_compiler_compile_value (compiler, assignment->name);
     vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
     vivi_code_compiler_take_code (compiler, vivi_code_asm_set_variable_new ());
   }
commit 63c0be1c155946647fa729d68d9b158874cd6742
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 17:14:00 2008 +0300

    Fix parsing of variable statements with no assignment. Add a test

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 1ec22b4..41fae08 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -56,5 +56,7 @@ EXTRA_DIST = \
 	or.as.expect \
 	trace.as \
 	trace.as.expect \
+	var.as \
+	var.as.expect \
 	while.as \
 	while.as.expect
diff --git a/vivified/code/test/compiler/var.as b/vivified/code/test/compiler/var.as
new file mode 100644
index 0000000..2303258
--- /dev/null
+++ b/vivified/code/test/compiler/var.as
@@ -0,0 +1 @@
+var a, b = 1, c = undefined;
diff --git a/vivified/code/test/compiler/var.as.expect b/vivified/code/test/compiler/var.as.expect
new file mode 100644
index 0000000..961a71b
--- /dev/null
+++ b/vivified/code/test/compiler/var.as.expect
@@ -0,0 +1,10 @@
+asm {
+  pool "a", "b", "c"
+  push pool 0
+  define_local2
+  push pool 1, 1
+  define_local
+  push pool 2, undefined
+  define_local
+  end
+}
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 24c8c32..c21428f 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -965,7 +965,7 @@ static ViviCodeStatement *
 parse_variable_declaration (ParseData *data)
 {
   ViviCodeValue *value;
-  ViviCodeStatement *variable, *statement_right;
+  ViviCodeStatement *variable;
   char *identifier;
 
   vivi_parser_start_code_token (data);
@@ -975,17 +975,13 @@ parse_variable_declaration (ParseData *data)
   if (try_parse_token (data, TOKEN_ASSIGN)) {
     value = parse_assignment_expression (data);
   } else {
-    vivi_parser_start_code_token (data);
-
-    value = vivi_code_undefined_new ();
-    statement_right = NULL;
-
-    vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
+    value = NULL;
   }
 
   variable = vivi_code_variable_new_name (identifier, value);
   g_free (identifier);
-  g_object_unref (value);
+  if (value != NULL)
+    g_object_unref (value);
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (variable));
 
commit 56597cf80a2db12d380796e09ba1de6641b9605e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 17:11:02 2008 +0300

    Change parsing functions returning value and statement to only return a value

diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 4c15c9d..24c8c32 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -121,7 +121,6 @@ typedef struct {
 
 typedef gboolean (*PeekFunction) (ParseData *data);
 typedef ViviCodeValue * (*ParseValueFunction) (ParseData *data);
-typedef ViviCodeValue * (*ParseValueStatementFunction) (ParseData *data, ViviCodeStatement **statement);
 typedef ViviCodeStatement * (*ParseStatementFunction) (ParseData *data);
 
 static ViviCodeStatement *
@@ -129,9 +128,8 @@ parse_statement_list (ParseData *data, PeekFunction peek,
     ParseStatementFunction parse, guint separator);
 
 static void
-parse_value_statement_list (ParseData *data, PeekFunction peek,
-    ParseValueStatementFunction parse, ViviCodeValue ***list,
-    ViviCodeStatement **statement, guint separator);
+parse_value_list (ParseData *data, PeekFunction peek, ParseValueFunction parse,
+    ViviCodeValue ***list, guint separator);
 
 // helpers
 
@@ -302,34 +300,6 @@ free_value_list (ViviCodeValue **list)
   g_free (list);
 }
 
-G_GNUC_WARN_UNUSED_RESULT static ViviCodeStatement *
-vivi_parser_join_statements (ViviCodeStatement *one, ViviCodeStatement *two)
-{
-
-  if (one == NULL) {
-    return two;
-  } else if (two == NULL) {
-    return one;
-  }
-
-  if (VIVI_IS_CODE_BLOCK (one)) {
-    vivi_code_block_add_statement (VIVI_CODE_BLOCK (one), two);
-    g_object_unref (two);
-    return one;
-  } else if (VIVI_IS_CODE_BLOCK (two)) {
-    vivi_code_block_insert_statement (VIVI_CODE_BLOCK (two), 0, one);
-    g_object_unref (one);
-    return two;
-  } else {
-    ViviCodeStatement *block = vivi_code_block_new ();
-    vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), one);
-    g_object_unref (one);
-    vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), two);
-    g_object_unref (two);
-    return block;
-  }
-}
-
 static ViviCodeValue *
 vivi_parser_function_call_new (ViviCodeValue *name)
 {
@@ -892,7 +862,7 @@ static gboolean
 peek_assignment_expression (ParseData *data);
 
 static ViviCodeValue *
-parse_assignment_expression (ParseData *data, ViviCodeStatement **statement);
+parse_assignment_expression (ParseData *data);
 
 static gboolean
 peek_array_literal (ParseData *data)
@@ -901,15 +871,13 @@ peek_array_literal (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_array_literal (ParseData *data, ViviCodeStatement **statement)
+parse_array_literal (ParseData *data)
 {
   ViviCodeValue *value, *member;
-  ViviCodeStatement *statement_new;
 
   vivi_parser_start_code_token (data);
 
   value = vivi_code_init_array_new ();
-  *statement = NULL;
 
   parse_token (data, TOKEN_BRACKET_LEFT);
 
@@ -924,12 +892,9 @@ parse_array_literal (ParseData *data, ViviCodeStatement **statement)
     }
     else if (peek_assignment_expression (data))
     {
-      member = parse_assignment_expression (data, &statement_new);
+      member = parse_assignment_expression (data);
 
-      *statement = vivi_parser_join_statements (*statement, statement_new);
-
-      vivi_code_init_array_add_variable (VIVI_CODE_INIT_ARRAY (value),
-	  member);
+      vivi_code_init_array_add_variable (VIVI_CODE_INIT_ARRAY (value), member);
       g_object_unref (member);
 
       if (!try_parse_token (data, TOKEN_COMMA)) {
@@ -958,27 +923,23 @@ peek_object_literal (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_object_literal (ParseData *data, ViviCodeStatement **statement)
+parse_object_literal (ParseData *data)
 {
   ViviCodeValue *value;
 
   vivi_parser_start_code_token (data);
 
   value = vivi_code_init_object_new ();
-  *statement = NULL;
 
   parse_token (data, TOKEN_BRACE_LEFT);
 
   if (!peek_token (data, TOKEN_BRACE_RIGHT)) {
     do {
       ViviCodeValue *property, *initializer;
-      ViviCodeStatement *statement_new;
 
       property = parse_property_name (data);
       parse_token (data, TOKEN_COLON);
-      initializer = parse_assignment_expression (data, &statement_new);
-
-      *statement = vivi_parser_join_statements (*statement, statement_new);
+      initializer = parse_assignment_expression (data);
 
       vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (value),
 	  property, initializer);
@@ -1012,7 +973,7 @@ parse_variable_declaration (ParseData *data)
   identifier = g_strdup (parse_identifier_value (data));
 
   if (try_parse_token (data, TOKEN_ASSIGN)) {
-    value = parse_assignment_expression (data, &statement_right);
+    value = parse_assignment_expression (data);
   } else {
     vivi_parser_start_code_token (data);
 
@@ -1028,7 +989,7 @@ parse_variable_declaration (ParseData *data)
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (variable));
 
-  return vivi_parser_join_statements (statement_right, variable);
+  return variable;
 }
 
 // asm functions
@@ -1270,21 +1231,19 @@ parse_get_url2 (ParseData *data, gboolean require_two, gboolean level,
     gboolean internal, gboolean variables)
 {
   ViviCodeValue *url, *target;
-  ViviCodeStatement *statement, *expression_statement;
+  ViviCodeStatement *statement;
   SwfdecLoaderRequest method;
 
   parse_token (data, TOKEN_PARENTHESIS_LEFT);
 
-  url = parse_assignment_expression (data, &statement);
+  url = parse_assignment_expression (data);
 
   if (require_two || peek_token (data, TOKEN_COMMA)) {
     parse_token (data, TOKEN_COMMA);
 
     // target
     if (!level) {
-      target = parse_assignment_expression (data, &expression_statement);
-      statement =
-	vivi_parser_join_statements (statement, expression_statement);
+      target = parse_assignment_expression (data);
     } else {
       // FIXME: integer only
       if (peek_numeric (data)) {
@@ -1294,9 +1253,7 @@ parse_get_url2 (ParseData *data, gboolean require_two, gboolean level,
 	g_free (level_name);
       } else {
 	// TODO
-	target = parse_assignment_expression (data, &expression_statement);
-	statement =
-	  vivi_parser_join_statements (statement, expression_statement);
+	target = parse_assignment_expression (data);
       }
     }
 
@@ -1374,20 +1331,14 @@ parse_load_variables_num (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_concat (ParseData *data, ViviCodeStatement **statement)
+parse_concat (ParseData *data)
 {
   ViviCodeValue *value, *first, *second;
-  ViviCodeStatement *expression_statement;
 
   parse_token (data, TOKEN_PARENTHESIS_LEFT);
-
-  first = parse_assignment_expression (data, statement);
-
+  first = parse_assignment_expression (data);
   parse_token (data, TOKEN_COMMA);
-
-  second = parse_assignment_expression (data, &expression_statement);
-  *statement = vivi_parser_join_statements (*statement, expression_statement);
-
+  second = parse_assignment_expression (data);
   parse_token (data, TOKEN_PARENTHESIS_RIGHT);
 
   value = vivi_code_concat_new (first, second);
@@ -1398,25 +1349,16 @@ parse_concat (ParseData *data, ViviCodeStatement **statement)
 }
 
 static ViviCodeValue *
-parse_substring (ParseData *data, ViviCodeStatement **statement)
+parse_substring (ParseData *data)
 {
   ViviCodeValue *value, *string, *index_, *count;
-  ViviCodeStatement *expression_statement;
 
   parse_token (data, TOKEN_PARENTHESIS_LEFT);
-
-  string = parse_assignment_expression (data, statement);
-
+  string = parse_assignment_expression (data);
   parse_token (data, TOKEN_COMMA);
-
-  index_ = parse_assignment_expression (data, &expression_statement);
-  *statement = vivi_parser_join_statements (*statement, expression_statement);
-
+  index_ = parse_assignment_expression (data);
   parse_token (data, TOKEN_COMMA);
-
-  count = parse_assignment_expression (data, &expression_statement);
-  *statement = vivi_parser_join_statements (*statement, expression_statement);
-
+  count = parse_assignment_expression (data);
   parse_token (data, TOKEN_PARENTHESIS_RIGHT);
 
   value = vivi_code_substring_new (string, index_, count);
@@ -1428,16 +1370,12 @@ parse_substring (ParseData *data, ViviCodeStatement **statement)
 }
 
 static ViviCodeValue *
-parse_target_path (ParseData *data, ViviCodeStatement **statement)
+parse_target_path (ParseData *data)
 {
   ViviCodeValue *value, *identifier;
 
-  *statement = NULL;
-
   parse_token (data, TOKEN_PARENTHESIS_LEFT);
-
   identifier = parse_identifier (data);
-
   parse_token (data, TOKEN_PARENTHESIS_RIGHT);
 
   value = vivi_code_target_path_new (identifier);
@@ -1485,10 +1423,10 @@ typedef ViviCodeValue *(*NewCallVoid) (void);
 typedef ViviCodeValue *(*NewCallValue) (ViviCodeValue *value);
 
 typedef struct {
-  const char *			name;
-  NewCallVoid			constructor_void;
-  NewCallValue			constructor_value;
-  ParseValueStatementFunction	parse_custom;
+  const char *		name;
+  NewCallVoid		constructor_void;
+  NewCallValue		constructor_value;
+  ParseValueFunction	parse_custom;
 } BuiltinCall;
 
 static const BuiltinCall builtin_calls[] = {
@@ -1533,7 +1471,7 @@ peek_builtin_call (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_builtin_call (ParseData *data, ViviCodeStatement **statement)
+parse_builtin_call (ParseData *data)
 {
   guint i;
   const char *identifier;
@@ -1551,12 +1489,12 @@ parse_builtin_call (ParseData *data, ViviCodeStatement **statement)
   }
 
   if (builtin_calls[i].parse_custom != NULL)
-    return builtin_calls[i].parse_custom (data, statement);
+    return builtin_calls[i].parse_custom (data);
 
   parse_token (data, TOKEN_PARENTHESIS_LEFT);
 
   if (builtin_calls[i].constructor_value != NULL)
-    argument = parse_assignment_expression (data, statement);
+    argument = parse_assignment_expression (data);
 
   parse_token (data, TOKEN_PARENTHESIS_RIGHT);
 
@@ -1603,7 +1541,7 @@ parse_builtin_statement (ParseData *data)
   guint i;
   const char *identifier;
   ViviCodeValue *argument;
-  ViviCodeStatement *statement, *argument_statement;
+  ViviCodeStatement *statement;
 
   identifier = parse_identifier_value (data);
 
@@ -1623,7 +1561,7 @@ parse_builtin_statement (ParseData *data)
   parse_token (data, TOKEN_PARENTHESIS_LEFT);
 
   if (builtin_statements[i].constructor_value != NULL)
-    argument = parse_assignment_expression (data, &argument_statement);
+    argument = parse_assignment_expression (data);
 
   parse_token (data, TOKEN_PARENTHESIS_RIGHT);
 
@@ -1632,7 +1570,6 @@ parse_builtin_statement (ParseData *data)
   if (builtin_statements[i].constructor_value != NULL) {
     statement = builtin_statements[i].constructor_value (argument);
     g_object_unref (argument);
-    statement = vivi_parser_join_statements (argument_statement, statement);
   } else {
     g_assert (builtin_statements[i].constructor_void != NULL);
     statement = builtin_statements[i].constructor_void ();
@@ -1646,13 +1583,12 @@ parse_builtin_statement (ParseData *data)
 static const struct {
   PeekFunction peek;
   ParseValueFunction parse_value;
-  ParseValueStatementFunction parse_value_statement;
 } primary_expression_functions[] = {
-  { peek_object_literal, NULL, parse_object_literal },
-  { peek_array_literal, NULL, parse_array_literal },
-  { peek_identifier, parse_identifier, NULL },
-  { peek_literal, parse_literal, NULL },
-  { NULL, NULL, NULL }
+  { peek_object_literal, parse_object_literal },
+  { peek_array_literal, parse_array_literal },
+  { peek_identifier, parse_identifier },
+  { peek_literal, parse_literal },
+  { NULL, NULL }
 };
 
 static gboolean
@@ -1673,10 +1609,10 @@ peek_primary_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_expression (ParseData *data, ViviCodeStatement **statement);
+parse_expression (ParseData *data);
 
 static ViviCodeValue *
-parse_primary_expression (ParseData *data, ViviCodeStatement **statement)
+parse_primary_expression (ParseData *data)
 {
   ViviCodeValue *value;
   guint i;
@@ -1685,40 +1621,27 @@ parse_primary_expression (ParseData *data, ViviCodeStatement **statement)
 
   if (try_parse_token (data, TOKEN_THIS)) {
     value = vivi_code_get_new_name ("this");
-    *statement = NULL;
-
     vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
-
     return value;
   }
 
   if (try_parse_token (data, TOKEN_PARENTHESIS_LEFT)) {
-    value = parse_expression (data, statement);
+    value = parse_expression (data);
     parse_token (data, TOKEN_PARENTHESIS_RIGHT);
-
     vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
-
     return value;
   }
 
   for (i = 0; primary_expression_functions[i].peek != NULL; i++) {
     if (primary_expression_functions[i].peek (data)) {
-      if (primary_expression_functions[i].parse_value != NULL) {
-	value = primary_expression_functions[i].parse_value (data);
-	*statement = NULL;
-      } else {
-	value = primary_expression_functions[i].parse_value_statement (data,
-	    statement);
-      }
+      value = primary_expression_functions[i].parse_value (data);
       vivi_parser_end_code_token (data, NULL);
-
       return value;
     }
   }
 
   vivi_parser_error_unexpected (data, ERROR_TOKEN_PRIMARY_EXPRESSION);
   value = vivi_code_undefined_new ();
-  *statement = NULL;
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
 
   return value;
@@ -1737,23 +1660,20 @@ peek_member_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_member_expression (ParseData *data, ViviCodeStatement **statement)
+parse_member_expression (ParseData *data)
 {
   ViviCodeValue *value, *member;
-  ViviCodeStatement *statement_member;
 
   vivi_parser_start_code_token (data);
 
   if (peek_primary_expression (data)) {
-    value = parse_primary_expression (data, statement);
+    value = parse_primary_expression (data);
   } else if (peek_function_expression (data)) {
     value = parse_function_expression (data);
-    *statement = NULL;
   } else {
     vivi_parser_error_unexpected_or (data, ERROR_TOKEN_PRIMARY_EXPRESSION,
 	ERROR_TOKEN_FUNCTION_EXPRESSION, TOKEN_NONE);
     value = vivi_code_undefined_new ();
-    *statement = NULL;
 
     vivi_parser_duplicate_code_token (data);
     vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
@@ -1763,10 +1683,7 @@ parse_member_expression (ParseData *data, ViviCodeStatement **statement)
     ViviCodeValue *tmp;
 
     if (try_parse_token (data, TOKEN_BRACKET_LEFT)) {
-      member = parse_expression (data, &statement_member);
-
-      *statement = vivi_parser_join_statements (*statement, statement_member);
-
+      member = parse_expression (data);
       parse_token (data, TOKEN_BRACKET_RIGHT);
     } else if (try_parse_token (data, TOKEN_DOT)) {
       member = parse_identifier (data);
@@ -1795,18 +1712,16 @@ peek_left_hand_side_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_left_hand_side_expression (ParseData *data,
-    ViviCodeStatement **statement)
+parse_left_hand_side_expression (ParseData *data)
 {
   ViviCodeValue *value, *name;
   ViviCodeValue **arguments;
-  ViviCodeStatement *argument_statement;
   guint i;
 
   vivi_parser_start_code_token (data);
 
   if (try_parse_token (data, TOKEN_NEW)) {
-    value = parse_left_hand_side_expression (data, statement);
+    value = parse_left_hand_side_expression (data);
 
     if (!VIVI_IS_CODE_FUNCTION_CALL (value)) {
       ViviCodeValue *tmp = value;
@@ -1823,20 +1738,15 @@ parse_left_hand_side_expression (ParseData *data,
   }
 
   if (peek_builtin_call (data)) {
-    value = parse_builtin_call (data, statement);
+    value = parse_builtin_call (data);
   } else {
-    value = parse_member_expression (data, statement);
+    value = parse_member_expression (data);
   }
 
   while (try_parse_token (data, TOKEN_PARENTHESIS_LEFT)) {
     if (!try_parse_token (data, TOKEN_PARENTHESIS_RIGHT)) {
-      parse_value_statement_list (data, peek_assignment_expression,
-	  parse_assignment_expression, &arguments, &argument_statement,
-	  TOKEN_COMMA);
-
-      *statement =
-	vivi_parser_join_statements (*statement, argument_statement);
-
+      parse_value_list (data, peek_assignment_expression,
+	  parse_assignment_expression, &arguments, TOKEN_COMMA);
       parse_token (data, TOKEN_PARENTHESIS_RIGHT);
     } else {
       arguments = NULL;
@@ -1870,14 +1780,14 @@ peek_postfix_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_postfix_expression (ParseData *data, ViviCodeStatement **statement)
+parse_postfix_expression (ParseData *data)
 {
   ViviCodeValue *assignment, *value, *operation, *one;
   gboolean add;
 
   vivi_parser_start_code_token (data);
 
-  value = parse_left_hand_side_expression (data, statement);
+  value = parse_left_hand_side_expression (data);
 
   if (peek_line_terminator (data)) {
     vivi_parser_end_code_token (data, NULL);
@@ -1937,7 +1847,7 @@ peek_unary_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
+parse_unary_expression (ParseData *data)
 {
   ViviCodeValue *value, *tmp, *one;
   gboolean increment = FALSE;
@@ -1953,7 +1863,7 @@ parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
 
       vivi_parser_scanner_get_next_token (data->scanner);
 
-      value = parse_unary_expression (data, statement);
+      value = parse_unary_expression (data);
 
       // FIXME: Correct?
       if (!vivi_parser_value_is_left_hand_side (value)) {
@@ -1976,7 +1886,7 @@ parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
     case TOKEN_PLUS:
       vivi_parser_scanner_get_next_token (data->scanner);
 
-      value = parse_unary_expression (data, statement);
+      value = parse_unary_expression (data);
 
       if (!VIVI_IS_CODE_NUMBER (value)) {
 	tmp = value;
@@ -1987,7 +1897,7 @@ parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
     case TOKEN_MINUS:
       vivi_parser_scanner_get_next_token (data->scanner);
 
-      value = parse_unary_expression (data, statement);
+      value = parse_unary_expression (data);
 
       if (VIVI_IS_CODE_NUMBER (value)) {
 	tmp = value;
@@ -2014,7 +1924,7 @@ parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
 
       vivi_parser_scanner_get_next_token (data->scanner);
 
-      value = parse_unary_expression (data, statement);
+      value = parse_unary_expression (data);
 
       tmp = VIVI_CODE_VALUE (value);
       value = vivi_code_unary_new (tmp, '!');
@@ -2023,7 +1933,7 @@ parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
       vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (tmp));
       break;
     default:
-      value = parse_postfix_expression (data, statement);
+      value = parse_postfix_expression (data);
       break;
   }
 
@@ -2037,12 +1947,11 @@ typedef enum {
 } ParseOperatorPass;
 
 static ViviCodeValue *
-parse_operator_expression (ParseData *data, ViviCodeStatement **statement,
+parse_operator_expression (ParseData *data,
     const ViviParserScannerToken *tokens, ParseOperatorPass pass,
-    ParseValueStatementFunction next_parse_function)
+    ParseValueFunction next_parse_function)
 {
   ViviCodeValue *value, *left, *right;
-  ViviCodeStatement *statement_right;
   guint i, j;
   static const struct {
     ViviParserScannerToken	token;
@@ -2082,38 +1991,12 @@ parse_operator_expression (ParseData *data, ViviCodeStatement **statement,
 
   vivi_parser_start_code_token (data);
 
-  value = next_parse_function (data, statement);
+  value = next_parse_function (data);
 
 again:
   for (i = 0; tokens[i] != TOKEN_NONE; i++) {
     if (try_parse_token (data, tokens[i])) {
-      right = next_parse_function (data, &statement_right);
-
-      if (statement_right != NULL) {
-	ViviCodeStatement *tmp;
-
-	switch (pass) {
-	  case PASS_LOGICAL_OR:
-	    tmp = vivi_code_if_new (vivi_code_unary_new (value, '!'));
-	    vivi_code_if_set_if (VIVI_CODE_IF (tmp), statement_right);
-	    g_object_unref (statement_right);
-	    statement_right = tmp;
-	    break;
-	  case PASS_LOGICAL_AND:
-	    tmp = vivi_code_if_new (value);
-	    vivi_code_if_set_if (VIVI_CODE_IF (tmp), statement_right);
-	    g_object_unref (statement_right);
-	    statement_right = tmp;
-	    break;
-	  case PASS_ALWAYS:
-	    // nothing
-	    break;
-	  default:
-	    g_assert_not_reached ();
-	}
-
-	*statement = vivi_parser_join_statements (*statement, statement_right);
-      }
+      right = next_parse_function (data);
 
       left = VIVI_CODE_VALUE (value);
       for (j = 0; j < G_N_ELEMENTS (table); j++) {
@@ -2157,13 +2040,12 @@ peek_multiplicative_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_multiplicative_expression (ParseData *data,
-    ViviCodeStatement **statement)
+parse_multiplicative_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_MULTIPLY,
     TOKEN_DIVIDE, TOKEN_REMAINDER, TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_ALWAYS,
+  return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_unary_expression);
 }
 
@@ -2174,12 +2056,12 @@ peek_additive_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_additive_expression (ParseData *data, ViviCodeStatement **statement)
+parse_additive_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_PLUS, TOKEN_MINUS,
     TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_ALWAYS,
+  return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_multiplicative_expression);
 }
 
@@ -2190,12 +2072,12 @@ peek_shift_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_shift_expression (ParseData *data, ViviCodeStatement **statement)
+parse_shift_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_SHIFT_LEFT,
     TOKEN_SHIFT_RIGHT, TOKEN_SHIFT_RIGHT_UNSIGNED, TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_ALWAYS,
+  return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_additive_expression);
 }
 
@@ -2206,13 +2088,13 @@ peek_relational_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_relational_expression (ParseData *data, ViviCodeStatement **statement)
+parse_relational_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_LESS_THAN,
     TOKEN_GREATER_THAN, TOKEN_LESS_THAN_OR_EQUAL,
     TOKEN_EQUAL_OR_GREATER_THAN, TOKEN_INSTANCEOF, /*TOKEN_IN,*/ TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_ALWAYS,
+  return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_shift_expression);
 }
 
@@ -2223,13 +2105,13 @@ peek_equality_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_equality_expression (ParseData *data, ViviCodeStatement **statement)
+parse_equality_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_EQUAL,
     TOKEN_NOT_EQUAL, TOKEN_STRICT_EQUAL, TOKEN_NOT_STRICT_EQUAL,
     TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_ALWAYS,
+  return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_relational_expression);
 }
 
@@ -2240,12 +2122,12 @@ peek_bitwise_and_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_bitwise_and_expression (ParseData *data, ViviCodeStatement **statement)
+parse_bitwise_and_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_BITWISE_AND,
     TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_ALWAYS,
+  return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_equality_expression);
 }
 
@@ -2256,12 +2138,12 @@ peek_bitwise_xor_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_bitwise_xor_expression (ParseData *data, ViviCodeStatement **statement)
+parse_bitwise_xor_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_BITWISE_XOR,
     TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_ALWAYS,
+  return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_bitwise_and_expression);
 }
 
@@ -2272,12 +2154,12 @@ peek_bitwise_or_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_bitwise_or_expression (ParseData *data, ViviCodeStatement **statement)
+parse_bitwise_or_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_BITWISE_OR,
     TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_ALWAYS,
+  return parse_operator_expression (data, tokens, PASS_ALWAYS,
       parse_bitwise_xor_expression);
 }
 
@@ -2288,12 +2170,12 @@ peek_logical_and_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_logical_and_expression (ParseData *data, ViviCodeStatement **statement)
+parse_logical_and_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_LOGICAL_AND,
     TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_LOGICAL_AND,
+  return parse_operator_expression (data, tokens, PASS_LOGICAL_AND,
       parse_bitwise_or_expression);
 }
 
@@ -2304,12 +2186,12 @@ peek_logical_or_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_logical_or_expression (ParseData *data, ViviCodeStatement **statement)
+parse_logical_or_expression (ParseData *data)
 {
   static const ViviParserScannerToken tokens[] = { TOKEN_LOGICAL_OR,
     TOKEN_NONE };
 
-  return parse_operator_expression (data, statement, tokens, PASS_LOGICAL_OR,
+  return parse_operator_expression (data, tokens, PASS_LOGICAL_OR,
       parse_logical_and_expression);
 }
 
@@ -2320,46 +2202,10 @@ peek_conditional_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_conditional_expression (ParseData *data, ViviCodeStatement **statement)
+parse_conditional_expression (ParseData *data)
 {
-  //ViviCodeStatement *if_statement, *else_statement;
-
-  return parse_logical_or_expression (data, statement);
-
-#if 0
-  if (!parse_token (data, TOKEN_QUESTION_MARK)) {
-    *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
-    g_object_unref (value);
-    return TRUE;
-  }
-
-  status = parse_assignment_expression (data, &if_statement);
-  if (status != TRUE) {
-    g_object_unref (value);
-    return FAIL_CHILD (status);
-  }
-
-  if (!parse_token (data, TOKEN_COLON)) {
-    g_object_unref (value);
-    g_object_unref (if_statement);
-    return TOKEN_COLON;
-  }
-
-  status = parse_assignment_expression (data, &else_statement);
-  if (status != TRUE) {
-    g_object_unref (value);
-    g_object_unref (if_statement);
-    return FAIL_CHILD (status);
-  }
-
-  *statement = vivi_code_if_new (value);
-  vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
-  vivi_code_if_set_else (VIVI_CODE_IF (*statement), else_statement);
-
-  g_object_unref (value);
-  g_object_unref (if_statement);
-  g_object_unref (else_statement);
-#endif
+  // TODO
+  return parse_logical_or_expression (data);
 }
 
 static gboolean
@@ -2369,15 +2215,14 @@ peek_assignment_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_assignment_expression (ParseData *data, ViviCodeStatement **statement)
+parse_assignment_expression (ParseData *data)
 {
   ViviCodeValue *value, *assignment, *right;
-  ViviCodeStatement *statement_right;
   ViviCodeValue * (* func) (ViviCodeValue *, ViviCodeValue *);
 
   vivi_parser_start_code_token (data);
 
-  value = parse_conditional_expression (data, statement);
+  value = parse_conditional_expression (data);
 
   // FIXME: Correct?
   if (!vivi_parser_value_is_left_hand_side (value)) {
@@ -2428,7 +2273,7 @@ parse_assignment_expression (ParseData *data, ViviCodeStatement **statement)
 
   vivi_parser_scanner_get_next_token (data->scanner);
 
-  right = parse_assignment_expression (data, &statement_right);
+  right = parse_assignment_expression (data);
 
   if (func != NULL) {
     assignment = vivi_parser_assignment_new (value, func (value, right));
@@ -2440,8 +2285,6 @@ parse_assignment_expression (ParseData *data, ViviCodeStatement **statement)
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (assignment));
 
-  *statement = vivi_parser_join_statements (*statement, statement_right);
-
   return assignment;
 }
 
@@ -2452,19 +2295,16 @@ peek_expression (ParseData *data)
 }
 
 static ViviCodeValue *
-parse_expression (ParseData *data, ViviCodeStatement **statement)
+parse_expression (ParseData *data)
 {
   ViviCodeValue *value;
-  ViviCodeStatement *statement_one;
 
   value = NULL;
-  *statement = NULL;
 
   do {
     if (value != NULL)
       g_object_unref (value);
-    value = parse_assignment_expression (data, &statement_one);
-    *statement = vivi_parser_join_statements (*statement, statement_one);
+    value = parse_assignment_expression (data);
   } while (try_parse_token (data, TOKEN_COMMA));
 
   return value;
@@ -2532,7 +2372,7 @@ static ViviCodeStatement *
 parse_throw_statement (ParseData *data)
 {
   ViviCodeValue *value;
-  ViviCodeStatement *statement, *expression_statement;
+  ViviCodeStatement *statement;
 
   parse_token (data, TOKEN_THROW);
 
@@ -2541,13 +2381,11 @@ parse_throw_statement (ParseData *data)
 	ERROR_TOKEN_EXPRESSION);
   }
 
-  value = parse_expression (data, &expression_statement);
+  value = parse_expression (data);
 
   statement = vivi_code_throw_new (value);
   g_object_unref (value);
 
-  statement = vivi_parser_join_statements (expression_statement, statement);
-
   parse_automatic_semicolon (data);
 
   return statement;
@@ -2570,15 +2408,12 @@ parse_return_statement (ParseData *data)
 
   if (!try_parse_restricted_semicolon (data)) {
     ViviCodeValue *value;
-    ViviCodeStatement *expression_statement;
 
-    value = parse_expression (data, &expression_statement);
+    value = parse_expression (data);
 
     vivi_code_return_set_value (VIVI_CODE_RETURN (statement), value);
     g_object_unref (value);
 
-    statement = vivi_parser_join_statements (expression_statement, statement);
-
     parse_automatic_semicolon (data);
   }
 
@@ -2603,14 +2438,14 @@ parse_iteration_statement (ParseData *data)
 {
   ViviCodeValue *condition;
   ViviCodeStatement *statement;
-  ViviCodeStatement *pre_statement, *condition_statement, *loop_statement;
+  ViviCodeStatement *pre_statement, *loop_statement;
 
   if (try_parse_token (data, TOKEN_DO))
   {
     loop_statement = parse_statement (data);
     parse_token (data, TOKEN_WHILE);
     parse_token (data, TOKEN_PARENTHESIS_LEFT);
-    condition = parse_expression (data, &condition_statement);
+    condition = parse_expression (data);
     parse_token (data, TOKEN_PARENTHESIS_RIGHT);
     parse_automatic_semicolon (data);
 
@@ -2619,7 +2454,7 @@ parse_iteration_statement (ParseData *data)
   else if (try_parse_token (data, TOKEN_WHILE))
   {
     parse_token (data, TOKEN_PARENTHESIS_LEFT);
-    condition = parse_expression (data, &condition_statement);
+    condition = parse_expression (data);
     parse_token (data, TOKEN_PARENTHESIS_RIGHT);
     loop_statement = parse_statement (data);
 
@@ -2628,7 +2463,6 @@ parse_iteration_statement (ParseData *data)
   else if (try_parse_token (data, TOKEN_FOR))
   {
     ViviCodeValue *pre_value;
-    ViviCodeStatement *post_statement;
 
     parse_token (data, TOKEN_PARENTHESIS_LEFT);
 
@@ -2654,7 +2488,8 @@ parse_iteration_statement (ParseData *data)
 	pre_statement = NULL;
       } else {
 	// FIXME: no in
-	pre_value = parse_expression (data, &pre_statement);
+	pre_value = parse_expression (data);
+	pre_statement = NULL;
       }
     }
 
@@ -2664,21 +2499,16 @@ parse_iteration_statement (ParseData *data)
 
       if (try_parse_token (data, TOKEN_SEMICOLON)) {
 	condition = vivi_code_boolean_new (TRUE);
-	condition_statement = NULL;
       } else {
-	condition = parse_expression (data, &condition_statement);
+	condition = parse_expression (data);
 	parse_token (data, TOKEN_SEMICOLON);
       }
 
-      if (peek_token (data, TOKEN_PARENTHESIS_RIGHT)) {
-	post_statement = NULL;
-      } else {
-	pre_value = parse_expression (data, &post_statement);
+      if (!peek_token (data, TOKEN_PARENTHESIS_RIGHT)) {
+	pre_value = parse_expression (data);
 	g_object_unref (pre_value);
       }
     } else if (pre_value != NULL && try_parse_token (data, TOKEN_IN)) {
-      post_statement = NULL;
-
       // FIXME: correct?
       if (!vivi_parser_value_is_left_hand_side (pre_value))
 	vivi_parser_error (data, "Invalid left-hand side expression for in");
@@ -2690,8 +2520,6 @@ parse_iteration_statement (ParseData *data)
       vivi_parser_error (data, "for (... in ...) has not been implemented yet");
 
       condition = vivi_code_undefined_new ();
-      condition_statement = NULL;
-      post_statement = NULL;
     } else {
       if (pre_value != NULL) {
 	vivi_parser_error_unexpected_or (data, TOKEN_SEMICOLON, TOKEN_IN,
@@ -2701,8 +2529,6 @@ parse_iteration_statement (ParseData *data)
       }
 
       condition = vivi_code_undefined_new ();
-      condition_statement = NULL;
-      post_statement = NULL;
 
       if (pre_value != NULL)
 	g_object_unref (pre_value);
@@ -2712,9 +2538,6 @@ parse_iteration_statement (ParseData *data)
 
     parse_token (data, TOKEN_PARENTHESIS_RIGHT);
     loop_statement = parse_statement (data);
-
-    loop_statement =
-      vivi_parser_join_statements (loop_statement, post_statement);
   }
   else
   {
@@ -2722,18 +2545,9 @@ parse_iteration_statement (ParseData *data)
 
     condition = vivi_code_undefined_new ();
     pre_statement = NULL;
-    condition_statement = NULL;
     loop_statement = vivi_compiler_empty_statement_new ();
   }
 
-  if (condition_statement != NULL) {
-    pre_statement = vivi_parser_join_statements (pre_statement,
-	g_object_ref (condition_statement));
-    loop_statement = vivi_parser_join_statements (loop_statement,
-	g_object_ref (condition_statement));
-    g_object_unref (condition_statement);
-  }
-
   statement = vivi_code_loop_new ();
   vivi_code_loop_set_condition (VIVI_CODE_LOOP (statement), condition);
   g_object_unref (condition);
@@ -2764,11 +2578,11 @@ static ViviCodeStatement *
 parse_if_statement (ParseData *data)
 {
   ViviCodeValue *condition;
-  ViviCodeStatement *statement, *pre_statement, *if_statement, *else_statement;
+  ViviCodeStatement *statement, *if_statement, *else_statement;
 
   parse_token (data, TOKEN_IF);
   parse_token (data, TOKEN_PARENTHESIS_LEFT);
-  condition = parse_expression (data, &pre_statement);
+  condition = parse_expression (data);
   parse_token (data, TOKEN_PARENTHESIS_RIGHT);
   if_statement = parse_statement (data);
 
@@ -2789,8 +2603,6 @@ parse_if_statement (ParseData *data)
     g_object_unref (else_statement);
   }
 
-  statement = vivi_parser_join_statements (pre_statement, statement);
-
   return statement;
 }
 
@@ -2807,39 +2619,15 @@ static ViviCodeStatement *
 parse_expression_statement (ParseData *data)
 {
   ViviCodeValue *value;
-  ViviCodeStatement *statement, *last;
 
   if (peek_token (data, TOKEN_BRACE_LEFT) || peek_token (data, TOKEN_FUNCTION))
     vivi_parser_error_unexpected (data, ERROR_TOKEN_EXPRESSION_STATEMENT);
 
-  value = parse_expression (data, &statement);
+  value = parse_expression (data);
 
   parse_automatic_semicolon (data);
 
-  // add a value statement, if the last statement is not an assignment with the
-  // same value
-  if (VIVI_IS_CODE_BLOCK (statement)) {
-    ViviCodeBlock *block = VIVI_CODE_BLOCK (statement);
-
-    last = vivi_code_block_get_statement (block,
-	vivi_code_block_get_n_statements (block) - 1);
-  } else {
-    last = statement;
-  }
-
-  if (VIVI_IS_CODE_ASSIGNMENT (last) && VIVI_IS_CODE_GET (value)) {
-    ViviCodeAssignment *assignment = VIVI_CODE_ASSIGNMENT (last);
-
-    if (assignment->from == NULL && assignment->name == VIVI_CODE_GET (value)->name) {
-      g_object_unref (value);
-      return statement;
-    }
-  }
-
-  statement = vivi_parser_join_statements (statement,
-      VIVI_CODE_STATEMENT (value));
-
-  return statement;
+  return VIVI_CODE_STATEMENT (value);
 }
 
 static gboolean
@@ -3165,28 +2953,22 @@ parse_statement_list (ParseData *data, PeekFunction peek,
 }
 
 static void
-parse_value_statement_list (ParseData *data, PeekFunction peek,
-    ParseValueStatementFunction parse, ViviCodeValue ***list,
-    ViviCodeStatement **statement, guint separator)
+parse_value_list (ParseData *data, PeekFunction peek, ParseValueFunction parse,
+    ViviCodeValue ***list, guint separator)
 {
   GPtrArray *array;
   ViviCodeValue *value;
-  ViviCodeStatement *statement_one;
 
   g_assert (data != NULL);
   g_assert (peek != NULL);
   g_assert (parse != NULL);
   g_assert (list != NULL);
-  g_assert (statement != NULL);
-
-  *statement = NULL;
 
   array = g_ptr_array_new ();
 
   do {
-    value = parse (data, &statement_one);
+    value = parse (data);
     g_ptr_array_add (array, value);
-    *statement = vivi_parser_join_statements (*statement, statement_one);
   } while ((separator == TOKEN_NONE || try_parse_token (data, separator)) &&
       peek (data));
 
commit 51ca93102620ad437a57c92a677302285ce82216
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 16:37:03 2008 +0300

    Remove ViviCodeValueStatement that is not needed anymore

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index c25a477..f001408 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -88,7 +88,6 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_unary.c \
 	vivi_code_undefined.c \
 	vivi_code_value.c \
-	vivi_code_value_statement.c \
 	vivi_code_variable.c \
 	vivi_compiler_empty_statement.c \
 	vivi_compiler_get_temporary.c \
@@ -166,7 +165,6 @@ noinst_HEADERS = \
 	vivi_code_unary.h \
 	vivi_code_undefined.h \
 	vivi_code_value.h \
-	vivi_code_value_statement.h \
 	vivi_code_variable.h \
 	vivi_compiler_empty_statement.h \
 	vivi_compiler_get_temporary.h \
diff --git a/vivified/code/vivi_code_value_statement.c b/vivified/code/vivi_code_value_statement.c
deleted file mode 100644
index 18cff57..0000000
--- a/vivified/code/vivi_code_value_statement.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "vivi_code_value_statement.h"
-#include "vivi_code_printer.h"
-#include "vivi_code_compiler.h"
-#include "vivi_code_asm.h"
-#include "vivi_code_asm_code_default.h"
-
-G_DEFINE_TYPE (ViviCodeValueStatement, vivi_code_value_statement, VIVI_TYPE_CODE_STATEMENT)
-
-static void
-vivi_code_value_statement_dispose (GObject *object)
-{
-  ViviCodeValueStatement *stmt = VIVI_CODE_VALUE_STATEMENT (object);
-
-  g_object_unref (stmt->value);
-
-  G_OBJECT_CLASS (vivi_code_value_statement_parent_class)->dispose (object);
-}
-
-static void
-vivi_code_value_statement_print (ViviCodeToken *token, ViviCodePrinter *printer)
-{
-  ViviCodeValueStatement *stmt = VIVI_CODE_VALUE_STATEMENT (token);
-
-  vivi_code_printer_print_token (printer, VIVI_CODE_TOKEN (stmt->value));
-  vivi_code_printer_print (printer, ";");
-  vivi_code_printer_new_line (printer, FALSE);
-}
-
-static void
-vivi_code_value_statement_compile (ViviCodeToken *token,
-    ViviCodeCompiler *compiler)
-{
-  ViviCodeValueStatement *stmt = VIVI_CODE_VALUE_STATEMENT (token);
-
-  vivi_code_compiler_compile_value (compiler, stmt->value);
-  vivi_code_compiler_take_code (compiler, vivi_code_asm_pop_new ());
-}
-
-static void
-vivi_code_value_statement_class_init (ViviCodeValueStatementClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
-
-  object_class->dispose = vivi_code_value_statement_dispose;
-
-  token_class->print = vivi_code_value_statement_print;
-  token_class->compile = vivi_code_value_statement_compile;
-}
-
-static void
-vivi_code_value_statement_init (ViviCodeValueStatement *token)
-{
-}
-
-ViviCodeStatement *
-vivi_code_value_statement_new (ViviCodeValue *value)
-{
-  ViviCodeValueStatement *stmt;
-
-  g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
-
-  stmt = g_object_new (VIVI_TYPE_CODE_VALUE_STATEMENT, NULL);
-  stmt->value = g_object_ref (value);
-
-  return VIVI_CODE_STATEMENT (stmt);
-}
-
-ViviCodeValue *
-vivi_code_value_statement_get_value (ViviCodeValueStatement *stmt)
-{
-  g_return_val_if_fail (VIVI_IS_CODE_VALUE_STATEMENT (stmt), NULL);
-
-  return stmt->value;
-}
-
diff --git a/vivified/code/vivi_code_value_statement.h b/vivified/code/vivi_code_value_statement.h
deleted file mode 100644
index 27d42e3..0000000
--- a/vivified/code/vivi_code_value_statement.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _VIVI_CODE_VALUE_STATEMENT_H_
-#define _VIVI_CODE_VALUE_STATEMENT_H_
-
-#include <vivified/code/vivi_code_statement.h>
-#include <vivified/code/vivi_code_value.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _ViviCodeValueStatement ViviCodeValueStatement;
-typedef struct _ViviCodeValueStatementClass ViviCodeValueStatementClass;
-
-#define VIVI_TYPE_CODE_VALUE_STATEMENT                    (vivi_code_value_statement_get_type())
-#define VIVI_IS_CODE_VALUE_STATEMENT(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_VALUE_STATEMENT))
-#define VIVI_IS_CODE_VALUE_STATEMENT_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_VALUE_STATEMENT))
-#define VIVI_CODE_VALUE_STATEMENT(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_VALUE_STATEMENT, ViviCodeValueStatement))
-#define VIVI_CODE_VALUE_STATEMENT_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_VALUE_STATEMENT, ViviCodeValueStatementClass))
-#define VIVI_CODE_VALUE_STATEMENT_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_VALUE_STATEMENT, ViviCodeValueStatementClass))
-
-struct _ViviCodeValueStatement
-{
-  ViviCodeStatement	statement;
-
-  ViviCodeValue *	value;
-};
-
-struct _ViviCodeValueStatementClass
-{
-  ViviCodeStatementClass	statement_class;
-};
-
-GType			vivi_code_value_statement_get_type   	(void);
-
-ViviCodeStatement *   	vivi_code_value_statement_new		(ViviCodeValue *	value);
-
-ViviCodeValue *   	vivi_code_value_statement_get_value	(ViviCodeValueStatement *stmt);
-
-
-G_END_DECLS
-#endif
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index 5c2a7b5..8f95b4f 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -52,7 +52,6 @@
 #include "vivi_code_string.h"
 #include "vivi_code_unary.h"
 #include "vivi_code_undefined.h"
-#include "vivi_code_value_statement.h"
 #include "vivi_code_variable.h"
 #include "vivi_decompiler_block.h"
 #include "vivi_decompiler_duplicate.h"
@@ -214,14 +213,12 @@ static gboolean
 vivi_decompile_pop (ViviDecompilerBlock *block, ViviDecompilerState *state,
     guint code, const guint8 *data, guint len)
 {
-  ViviCodeStatement *stmt;
   ViviCodeValue *val;
-  
+
   val = vivi_decompiler_state_pop (state);
-  stmt = vivi_code_value_statement_new (val);
+  vivi_code_block_add_statement (VIVI_CODE_BLOCK (block),
+      VIVI_CODE_STATEMENT (val));
   g_object_unref (val);
-  vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), stmt);
-  g_object_unref (stmt);
   return TRUE;
 }
 
@@ -1121,9 +1118,7 @@ vivi_decompiler_merge_andor (GList **list)
       case 1:
 	{
 	  ViviCodeStatement *stmt = vivi_code_block_get_statement (VIVI_CODE_BLOCK (andor), 0);
-	  if (!VIVI_IS_CODE_VALUE_STATEMENT (stmt))
-	    continue;
-	  if (value != vivi_code_value_statement_get_value (VIVI_CODE_VALUE_STATEMENT (stmt)))
+	  if (!VIVI_IS_CODE_VALUE (stmt))
 	    continue;
 	}
 	break;
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 2c3d211..4c15c9d 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -63,7 +63,6 @@
 #include "vivi_code_throw.h"
 #include "vivi_code_unary.h"
 #include "vivi_code_undefined.h"
-#include "vivi_code_value_statement.h"
 #include "vivi_code_variable.h"
 #include "vivi_compiler_empty_statement.h"
 #include "vivi_compiler_get_temporary.h"
@@ -2838,8 +2837,7 @@ parse_expression_statement (ParseData *data)
   }
 
   statement = vivi_parser_join_statements (statement,
-      vivi_code_value_statement_new (value));
-  g_object_unref (value);
+      VIVI_CODE_STATEMENT (value));
 
   return statement;
 }
commit 0ae5fb47675d38b6bf1d26fae199505dc4b3454a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 16:32:24 2008 +0300

    Make ViviCodeAssignment a value. Split local variables to ViviCodeAssignment

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index cd811f8..c25a477 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -89,6 +89,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_undefined.c \
 	vivi_code_value.c \
 	vivi_code_value_statement.c \
+	vivi_code_variable.c \
 	vivi_compiler_empty_statement.c \
 	vivi_compiler_get_temporary.c \
 	vivi_compiler_goto_name.c \
@@ -166,6 +167,7 @@ noinst_HEADERS = \
 	vivi_code_undefined.h \
 	vivi_code_value.h \
 	vivi_code_value_statement.h \
+	vivi_code_variable.h \
 	vivi_compiler_empty_statement.h \
 	vivi_compiler_get_temporary.h \
 	vivi_compiler_goto_name.h \
diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index 7b4d3c1..b0ff354 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -29,7 +29,7 @@
 #include "vivi_code_compiler.h"
 #include "vivi_code_asm_code_default.h"
 
-G_DEFINE_TYPE (ViviCodeAssignment, vivi_code_assignment, VIVI_TYPE_CODE_STATEMENT)
+G_DEFINE_TYPE (ViviCodeAssignment, vivi_code_assignment, VIVI_TYPE_CODE_VALUE)
 
 static void
 vivi_code_assignment_dispose (GObject *object)
@@ -56,9 +56,6 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
     varname = NULL;
   }
 
-  if (assignment->local)
-    vivi_code_printer_print (printer, "var ");
-
   if (assignment->from) {
     vivi_code_printer_print_value (printer, assignment->from, VIVI_PRECEDENCE_MEMBER);
     if (varname) {
@@ -78,17 +75,14 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
       vivi_code_printer_print (printer, ", ");
       vivi_code_printer_print_value (printer, assignment->value, VIVI_PRECEDENCE_ASSIGNMENT);
       vivi_code_printer_print (printer, ")");
-      goto finalize;
+      return;
     }
   }
-  if (!assignment->local || !VIVI_IS_CODE_UNDEFINED (assignment->value)) {
-    vivi_code_printer_print (printer, " = ");
-    vivi_code_printer_print_value (printer, assignment->value, VIVI_PRECEDENCE_ASSIGNMENT);
-  }
+
+  vivi_code_printer_print (printer, " = ");
+  vivi_code_printer_print_value (printer, assignment->value, VIVI_PRECEDENCE_ASSIGNMENT);
+
   g_free (varname);
-finalize:
-  vivi_code_printer_print (printer, ";");
-  vivi_code_printer_new_line (printer, FALSE);
 }
 
 static void
@@ -97,22 +91,12 @@ vivi_code_assignment_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   ViviCodeAssignment *assignment = VIVI_CODE_ASSIGNMENT (token);
   ViviCodeAsm *code;
 
-  if (assignment->from && !assignment->local)
+  if (assignment->from)
     vivi_code_compiler_compile_value (compiler, assignment->from);
   vivi_code_compiler_compile_value (compiler, assignment->name);
+  vivi_code_compiler_compile_value (compiler, assignment->value);
 
-  if (assignment->local && assignment->from) {
-    ViviCodeValue *get =
-      vivi_code_get_new (assignment->from, assignment->value);
-    vivi_code_compiler_compile_value (compiler, get);
-    g_object_unref (get);
-  } else {
-    vivi_code_compiler_compile_value (compiler, assignment->value);
-  }
-
-  if (assignment->local) {
-    code = vivi_code_asm_define_local_new ();
-  } else if (assignment->from) {
+  if (assignment->from) {
     code = vivi_code_asm_set_member_new ();
   } else {
     code = vivi_code_asm_set_variable_new ();
@@ -121,15 +105,42 @@ vivi_code_assignment_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 }
 
 static void
+vivi_code_assignment_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
+{
+  ViviCodeAssignment *assignment = VIVI_CODE_ASSIGNMENT (value);
+
+  if (assignment->from)
+    vivi_code_compiler_compile_value (compiler, assignment->from);
+  vivi_code_compiler_compile_value (compiler, assignment->name);
+  vivi_code_compiler_compile_value (compiler, assignment->value);
+
+
+  if (assignment->from) {
+    // TODO
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_member_new ());
+    g_assert_not_reached ();
+  } else {
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_push_duplicate_new ());
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_swap_new ());
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_set_variable_new ());
+  }
+}
+
+static void
 vivi_code_assignment_class_init (ViviCodeAssignmentClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_assignment_dispose;
 
   token_class->print = vivi_code_assignment_print;
   token_class->compile = vivi_code_assignment_compile;
+
+  value_class->compile_value = vivi_code_assignment_compile_value;
 }
 
 static void
@@ -137,7 +148,7 @@ vivi_code_assignment_init (ViviCodeAssignment *assignment)
 {
 }
 
-ViviCodeStatement *
+ViviCodeValue *
 vivi_code_assignment_new (ViviCodeValue *from, ViviCodeValue *name, ViviCodeValue *value)
 {
   ViviCodeAssignment *assignment;
@@ -152,14 +163,13 @@ vivi_code_assignment_new (ViviCodeValue *from, ViviCodeValue *name, ViviCodeValu
   assignment->name = g_object_ref (name);
   assignment->value = g_object_ref (value);
 
-  return VIVI_CODE_STATEMENT (assignment);
+  return VIVI_CODE_VALUE (assignment);
 }
 
-ViviCodeStatement *
+ViviCodeValue *
 vivi_code_assignment_new_name (const char *name, ViviCodeValue *value)
 {
-  ViviCodeValue *constant;
-  ViviCodeStatement *result;
+  ViviCodeValue *constant, *result;
 
   g_return_val_if_fail (name != NULL, NULL);
   g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
@@ -167,16 +177,6 @@ vivi_code_assignment_new_name (const char *name, ViviCodeValue *value)
   constant = vivi_code_string_new (name);
   result = vivi_code_assignment_new (NULL, constant, value);
   g_object_unref (constant);
-  return result;
-}
 
-void
-vivi_code_assignment_set_local (ViviCodeAssignment *assign, gboolean local)
-{
-  g_return_if_fail (VIVI_IS_CODE_ASSIGNMENT (assign));
-  /* can't assign to non-local variables */
-  g_return_if_fail (assign->from == NULL);
-
-  assign->local = local;
+  return result;
 }
-
diff --git a/vivified/code/vivi_code_assignment.h b/vivified/code/vivi_code_assignment.h
index 411c89a..a09d09c 100644
--- a/vivified/code/vivi_code_assignment.h
+++ b/vivified/code/vivi_code_assignment.h
@@ -20,7 +20,7 @@
 #ifndef _VIVI_CODE_ASSIGNMENT_H_
 #define _VIVI_CODE_ASSIGNMENT_H_
 
-#include <vivified/code/vivi_code_statement.h>
+#include <vivified/code/vivi_code_value.h>
 #include <vivified/code/vivi_code_value.h>
 
 G_BEGIN_DECLS
@@ -38,30 +38,26 @@ typedef struct _ViviCodeAssignmentClass ViviCodeAssignmentClass;
 
 struct _ViviCodeAssignment
 {
-  ViviCodeStatement	statement;
+  ViviCodeValue		token;
 
   ViviCodeValue *	from;
   ViviCodeValue *	name;
   ViviCodeValue	*	value;
-  gboolean		local;
 };
 
 struct _ViviCodeAssignmentClass
 {
-  ViviCodeStatementClass	value_class;
+  ViviCodeValueClass	value_class;
 };
 
-GType			vivi_code_assignment_get_type   	(void);
+GType			vivi_code_assignment_get_type		(void);
 
-ViviCodeStatement *	vivi_code_assignment_new		(ViviCodeValue *	from,
+ViviCodeValue *		vivi_code_assignment_new		(ViviCodeValue *	from,
 								 ViviCodeValue *	name,
 								 ViviCodeValue *	value);
-ViviCodeStatement *	vivi_code_assignment_new_name		(const char *		name,
+ViviCodeValue *		vivi_code_assignment_new_name		(const char *		name,
 								 ViviCodeValue *	value);
 
-void			vivi_code_assignment_set_local		(ViviCodeAssignment *	assign,
-								 gboolean		local);
-
 
 G_END_DECLS
 #endif
diff --git a/vivified/code/vivi_code_variable.c b/vivified/code/vivi_code_variable.c
new file mode 100644
index 0000000..7692aad
--- /dev/null
+++ b/vivified/code/vivi_code_variable.c
@@ -0,0 +1,152 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *               2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_code_variable.h"
+#include "vivi_code_get.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_string.h"
+#include "vivi_code_undefined.h"
+#include "vivi_code_compiler.h"
+#include "vivi_code_asm_code_default.h"
+
+G_DEFINE_TYPE (ViviCodeVariable, vivi_code_variable, VIVI_TYPE_CODE_STATEMENT)
+
+static void
+vivi_code_variable_dispose (GObject *object)
+{
+  ViviCodeVariable *variable = VIVI_CODE_VARIABLE (object);
+
+  g_object_unref (variable->name);
+  if (variable->value)
+    g_object_unref (variable->value);
+
+  G_OBJECT_CLASS (vivi_code_variable_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_variable_print (ViviCodeToken *token, ViviCodePrinter*printer)
+{
+  ViviCodeVariable *variable = VIVI_CODE_VARIABLE (token);
+  char *varname;
+
+  if (VIVI_IS_CODE_CONSTANT (variable->name)) {
+    varname = vivi_code_constant_get_variable_name (
+	VIVI_CODE_CONSTANT (variable->name));
+  } else {
+    varname = NULL;
+  }
+
+  vivi_code_printer_print (printer, "var ");
+
+  if (varname) {
+    vivi_code_printer_print (printer, varname);
+    g_free (varname);
+  } else {
+    // FIXME
+    vivi_code_printer_print (printer, "set (");
+    vivi_code_printer_print_value (printer, variable->name,
+	VIVI_PRECEDENCE_MIN);
+    vivi_code_printer_print (printer, ", ");
+    vivi_code_printer_print_value (printer, variable->value,
+	VIVI_PRECEDENCE_ASSIGNMENT);
+    vivi_code_printer_print (printer, ")");
+    goto finalize;
+  }
+
+  if (variable->value != NULL) {
+    vivi_code_printer_print (printer, " = ");
+    vivi_code_printer_print_value (printer, variable->value,
+	VIVI_PRECEDENCE_ASSIGNMENT);
+  }
+
+finalize:
+  vivi_code_printer_print (printer, ";");
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_code_variable_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+{
+  ViviCodeVariable *variable = VIVI_CODE_VARIABLE (token);
+  ViviCodeAsm *code;
+
+  vivi_code_compiler_compile_value (compiler, variable->name);
+
+  if (variable->value != NULL) {
+    vivi_code_compiler_compile_value (compiler, variable->value);
+    code = vivi_code_asm_define_local_new ();
+  } else {
+    code = vivi_code_asm_define_local2_new ();
+  }
+  vivi_code_compiler_take_code (compiler, code);
+}
+
+static void
+vivi_code_variable_class_init (ViviCodeVariableClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+
+  object_class->dispose = vivi_code_variable_dispose;
+
+  token_class->print = vivi_code_variable_print;
+  token_class->compile = vivi_code_variable_compile;
+}
+
+static void
+vivi_code_variable_init (ViviCodeVariable *variable)
+{
+}
+
+ViviCodeStatement *
+vivi_code_variable_new (ViviCodeValue *name, ViviCodeValue *value)
+{
+  ViviCodeVariable *variable;
+
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (name), NULL);
+  g_return_val_if_fail (value == NULL || VIVI_IS_CODE_VALUE (value), NULL);
+
+  variable = g_object_new (VIVI_TYPE_CODE_VARIABLE, NULL);
+  variable->name = g_object_ref (name);
+  if (value != NULL)
+    variable->value = g_object_ref (value);
+
+  return VIVI_CODE_STATEMENT (variable);
+}
+
+ViviCodeStatement *
+vivi_code_variable_new_name (const char *name, ViviCodeValue *value)
+{
+  ViviCodeValue *constant;
+  ViviCodeStatement *result;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (value == NULL || VIVI_IS_CODE_VALUE (value), NULL);
+
+  constant = vivi_code_string_new (name);
+  result = vivi_code_variable_new (constant, value);
+  g_object_unref (constant);
+
+  return result;
+}
diff --git a/vivified/code/vivi_code_variable.h b/vivified/code/vivi_code_variable.h
new file mode 100644
index 0000000..442df32
--- /dev/null
+++ b/vivified/code/vivi_code_variable.h
@@ -0,0 +1,62 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *               2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_CODE_VARIABLE_H_
+#define _VIVI_CODE_VARIABLE_H_
+
+#include <vivified/code/vivi_code_statement.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeVariable ViviCodeVariable;
+typedef struct _ViviCodeVariableClass ViviCodeVariableClass;
+
+#define VIVI_TYPE_CODE_VARIABLE                    (vivi_code_variable_get_type())
+#define VIVI_IS_CODE_VARIABLE(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_VARIABLE))
+#define VIVI_IS_CODE_VARIABLE_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_VARIABLE))
+#define VIVI_CODE_VARIABLE(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_VARIABLE, ViviCodeVariable))
+#define VIVI_CODE_VARIABLE_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_VARIABLE, ViviCodeVariableClass))
+#define VIVI_CODE_VARIABLE_VARIABLE_CLASS(obj)          (G_TYPE_INSTANCE_VARIABLE_CLASS ((obj), VIVI_TYPE_CODE_VARIABLE, ViviCodeVariableClass))
+
+struct _ViviCodeVariable
+{
+  ViviCodeStatement	statement;
+
+  ViviCodeValue *	name;
+  ViviCodeValue	*	value;
+};
+
+struct _ViviCodeVariableClass
+{
+  ViviCodeStatementClass	value_class;
+};
+
+GType			vivi_code_variable_get_type   	(void);
+
+ViviCodeStatement *	vivi_code_variable_new		(ViviCodeValue *	name,
+							 ViviCodeValue *	value);
+ViviCodeStatement *	vivi_code_variable_new_name	(const char *		name,
+							 ViviCodeValue *	value);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index eb51427..5c2a7b5 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -53,6 +53,7 @@
 #include "vivi_code_unary.h"
 #include "vivi_code_undefined.h"
 #include "vivi_code_value_statement.h"
+#include "vivi_code_variable.h"
 #include "vivi_decompiler_block.h"
 #include "vivi_decompiler_duplicate.h"
 #include "vivi_decompiler_state.h"
@@ -365,7 +366,7 @@ vivi_decompile_set_variable (ViviDecompilerBlock *block, ViviDecompilerState *st
 
   value = vivi_decompiler_state_pop (state);
   name = vivi_decompiler_state_pop (state);
-  assign = vivi_code_assignment_new (NULL, name, value);
+  assign = VIVI_CODE_STATEMENT (vivi_code_assignment_new (NULL, name, value));
   g_object_unref (name);
   g_object_unref (value);
   vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), assign);
@@ -382,7 +383,7 @@ vivi_decompile_set_member (ViviDecompilerBlock *block, ViviDecompilerState *stat
   value = vivi_decompiler_state_pop (state);
   name = vivi_decompiler_state_pop (state);
   from = vivi_decompiler_state_pop (state);
-  assign = vivi_code_assignment_new (from, name, value);
+  assign = VIVI_CODE_STATEMENT (vivi_code_assignment_new (from, name, value));
   g_object_unref (from);
   g_object_unref (name);
   g_object_unref (value);
@@ -395,7 +396,7 @@ vivi_decompile_define_local (ViviDecompilerBlock *block, ViviDecompilerState *st
     guint code, const guint8 *data, guint len)
 {
   ViviCodeValue *name, *value;
-  ViviCodeStatement *assign;
+  ViviCodeStatement *variable;
 
   if (code == SWFDEC_AS_ACTION_DEFINE_LOCAL)
     value = vivi_decompiler_state_pop (state);
@@ -403,11 +404,10 @@ vivi_decompile_define_local (ViviDecompilerBlock *block, ViviDecompilerState *st
     value = vivi_code_undefined_new ();
   name = vivi_decompiler_state_pop (state);
 
-  assign = vivi_code_assignment_new (NULL, name, value);
-  vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (assign), TRUE);
+  variable = vivi_code_variable_new (name, value);
   g_object_unref (name);
   g_object_unref (value);
-  vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), assign);
+  vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), variable);
   return TRUE;
 }
 
@@ -632,7 +632,7 @@ vivi_decompile_store_register (ViviDecompilerBlock *block, ViviDecompilerState *
     char *name;
 
     name = g_strdup_printf ("$reg%u", data[0]);
-    assign = vivi_code_assignment_new_name (name, value);
+    assign = VIVI_CODE_STATEMENT (vivi_code_assignment_new_name (name, value));
     vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), assign);
     g_object_unref (assign);
 
diff --git a/vivified/code/vivi_decompiler_block.c b/vivified/code/vivi_decompiler_block.c
index 895cf58..56cf886 100644
--- a/vivified/code/vivi_decompiler_block.c
+++ b/vivified/code/vivi_decompiler_block.c
@@ -331,8 +331,8 @@ vivi_decompiler_block_add_state_transition (ViviDecompilerBlock *from,
     }
     if (val_from != VIVI_CODE_VALUE (val_to)) {
       name = vivi_code_string_new (vivi_decompiler_unknown_get_name (val_to));
-      vivi_code_block_add_statement (block,
-	  vivi_code_assignment_new (NULL, name, val_from));
+      vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (
+	    vivi_code_assignment_new (NULL, name, val_from)));
     }
   }
 }
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 2011257..2c3d211 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -64,6 +64,7 @@
 #include "vivi_code_unary.h"
 #include "vivi_code_undefined.h"
 #include "vivi_code_value_statement.h"
+#include "vivi_code_variable.h"
 #include "vivi_compiler_empty_statement.h"
 #include "vivi_compiler_get_temporary.h"
 #include "vivi_compiler_goto_name.h"
@@ -358,7 +359,7 @@ vivi_parser_function_call_new (ViviCodeValue *name)
   return vivi_code_function_call_new (value, name);
 }
 
-static ViviCodeStatement *
+static ViviCodeValue *
 vivi_parser_assignment_new (ViviCodeValue *left, ViviCodeValue *right)
 {
   ViviCodeValue *from;
@@ -1003,12 +1004,13 @@ peek_variable_declaration (ParseData *data)
 static ViviCodeStatement *
 parse_variable_declaration (ParseData *data)
 {
-  ViviCodeValue *identifier, *value;
-  ViviCodeStatement *assignment, *statement_right;
+  ViviCodeValue *value;
+  ViviCodeStatement *variable, *statement_right;
+  char *identifier;
 
   vivi_parser_start_code_token (data);
 
-  identifier = parse_identifier (data);
+  identifier = g_strdup (parse_identifier_value (data));
 
   if (try_parse_token (data, TOKEN_ASSIGN)) {
     value = parse_assignment_expression (data, &statement_right);
@@ -1021,14 +1023,13 @@ parse_variable_declaration (ParseData *data)
     vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
   }
 
-  assignment = vivi_parser_assignment_new (identifier, value);
-  vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (assignment), TRUE);
-  g_object_unref (identifier);
+  variable = vivi_code_variable_new_name (identifier, value);
+  g_free (identifier);
   g_object_unref (value);
 
-  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (assignment));
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (variable));
 
-  return vivi_parser_join_statements (statement_right, assignment);
+  return vivi_parser_join_statements (statement_right, variable);
 }
 
 // asm functions
@@ -1872,8 +1873,7 @@ peek_postfix_expression (ParseData *data)
 static ViviCodeValue *
 parse_postfix_expression (ParseData *data, ViviCodeStatement **statement)
 {
-  ViviCodeStatement *assignment;
-  ViviCodeValue *value, *operation, *one, *temporary;
+  ViviCodeValue *assignment, *value, *operation, *one;
   gboolean add;
 
   vivi_parser_start_code_token (data);
@@ -1909,18 +1909,11 @@ parse_postfix_expression (ParseData *data, ViviCodeStatement **statement)
 
   assignment = vivi_parser_assignment_new (value, operation);
   g_object_unref (operation);
+  g_object_unref (value);
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (assignment));
 
-  temporary = vivi_compiler_get_temporary_new ();
-  *statement = vivi_parser_join_statements (*statement,
-     vivi_parser_join_statements (
-       vivi_parser_assignment_new (temporary, value), assignment));
-
-  g_object_unref (value);
-  value = temporary;
-
-  return value;
+  return assignment;
 }
 
 static gboolean
@@ -1976,9 +1969,10 @@ parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
 
       vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (tmp));
 
-      *statement = vivi_parser_join_statements (*statement,
-	  vivi_parser_assignment_new (value, tmp));
+      one = vivi_parser_assignment_new (value, tmp);
       g_object_unref (tmp);
+      g_object_unref (value);
+      value = one;
       break;
     case TOKEN_PLUS:
       vivi_parser_scanner_get_next_token (data->scanner);
@@ -2378,8 +2372,8 @@ peek_assignment_expression (ParseData *data)
 static ViviCodeValue *
 parse_assignment_expression (ParseData *data, ViviCodeStatement **statement)
 {
-  ViviCodeValue *value, *right;
-  ViviCodeStatement *assignment, *statement_right;
+  ViviCodeValue *value, *assignment, *right;
+  ViviCodeStatement *statement_right;
   ViviCodeValue * (* func) (ViviCodeValue *, ViviCodeValue *);
 
   vivi_parser_start_code_token (data);
@@ -2443,13 +2437,13 @@ parse_assignment_expression (ParseData *data, ViviCodeStatement **statement)
     assignment = vivi_parser_assignment_new (value, right);
   }
   g_object_unref (right);
+  g_object_unref (value);
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (assignment));
 
-  *statement = vivi_parser_join_statements (*statement,
-      vivi_parser_join_statements (statement_right, assignment));
+  *statement = vivi_parser_join_statements (*statement, statement_right);
 
-  return value;
+  return assignment;
 }
 
 static gboolean
commit b72f722ab040592f7c93a8e8f42e692b63cfcb5a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 16:02:38 2008 +0300

    Make ViviCodeValue be a subclass of ViviCodeStatement
    
    Add print_value and compile_value vfuncs for printing and compiling the value
    instead of the statement

diff --git a/vivified/code/vivi_code_and.c b/vivified/code/vivi_code_and.c
index 4ac5154..9bc00df 100644
--- a/vivified/code/vivi_code_and.c
+++ b/vivified/code/vivi_code_and.c
@@ -29,21 +29,19 @@
 G_DEFINE_TYPE (ViviCodeAnd, vivi_code_and, VIVI_TYPE_CODE_BINARY)
 
 static void
-vivi_code_and_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_and_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
 {
-  ViviCodeBinary *binary = VIVI_CODE_BINARY (token);
+  ViviCodeBinary *binary = VIVI_CODE_BINARY (value);
   ViviCodeLabel *label_end;
 
   vivi_code_compiler_compile_value (compiler, binary->left);
-
   vivi_code_compiler_take_code (compiler, vivi_code_asm_push_duplicate_new ());
-  vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
 
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
   label_end = vivi_code_compiler_create_label (compiler, "and_end");
   vivi_code_compiler_take_code (compiler, vivi_code_asm_if_new (label_end));
 
   vivi_code_compiler_take_code (compiler, vivi_code_asm_pop_new ());
-
   vivi_code_compiler_compile_value (compiler, binary->right);
 
   vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
@@ -52,10 +50,10 @@ vivi_code_and_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 static void
 vivi_code_and_class_init (ViviCodeAndClass *klass)
 {
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
   ViviCodeBinaryClass *binary_class = VIVI_CODE_BINARY_CLASS (klass);
 
-  token_class->compile = vivi_code_and_compile;
+  value_class->compile_value = vivi_code_and_compile_value;
 
   binary_class->operator_name = "&&";
 }
diff --git a/vivified/code/vivi_code_binary.c b/vivified/code/vivi_code_binary.c
index 26188f9..035f254 100644
--- a/vivified/code/vivi_code_binary.c
+++ b/vivified/code/vivi_code_binary.c
@@ -41,10 +41,9 @@ vivi_code_binary_dispose (GObject *object)
 }
 
 static void
-vivi_code_binary_print (ViviCodeToken *token, ViviCodePrinter*printer)
+vivi_code_binary_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
-  ViviCodeBinary *binary = VIVI_CODE_BINARY (token);
-  ViviCodeValue *value = VIVI_CODE_VALUE (token);
+  ViviCodeBinary *binary = VIVI_CODE_BINARY (value);
   ViviCodeBinaryClass *klass = VIVI_CODE_BINARY_GET_CLASS (binary);
 
   vivi_code_printer_print_value (printer, binary->left, 
@@ -57,9 +56,10 @@ vivi_code_binary_print (ViviCodeToken *token, ViviCodePrinter*printer)
 }
 
 static void
-vivi_code_binary_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_binary_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
-  ViviCodeBinary *binary = VIVI_CODE_BINARY (token);
+  ViviCodeBinary *binary = VIVI_CODE_BINARY (value);
   ViviCodeBinaryClass *klass = VIVI_CODE_BINARY_GET_CLASS (binary);
 
   vivi_code_compiler_compile_value (compiler, binary->left);
@@ -82,14 +82,12 @@ static void
 vivi_code_binary_class_init (ViviCodeBinaryClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
   ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_binary_dispose;
 
-  token_class->print = vivi_code_binary_print;
-  token_class->compile = vivi_code_binary_compile;
-
+  value_class->print_value = vivi_code_binary_print_value;
+  value_class->compile_value = vivi_code_binary_compile_value;
   value_class->is_constant = vivi_code_binary_is_constant;
 }
 
diff --git a/vivified/code/vivi_code_boolean.c b/vivified/code/vivi_code_boolean.c
index b97f8a7..8060ff9 100644
--- a/vivified/code/vivi_code_boolean.c
+++ b/vivified/code/vivi_code_boolean.c
@@ -29,17 +29,18 @@
 G_DEFINE_TYPE (ViviCodeBoolean, vivi_code_boolean, VIVI_TYPE_CODE_CONSTANT)
 
 static void
-vivi_code_boolean_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_boolean_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
-  ViviCodeBoolean *b = VIVI_CODE_BOOLEAN (token);
+  ViviCodeBoolean *b = VIVI_CODE_BOOLEAN (value);
 
   vivi_code_printer_print (printer, b->value ? "true" : "false");
 }
 
 static void
-vivi_code_boolean_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_boolean_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
-  ViviCodeBoolean *b = VIVI_CODE_BOOLEAN (token);
+  ViviCodeBoolean *b = VIVI_CODE_BOOLEAN (value);
   ViviCodeAsm *code;
 
   code = vivi_code_asm_push_new ();
@@ -58,11 +59,11 @@ vivi_code_boolean_get_variable_name (ViviCodeConstant *constant)
 static void
 vivi_code_boolean_class_init (ViviCodeBooleanClass *klass)
 {
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
   ViviCodeConstantClass *constant_class = VIVI_CODE_CONSTANT_CLASS (klass);
 
-  token_class->print = vivi_code_boolean_print;
-  token_class->compile = vivi_code_boolean_compile;
+  value_class->print_value = vivi_code_boolean_print_value;
+  value_class->compile_value = vivi_code_boolean_compile_value;
 
   constant_class->get_variable_name = vivi_code_boolean_get_variable_name;
 }
diff --git a/vivified/code/vivi_code_builtin_call.c b/vivified/code/vivi_code_builtin_call.c
index a43dd7d..4206371 100644
--- a/vivified/code/vivi_code_builtin_call.c
+++ b/vivified/code/vivi_code_builtin_call.c
@@ -28,21 +28,21 @@
 G_DEFINE_ABSTRACT_TYPE (ViviCodeBuiltinCall, vivi_code_builtin_call, VIVI_TYPE_CODE_VALUE)
 
 static void
-vivi_code_builtin_call_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_builtin_call_print_value (ViviCodeValue *value,
+    ViviCodePrinter *printer)
 {
-  ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (token);
+  ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (value);
 
   g_assert (klass->function_name != NULL);
   vivi_code_printer_print (printer, klass->function_name);
-  vivi_code_printer_print (printer, " ();");
-  vivi_code_printer_new_line (printer, FALSE);
+  vivi_code_printer_print (printer, " ()");
 }
 
 static void
-vivi_code_builtin_call_compile (ViviCodeToken *token,
+vivi_code_builtin_call_compile_value (ViviCodeValue *value,
     ViviCodeCompiler *compiler)
 {
-  ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (token);
+  ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (value);
 
   g_assert (klass->asm_constructor != NULL);
   vivi_code_compiler_take_code (compiler, klass->asm_constructor ());
@@ -51,10 +51,10 @@ vivi_code_builtin_call_compile (ViviCodeToken *token,
 static void
 vivi_code_builtin_call_class_init (ViviCodeBuiltinCallClass *klass)
 {
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
-  token_class->print = vivi_code_builtin_call_print;
-  token_class->compile = vivi_code_builtin_call_compile;
+  value_class->print_value = vivi_code_builtin_call_print_value;
+  value_class->compile_value = vivi_code_builtin_call_compile_value;
 }
 
 static void
diff --git a/vivified/code/vivi_code_builtin_value_call.c b/vivified/code/vivi_code_builtin_value_call.c
index fa17b0d..368bb64 100644
--- a/vivified/code/vivi_code_builtin_value_call.c
+++ b/vivified/code/vivi_code_builtin_value_call.c
@@ -39,11 +39,11 @@ vivi_code_builtin_value_call_dispose (GObject *object)
 }
 
 static void
-vivi_code_builtin_value_call_print (ViviCodeToken *token,
+vivi_code_builtin_value_call_print_value (ViviCodeValue *value,
     ViviCodePrinter *printer)
 {
-  ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (token);
-  ViviCodeBuiltinValueCall *call = VIVI_CODE_BUILTIN_VALUE_CALL (token);
+  ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (value);
+  ViviCodeBuiltinValueCall *call = VIVI_CODE_BUILTIN_VALUE_CALL (value);
 
   g_assert (klass->function_name != NULL);
   vivi_code_printer_print (printer, klass->function_name);
@@ -52,16 +52,15 @@ vivi_code_builtin_value_call_print (ViviCodeToken *token,
   g_assert (call->value != NULL);
   vivi_code_printer_print_value (printer, call->value, VIVI_PRECEDENCE_COMMA);
 
-  vivi_code_printer_print (printer, ");");
-  vivi_code_printer_new_line (printer, FALSE);
+  vivi_code_printer_print (printer, ")");
 }
 
 static void
-vivi_code_builtin_value_call_compile (ViviCodeToken *token,
+vivi_code_builtin_value_call_compile_value (ViviCodeValue *value,
     ViviCodeCompiler *compiler)
 {
-  ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (token);
-  ViviCodeBuiltinValueCall *call = VIVI_CODE_BUILTIN_VALUE_CALL (token);
+  ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (value);
+  ViviCodeBuiltinValueCall *call = VIVI_CODE_BUILTIN_VALUE_CALL (value);
 
   g_assert (call->value != NULL);
   vivi_code_compiler_compile_value (compiler, call->value);
@@ -71,16 +70,15 @@ vivi_code_builtin_value_call_compile (ViviCodeToken *token,
 }
 
 static void
-vivi_code_builtin_value_call_class_init (
-    ViviCodeBuiltinValueCallClass *klass)
+vivi_code_builtin_value_call_class_init (ViviCodeBuiltinValueCallClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_builtin_value_call_dispose;
 
-  token_class->print = vivi_code_builtin_value_call_print;
-  token_class->compile = vivi_code_builtin_value_call_compile;
+  value_class->print_value = vivi_code_builtin_value_call_print_value;
+  value_class->compile_value = vivi_code_builtin_value_call_compile_value;
 }
 
 static void
diff --git a/vivified/code/vivi_code_compiler.c b/vivified/code/vivi_code_compiler.c
index e7cdc45..6a54419 100644
--- a/vivified/code/vivi_code_compiler.c
+++ b/vivified/code/vivi_code_compiler.c
@@ -51,6 +51,20 @@ vivi_code_compiler_init (ViviCodeCompiler *compiler)
 }
 
 void
+vivi_code_compiler_compile_value (ViviCodeCompiler *compiler,
+    ViviCodeValue *value)
+{
+  ViviCodeValueClass *klass;
+
+  g_return_if_fail (VIVI_IS_CODE_COMPILER (compiler));
+  g_return_if_fail (VIVI_IS_CODE_VALUE (value));
+
+  klass = VIVI_CODE_VALUE_GET_CLASS (value);
+  g_return_if_fail (klass->compile_value);
+  klass->compile_value (value, compiler);
+}
+
+void
 vivi_code_compiler_compile_token (ViviCodeCompiler *compiler,
     ViviCodeToken *token)
 {
diff --git a/vivified/code/vivi_code_compiler.h b/vivified/code/vivi_code_compiler.h
index ad18dab..5215425 100644
--- a/vivified/code/vivi_code_compiler.h
+++ b/vivified/code/vivi_code_compiler.h
@@ -25,6 +25,7 @@
 #include <vivified/code/vivi_code_assembler.h>
 #include <vivified/code/vivi_code_asm.h>
 #include <vivified/code/vivi_code_label.h>
+#include <vivified/code/vivi_code_value.h>
 
 G_BEGIN_DECLS
 
@@ -56,10 +57,11 @@ GType			vivi_code_compiler_get_type   		(void);
 
 ViviCodeCompiler *	vivi_code_compiler_new			(guint			version);
 
-#define vivi_code_compiler_compile_value(c,v) vivi_code_compiler_compile_token((c), VIVI_CODE_TOKEN((v)))
 #define vivi_code_compiler_compile_statement(c,s) vivi_code_compiler_compile_token((c), VIVI_CODE_TOKEN((s)))
 void			vivi_code_compiler_compile_token	(ViviCodeCompiler *	compiler,
 								 ViviCodeToken *	token);
+void			vivi_code_compiler_compile_value	(ViviCodeCompiler *	compiler,
+								 ViviCodeValue *	value);
 void			vivi_code_compiler_compile_script	(ViviCodeCompiler *	compiler,
 								 ViviCodeStatement *	statement);
 
diff --git a/vivified/code/vivi_code_concat.c b/vivified/code/vivi_code_concat.c
index ff6668f..130c761 100644
--- a/vivified/code/vivi_code_concat.c
+++ b/vivified/code/vivi_code_concat.c
@@ -40,9 +40,9 @@ vivi_code_concat_dispose (GObject *object)
 }
 
 static void
-vivi_code_concat_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_concat_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
-  ViviCodeConcat *concat = VIVI_CODE_CONCAT (token);
+  ViviCodeConcat *concat = VIVI_CODE_CONCAT (value);
 
   vivi_code_printer_print (printer, "concat (");
   vivi_code_printer_print_value (printer, concat->first,
@@ -50,14 +50,14 @@ vivi_code_concat_print (ViviCodeToken *token, ViviCodePrinter *printer)
   vivi_code_printer_print (printer, ", ");
   vivi_code_printer_print_value (printer, concat->second,
       VIVI_PRECEDENCE_COMMA);
-  vivi_code_printer_print (printer, ");");
-  vivi_code_printer_new_line (printer, FALSE);
+  vivi_code_printer_print (printer, ")");
 }
 
 static void
-vivi_code_concat_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_concat_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
-  ViviCodeConcat *concat = VIVI_CODE_CONCAT (token);
+  ViviCodeConcat *concat = VIVI_CODE_CONCAT (value);
 
   vivi_code_compiler_compile_value (compiler, concat->first);
   vivi_code_compiler_compile_value (compiler, concat->second);
@@ -69,12 +69,12 @@ static void
 vivi_code_concat_class_init (ViviCodeConcatClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_concat_dispose;
 
-  token_class->print = vivi_code_concat_print;
-  token_class->compile = vivi_code_concat_compile;
+  value_class->print_value = vivi_code_concat_print_value;
+  value_class->compile_value = vivi_code_concat_compile_value;
 }
 
 static void
diff --git a/vivified/code/vivi_code_function.c b/vivified/code/vivi_code_function.c
index 5652022..33d6105 100644
--- a/vivified/code/vivi_code_function.c
+++ b/vivified/code/vivi_code_function.c
@@ -52,9 +52,9 @@ vivi_code_function_dispose (GObject *object)
 }
 
 static void
-vivi_code_function_print (ViviCodeToken *token, ViviCodePrinter*printer)
+vivi_code_function_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
-  ViviCodeFunction *function = VIVI_CODE_FUNCTION (token);
+  ViviCodeFunction *function = VIVI_CODE_FUNCTION (value);
   guint i;
 
   vivi_code_printer_print (printer, "function (");
@@ -75,9 +75,10 @@ vivi_code_function_print (ViviCodeToken *token, ViviCodePrinter*printer)
 }
 
 static void
-vivi_code_function_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_function_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
-  ViviCodeFunction *function = VIVI_CODE_FUNCTION (token);
+  ViviCodeFunction *function = VIVI_CODE_FUNCTION (value);
   ViviCodeLabel *label_end;
   ViviCodeAsm *code;
   guint i;
@@ -108,14 +109,12 @@ static void
 vivi_code_function_class_init (ViviCodeFunctionClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
   ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_function_dispose;
 
-  token_class->print = vivi_code_function_print;
-  token_class->compile = vivi_code_function_compile;
-
+  value_class->print_value = vivi_code_function_print_value;
+  value_class->compile_value = vivi_code_function_compile_value;
   value_class->is_constant = vivi_code_function_is_constant;
 }
 
diff --git a/vivified/code/vivi_code_function_call.c b/vivified/code/vivi_code_function_call.c
index 20377df..5f93d29 100644
--- a/vivified/code/vivi_code_function_call.c
+++ b/vivified/code/vivi_code_function_call.c
@@ -75,9 +75,10 @@ vivi_code_function_call_optimize (ViviCodeValue *value, SwfdecAsValueType hint)
 }
 
 static void
-vivi_code_function_call_print (ViviCodeToken *token, ViviCodePrinter*printer)
+vivi_code_function_call_print_value (ViviCodeValue *value,
+    ViviCodePrinter *printer)
 {
-  ViviCodeFunctionCall *call = VIVI_CODE_FUNCTION_CALL (token);
+  ViviCodeFunctionCall *call = VIVI_CODE_FUNCTION_CALL (value);
   char *varname;
   guint i;
 
@@ -122,10 +123,10 @@ vivi_code_function_call_print (ViviCodeToken *token, ViviCodePrinter*printer)
 }
 
 static void
-vivi_code_function_call_compile (ViviCodeToken *token,
+vivi_code_function_call_compile_value (ViviCodeValue *value,
     ViviCodeCompiler *compiler)
 {
-  ViviCodeFunctionCall *call = VIVI_CODE_FUNCTION_CALL (token);
+  ViviCodeFunctionCall *call = VIVI_CODE_FUNCTION_CALL (value);
   ViviCodeValue *count;
   ViviCodeAsm *code;
   guint i;
@@ -170,14 +171,12 @@ static void
 vivi_code_function_call_class_init (ViviCodeFunctionCallClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
   ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_function_call_dispose;
 
-  token_class->print = vivi_code_function_call_print;
-  token_class->compile = vivi_code_function_call_compile;
-
+  value_class->print_value = vivi_code_function_call_print_value;
+  value_class->compile_value = vivi_code_function_call_compile_value;
   value_class->is_constant = vivi_code_function_call_is_constant;
   value_class->optimize = vivi_code_function_call_optimize;
 }
diff --git a/vivified/code/vivi_code_get.c b/vivified/code/vivi_code_get.c
index 5a8654f..dc9bb40 100644
--- a/vivified/code/vivi_code_get.c
+++ b/vivified/code/vivi_code_get.c
@@ -42,9 +42,9 @@ vivi_code_get_dispose (GObject *object)
 }
 
 static void
-vivi_code_get_print (ViviCodeToken *token, ViviCodePrinter*printer)
+vivi_code_get_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
-  ViviCodeGet *get = VIVI_CODE_GET (token);
+  ViviCodeGet *get = VIVI_CODE_GET (value);
   char *varname;
 
   if (VIVI_IS_CODE_CONSTANT (get->name))
@@ -75,9 +75,9 @@ vivi_code_get_print (ViviCodeToken *token, ViviCodePrinter*printer)
 }
 
 static void
-vivi_code_get_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_get_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
 {
-  ViviCodeGet *get = VIVI_CODE_GET (token);
+  ViviCodeGet *get = VIVI_CODE_GET (value);
   ViviCodeAsm *code;
 
   if (get->from)
@@ -103,14 +103,12 @@ static void
 vivi_code_get_class_init (ViviCodeGetClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
   ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_get_dispose;
 
-  token_class->print = vivi_code_get_print;
-  token_class->compile = vivi_code_get_compile;
-
+  value_class->print_value = vivi_code_get_print_value;
+  value_class->compile_value = vivi_code_get_compile_value;
   value_class->is_constant = vivi_code_get_is_constant;
 }
 
diff --git a/vivified/code/vivi_code_increment.c b/vivified/code/vivi_code_increment.c
index be2c2e6..c8d9b83 100644
--- a/vivified/code/vivi_code_increment.c
+++ b/vivified/code/vivi_code_increment.c
@@ -39,9 +39,10 @@ vivi_code_increment_dispose (GObject *object)
 }
 
 static void
-vivi_code_increment_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_increment_print_value (ViviCodeValue *value,
+    ViviCodePrinter *printer)
 {
-  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (token);
+  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (value);
 
   vivi_code_printer_print_value (printer, increment->value,
       VIVI_PRECEDENCE_INCREMENT);
@@ -50,9 +51,10 @@ vivi_code_increment_print (ViviCodeToken *token, ViviCodePrinter *printer)
 }
 
 static void
-vivi_code_increment_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_increment_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
-  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (token);
+  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (value);
 
   vivi_code_compiler_compile_value (compiler, increment->value);
   vivi_code_compiler_take_code (compiler, vivi_code_asm_increment_new ());
@@ -62,12 +64,12 @@ static void
 vivi_code_increment_class_init (ViviCodeIncrementClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_increment_dispose;
 
-  token_class->print = vivi_code_increment_print;
-  token_class->compile = vivi_code_increment_compile;
+  value_class->print_value = vivi_code_increment_print_value;
+  value_class->compile_value = vivi_code_increment_compile_value;
 }
 
 static void
diff --git a/vivified/code/vivi_code_init_array.c b/vivified/code/vivi_code_init_array.c
index ecb7b7c..8bf633e 100644
--- a/vivified/code/vivi_code_init_array.c
+++ b/vivified/code/vivi_code_init_array.c
@@ -60,30 +60,31 @@ vivi_code_init_array_optimize (ViviCodeValue *value, SwfdecAsValueType hint)
 }
 
 static void
-vivi_code_init_array_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_init_array_print_value (ViviCodeValue *value,
+    ViviCodePrinter *printer)
 {
-  ViviCodeInitArray *array = VIVI_CODE_INIT_ARRAY (token);
+  ViviCodeInitArray *array = VIVI_CODE_INIT_ARRAY (value);
   guint i;
 
   vivi_code_printer_print (printer, "[");
   for (i = 0; i < array->variables->len; i++) {
-    ViviCodeValue *value =
+    ViviCodeValue *member =
       VIVI_CODE_VALUE (g_ptr_array_index (array->variables, i));
     if (i > 0)
       vivi_code_printer_print (printer, ", ");
     /* FIXME: precedences? */
     // don't write undefined values
-    if (!VIVI_IS_CODE_UNDEFINED (value))
-      vivi_code_printer_print_value (printer, value, VIVI_PRECEDENCE_COMMA);
+    if (!VIVI_IS_CODE_UNDEFINED (member))
+      vivi_code_printer_print_value (printer, member, VIVI_PRECEDENCE_COMMA);
   }
   vivi_code_printer_print (printer, "]");
 }
 
 static void
-vivi_code_init_array_compile (ViviCodeToken *token,
+vivi_code_init_array_compile_value (ViviCodeValue *value,
     ViviCodeCompiler *compiler)
 {
-  ViviCodeInitArray *array = VIVI_CODE_INIT_ARRAY (token);
+  ViviCodeInitArray *array = VIVI_CODE_INIT_ARRAY (value);
   ViviCodeValue *count;
   guint i;
 
@@ -109,14 +110,12 @@ static void
 vivi_code_init_array_class_init (ViviCodeInitArrayClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
   ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_init_array_dispose;
 
-  token_class->print = vivi_code_init_array_print;
-  token_class->compile = vivi_code_init_array_compile;
-
+  value_class->print_value = vivi_code_init_array_print_value;
+  value_class->compile_value = vivi_code_init_array_compile_value;
   value_class->is_constant = vivi_code_init_array_is_constant;
   value_class->optimize = vivi_code_init_array_optimize;
 }
diff --git a/vivified/code/vivi_code_init_object.c b/vivified/code/vivi_code_init_object.c
index 09c02bd..afd1358 100644
--- a/vivified/code/vivi_code_init_object.c
+++ b/vivified/code/vivi_code_init_object.c
@@ -60,9 +60,10 @@ vivi_code_init_object_optimize (ViviCodeValue *value, SwfdecAsValueType hint)
 }
 
 static void
-vivi_code_init_object_print (ViviCodeToken *token, ViviCodePrinter*printer)
+vivi_code_init_object_print_value (ViviCodeValue *value,
+    ViviCodePrinter *printer)
 {
-  ViviCodeInitObject *object = VIVI_CODE_INIT_OBJECT (token);
+  ViviCodeInitObject *object = VIVI_CODE_INIT_OBJECT (value);
   guint i;
 
   vivi_code_printer_print (printer, "{");
@@ -79,10 +80,10 @@ vivi_code_init_object_print (ViviCodeToken *token, ViviCodePrinter*printer)
 }
 
 static void
-vivi_code_init_object_compile (ViviCodeToken *token,
+vivi_code_init_object_compile_value (ViviCodeValue *value,
     ViviCodeCompiler *compiler)
 {
-  ViviCodeInitObject *object = VIVI_CODE_INIT_OBJECT (token);
+  ViviCodeInitObject *object = VIVI_CODE_INIT_OBJECT (value);
   ViviCodeValue *count;
   guint i;
 
@@ -110,14 +111,12 @@ static void
 vivi_code_init_object_class_init (ViviCodeInitObjectClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
   ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_init_object_dispose;
 
-  token_class->print = vivi_code_init_object_print;
-  token_class->compile = vivi_code_init_object_compile;
-
+  value_class->print_value = vivi_code_init_object_print_value;
+  value_class->compile_value = vivi_code_init_object_compile_value;
   value_class->is_constant = vivi_code_init_object_is_constant;
   value_class->optimize = vivi_code_init_object_optimize;
 }
diff --git a/vivified/code/vivi_code_null.c b/vivified/code/vivi_code_null.c
index 2f49c84..77bf62a 100644
--- a/vivified/code/vivi_code_null.c
+++ b/vivified/code/vivi_code_null.c
@@ -33,13 +33,13 @@
 G_DEFINE_TYPE (ViviCodeNull, vivi_code_null, VIVI_TYPE_CODE_CONSTANT)
 
 static void
-vivi_code_null_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_null_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
   vivi_code_printer_print (printer, "null");
 }
 
 static void
-vivi_code_null_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_null_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
 {
   ViviCodeAsm *code;
 
@@ -57,11 +57,11 @@ vivi_code_null_get_variable_name (ViviCodeConstant *constant)
 static void
 vivi_code_null_class_init (ViviCodeNullClass *klass)
 {
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
   ViviCodeConstantClass *constant_class = VIVI_CODE_CONSTANT_CLASS (klass);
 
-  token_class->print = vivi_code_null_print;
-  token_class->compile = vivi_code_null_compile;
+  value_class->print_value = vivi_code_null_print_value;
+  value_class->compile_value = vivi_code_null_compile_value;
 
   constant_class->get_variable_name = vivi_code_null_get_variable_name;
 }
diff --git a/vivified/code/vivi_code_number.c b/vivified/code/vivi_code_number.c
index 70a990b..d188784 100644
--- a/vivified/code/vivi_code_number.c
+++ b/vivified/code/vivi_code_number.c
@@ -29,9 +29,9 @@
 G_DEFINE_TYPE (ViviCodeNumber, vivi_code_number, VIVI_TYPE_CODE_CONSTANT)
 
 static void
-vivi_code_number_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_number_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
-  ViviCodeNumber *number = VIVI_CODE_NUMBER (token);
+  ViviCodeNumber *number = VIVI_CODE_NUMBER (value);
   char s[G_ASCII_DTOSTR_BUF_SIZE];
 
   g_ascii_dtostr (s, G_ASCII_DTOSTR_BUF_SIZE, number->value);
@@ -39,9 +39,10 @@ vivi_code_number_print (ViviCodeToken *token, ViviCodePrinter *printer)
 }
 
 static void
-vivi_code_number_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_number_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
-  ViviCodeNumber *number = VIVI_CODE_NUMBER (token);
+  ViviCodeNumber *number = VIVI_CODE_NUMBER (value);
   ViviCodeAsm *code;
   ViviCodeNumberHint hint;
 
@@ -81,10 +82,10 @@ vivi_code_number_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 static void
 vivi_code_number_class_init (ViviCodeNumberClass *klass)
 {
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
-  token_class->print = vivi_code_number_print;
-  token_class->compile = vivi_code_number_compile;
+  value_class->print_value = vivi_code_number_print_value;
+  value_class->compile_value = vivi_code_number_compile_value;
 }
 
 static void
diff --git a/vivified/code/vivi_code_or.c b/vivified/code/vivi_code_or.c
index 5a6f212..b231f00 100644
--- a/vivified/code/vivi_code_or.c
+++ b/vivified/code/vivi_code_or.c
@@ -29,9 +29,9 @@
 G_DEFINE_TYPE (ViviCodeOr, vivi_code_or, VIVI_TYPE_CODE_BINARY)
 
 static void
-vivi_code_or_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_or_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
 {
-  ViviCodeBinary *binary = VIVI_CODE_BINARY (token);
+  ViviCodeBinary *binary = VIVI_CODE_BINARY (value);
   ViviCodeLabel *label_end;
 
   vivi_code_compiler_compile_value (compiler, binary->left);
@@ -48,10 +48,10 @@ vivi_code_or_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 static void
 vivi_code_or_class_init (ViviCodeOrClass *klass)
 {
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
   ViviCodeBinaryClass *binary_class = VIVI_CODE_BINARY_CLASS (klass);
 
-  token_class->compile = vivi_code_or_compile;
+  value_class->compile_value = vivi_code_or_compile_value;
 
   binary_class->operator_name = "||";
 }
diff --git a/vivified/code/vivi_code_printer.c b/vivified/code/vivi_code_printer.c
index 738069f..48cbbc3 100644
--- a/vivified/code/vivi_code_printer.c
+++ b/vivified/code/vivi_code_printer.c
@@ -84,6 +84,8 @@ void
 vivi_code_printer_print_value (ViviCodePrinter *printer, ViviCodeValue *value,
     ViviPrecedence precedence)
 {
+  ViviCodePrinterClass *klass;
+  ViviCodeValueClass *value_class;
   gboolean needs_parens;
 
   g_return_if_fail (VIVI_IS_CODE_PRINTER (printer));
@@ -92,7 +94,16 @@ vivi_code_printer_print_value (ViviCodePrinter *printer, ViviCodeValue *value,
   needs_parens = vivi_code_value_get_precedence (value) < precedence;
   if (needs_parens)
     vivi_code_printer_print (printer, "(");
-  vivi_code_printer_print_token (printer, VIVI_CODE_TOKEN (value));
+
+  klass = VIVI_CODE_PRINTER_GET_CLASS (printer);
+  if (klass->push_token)
+    klass->push_token (printer, VIVI_CODE_TOKEN (value));
+  value_class = VIVI_CODE_VALUE_GET_CLASS (value);
+  g_return_if_fail (value_class->print_value);
+  value_class->print_value (value, printer);
+  if (klass->pop_token)
+    klass->pop_token (printer, VIVI_CODE_TOKEN (value));
+
   if (needs_parens)
     vivi_code_printer_print (printer, ")");
 }
diff --git a/vivified/code/vivi_code_string.c b/vivified/code/vivi_code_string.c
index 807442f..f8c2d1c 100644
--- a/vivified/code/vivi_code_string.c
+++ b/vivified/code/vivi_code_string.c
@@ -42,9 +42,9 @@ vivi_code_string_dispose (GObject *object)
 }
 
 static void
-vivi_code_string_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_string_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
-  ViviCodeString *string = VIVI_CODE_STRING (token);
+  ViviCodeString *string = VIVI_CODE_STRING (value);
   char *s;
 
   s = vivi_code_escape_string (string->value);
@@ -53,9 +53,10 @@ vivi_code_string_print (ViviCodeToken *token, ViviCodePrinter *printer)
 }
 
 static void
-vivi_code_string_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_string_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
-  ViviCodeString *string = VIVI_CODE_STRING (token);
+  ViviCodeString *string = VIVI_CODE_STRING (value);
   ViviCodeAsm *code;
 
   code = vivi_code_asm_push_new ();
@@ -81,13 +82,13 @@ static void
 vivi_code_string_class_init (ViviCodeStringClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
   ViviCodeConstantClass *constant_class = VIVI_CODE_CONSTANT_CLASS (klass);
 
   object_class->dispose = vivi_code_string_dispose;
 
-  token_class->print = vivi_code_string_print;
-  token_class->compile = vivi_code_string_compile;
+  value_class->print_value = vivi_code_string_print_value;
+  value_class->compile_value = vivi_code_string_compile_value;
 
   constant_class->get_variable_name = vivi_code_string_get_variable_name;
 }
diff --git a/vivified/code/vivi_code_substring.c b/vivified/code/vivi_code_substring.c
index fe1ab0a..93a84f6 100644
--- a/vivified/code/vivi_code_substring.c
+++ b/vivified/code/vivi_code_substring.c
@@ -40,9 +40,10 @@ vivi_code_substring_dispose (GObject *object)
 }
 
 static void
-vivi_code_substring_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_substring_print_value (ViviCodeValue *value,
+    ViviCodePrinter *printer)
 {
-  ViviCodeSubstring *substring = VIVI_CODE_SUBSTRING (token);
+  ViviCodeSubstring *substring = VIVI_CODE_SUBSTRING (value);
 
   vivi_code_printer_print (printer, "substring (");
   vivi_code_printer_print_value (printer, substring->string,
@@ -53,16 +54,16 @@ vivi_code_substring_print (ViviCodeToken *token, ViviCodePrinter *printer)
   vivi_code_printer_print (printer, ", ");
   vivi_code_printer_print_value (printer, substring->count,
       VIVI_PRECEDENCE_COMMA);
-  vivi_code_printer_print (printer, ");");
-  vivi_code_printer_new_line (printer, FALSE);
+  vivi_code_printer_print (printer, ")");
 }
 
 static void
-vivi_code_substring_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_substring_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
   g_printerr ("Implement substring\n");
 #if 0
-  ViviCodeSubstring *substring = VIVI_CODE_SUBSTRING (token);
+  ViviCodeSubstring *substring = VIVI_CODE_SUBSTRING (value);
 
   vivi_code_value_compile (substring->string, compiler);
   vivi_code_value_compile (substring->index_, compiler);
@@ -76,12 +77,12 @@ static void
 vivi_code_substring_class_init (ViviCodeSubstringClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_substring_dispose;
 
-  token_class->print = vivi_code_substring_print;
-  token_class->compile = vivi_code_substring_compile;
+  value_class->print_value = vivi_code_substring_print_value;
+  value_class->compile_value = vivi_code_substring_compile_value;
 }
 
 static void
diff --git a/vivified/code/vivi_code_unary.c b/vivified/code/vivi_code_unary.c
index 023f56e..609827b 100644
--- a/vivified/code/vivi_code_unary.c
+++ b/vivified/code/vivi_code_unary.c
@@ -56,9 +56,9 @@ vivi_code_unary_optimize (ViviCodeValue *value, SwfdecAsValueType hint)
 }
 
 static void
-vivi_code_unary_print (ViviCodeToken *token, ViviCodePrinter*printer)
+vivi_code_unary_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
 {
-  ViviCodeUnary *unary = VIVI_CODE_UNARY (token);
+  ViviCodeUnary *unary = VIVI_CODE_UNARY (value);
   char *sign;
 
   /* FIXME: ugly! */
@@ -70,9 +70,9 @@ vivi_code_unary_print (ViviCodeToken *token, ViviCodePrinter*printer)
 }
 
 static void
-vivi_code_unary_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_unary_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
 {
-  ViviCodeUnary *unary = VIVI_CODE_UNARY (token);
+  ViviCodeUnary *unary = VIVI_CODE_UNARY (value);
 
   g_return_if_fail (unary->operation == '!');
 
@@ -91,14 +91,12 @@ static void
 vivi_code_unary_class_init (ViviCodeUnaryClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
   ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
   object_class->dispose = vivi_code_unary_dispose;
 
-  token_class->print = vivi_code_unary_print;
-  token_class->compile = vivi_code_unary_compile;
-
+  value_class->print_value = vivi_code_unary_print_value;
+  value_class->compile_value = vivi_code_unary_compile_value;
   value_class->is_constant = vivi_code_unary_is_constant;
   value_class->optimize = vivi_code_unary_optimize;
 }
diff --git a/vivified/code/vivi_code_undefined.c b/vivified/code/vivi_code_undefined.c
index 1b74017..4602fc4 100644
--- a/vivified/code/vivi_code_undefined.c
+++ b/vivified/code/vivi_code_undefined.c
@@ -33,13 +33,15 @@
 G_DEFINE_TYPE (ViviCodeUndefined, vivi_code_undefined, VIVI_TYPE_CODE_CONSTANT)
 
 static void
-vivi_code_undefined_print (ViviCodeToken *token, ViviCodePrinter *printer)
+vivi_code_undefined_print_value (ViviCodeValue *value,
+    ViviCodePrinter *printer)
 {
   vivi_code_printer_print (printer, "undefined");
 }
 
 static void
-vivi_code_undefined_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+vivi_code_undefined_compile_value (ViviCodeValue *value,
+    ViviCodeCompiler *compiler)
 {
   ViviCodeAsm *code;
 
@@ -57,11 +59,11 @@ vivi_code_undefined_get_variable_name (ViviCodeConstant *constant)
 static void
 vivi_code_undefined_class_init (ViviCodeUndefinedClass *klass)
 {
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
   ViviCodeConstantClass *constant_class = VIVI_CODE_CONSTANT_CLASS (klass);
 
-  token_class->print = vivi_code_undefined_print;
-  token_class->compile = vivi_code_undefined_compile;
+  value_class->print_value = vivi_code_undefined_print_value;
+  value_class->compile_value = vivi_code_undefined_compile_value;
 
   constant_class->get_variable_name = vivi_code_undefined_get_variable_name;
 }
diff --git a/vivified/code/vivi_code_value.c b/vivified/code/vivi_code_value.c
index 30539cf..f0d70ce 100644
--- a/vivified/code/vivi_code_value.c
+++ b/vivified/code/vivi_code_value.c
@@ -22,23 +22,38 @@
 #endif
 
 #include "vivi_code_value.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_compiler.h"
+#include "vivi_code_asm_code_default.h"
 
-G_DEFINE_ABSTRACT_TYPE (ViviCodeValue, vivi_code_value, VIVI_TYPE_CODE_TOKEN)
+G_DEFINE_ABSTRACT_TYPE (ViviCodeValue, vivi_code_value, VIVI_TYPE_CODE_STATEMENT)
 
 static void
-vivi_code_value_dispose (GObject *object)
+vivi_code_value_print (ViviCodeToken *token, ViviCodePrinter *printer)
 {
-  //ViviCodeValue *dec = VIVI_CODE_VAULE (object);
+  ViviCodeValue *value = VIVI_CODE_VALUE (token);
 
-  G_OBJECT_CLASS (vivi_code_value_parent_class)->dispose (object);
+  vivi_code_printer_print_value (printer, value, VIVI_PRECEDENCE_MIN);
+  vivi_code_printer_print (printer, ";");
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_code_value_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+{
+  ViviCodeValue *value = VIVI_CODE_VALUE (token);
+
+  vivi_code_compiler_compile_value (compiler, value);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_pop_new ());
 }
 
 static void
 vivi_code_value_class_init (ViviCodeValueClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
 
-  object_class->dispose = vivi_code_value_dispose;
+  token_class->print = vivi_code_value_print;
+  token_class->compile = vivi_code_value_compile;
 }
 
 static void
diff --git a/vivified/code/vivi_code_value.h b/vivified/code/vivi_code_value.h
index df2438f..c5c145d 100644
--- a/vivified/code/vivi_code_value.h
+++ b/vivified/code/vivi_code_value.h
@@ -20,7 +20,7 @@
 #ifndef _VIVI_CODE_VALUE_H_
 #define _VIVI_CODE_VALUE_H_
 
-#include <vivified/code/vivi_code_token.h>
+#include <vivified/code/vivi_code_statement.h>
 
 G_BEGIN_DECLS
 
@@ -61,14 +61,19 @@ typedef struct _ViviCodeValueClass ViviCodeValueClass;
 
 struct _ViviCodeValue
 {
-  ViviCodeToken		token;
+  ViviCodeStatement		statement;
 
-  ViviPrecedence	precedence;
+  ViviPrecedence		precedence;
 };
 
 struct _ViviCodeValueClass
 {
-  ViviCodeTokenClass  	token_class;
+  ViviCodeStatementClass	statement_class;
+
+  void			(* print_value)			(ViviCodeValue *	value,
+							 ViviCodePrinter *	printer);
+  void			(* compile_value)		(ViviCodeValue *	value,
+							 ViviCodeCompiler *	compiler);
 
   gboolean		(* is_constant)			(ViviCodeValue *	value);
   ViviCodeValue *	(* optimize)			(ViviCodeValue *	value,
commit 75aec10227a41935e3bf62231332d6957ca72c32
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 10:06:11 2008 +0300

    Add vivi_code_compiler_take_code to get rid of add_code, g_object_unref pairs

diff --git a/vivified/code/vivi_code_and.c b/vivified/code/vivi_code_and.c
index 34bb2cf..4ac5154 100644
--- a/vivified/code/vivi_code_and.c
+++ b/vivified/code/vivi_code_and.c
@@ -32,32 +32,21 @@ static void
 vivi_code_and_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeBinary *binary = VIVI_CODE_BINARY (token);
-  ViviCodeAsm *code;
   ViviCodeLabel *label_end;
 
   vivi_code_compiler_compile_value (compiler, binary->left);
 
-  code = vivi_code_asm_push_duplicate_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
-
-  code = vivi_code_asm_not_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_push_duplicate_new ());
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
 
   label_end = vivi_code_compiler_create_label (compiler, "and_end");
-  code = vivi_code_asm_if_new (label_end);
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_if_new (label_end));
 
-  code = vivi_code_asm_pop_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_pop_new ());
 
   vivi_code_compiler_compile_value (compiler, binary->right);
 
-  vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_end));
-  g_object_unref (label_end);
+  vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
 }
 
 static void
diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index 48dd66e..7b4d3c1 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -117,8 +117,7 @@ vivi_code_assignment_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   } else {
     code = vivi_code_asm_set_variable_new ();
   }
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 }
 
 static void
diff --git a/vivified/code/vivi_code_binary.c b/vivified/code/vivi_code_binary.c
index d288627..26188f9 100644
--- a/vivified/code/vivi_code_binary.c
+++ b/vivified/code/vivi_code_binary.c
@@ -61,15 +61,12 @@ vivi_code_binary_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeBinary *binary = VIVI_CODE_BINARY (token);
   ViviCodeBinaryClass *klass = VIVI_CODE_BINARY_GET_CLASS (binary);
-  ViviCodeAsm *code;
 
   vivi_code_compiler_compile_value (compiler, binary->left);
   vivi_code_compiler_compile_value (compiler, binary->right);
 
   g_assert (klass->asm_constructor != 0);
-  code = klass->asm_constructor ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, klass->asm_constructor ());
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_boolean.c b/vivified/code/vivi_code_boolean.c
index dd5ae83..b97f8a7 100644
--- a/vivified/code/vivi_code_boolean.c
+++ b/vivified/code/vivi_code_boolean.c
@@ -44,8 +44,7 @@ vivi_code_boolean_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 
   code = vivi_code_asm_push_new ();
   vivi_code_asm_push_add_boolean (VIVI_CODE_ASM_PUSH (code), b->value);
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 }
 
 static char *
diff --git a/vivified/code/vivi_code_builtin_call.c b/vivified/code/vivi_code_builtin_call.c
index 06174eb..a43dd7d 100644
--- a/vivified/code/vivi_code_builtin_call.c
+++ b/vivified/code/vivi_code_builtin_call.c
@@ -43,12 +43,9 @@ vivi_code_builtin_call_compile (ViviCodeToken *token,
     ViviCodeCompiler *compiler)
 {
   ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (token);
-  ViviCodeAsm *code;
 
   g_assert (klass->asm_constructor != NULL);
-  code = klass->asm_constructor ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, klass->asm_constructor ());
 }
 
 static void
diff --git a/vivified/code/vivi_code_builtin_statement.c b/vivified/code/vivi_code_builtin_statement.c
index 7802868..a53b202 100644
--- a/vivified/code/vivi_code_builtin_statement.c
+++ b/vivified/code/vivi_code_builtin_statement.c
@@ -46,12 +46,9 @@ vivi_code_builtin_statement_compile (ViviCodeToken *token,
 {
   ViviCodeBuiltinStatementClass *klass =
     VIVI_CODE_BUILTIN_STATEMENT_GET_CLASS (token);
-  ViviCodeAsm *code;
 
   g_assert (klass->asm_constructor != NULL);
-  code = klass->asm_constructor ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, klass->asm_constructor ());
 }
 
 static void
diff --git a/vivified/code/vivi_code_builtin_value_call.c b/vivified/code/vivi_code_builtin_value_call.c
index 0fbbcc4..fa17b0d 100644
--- a/vivified/code/vivi_code_builtin_value_call.c
+++ b/vivified/code/vivi_code_builtin_value_call.c
@@ -62,15 +62,12 @@ vivi_code_builtin_value_call_compile (ViviCodeToken *token,
 {
   ViviCodeBuiltinCallClass *klass = VIVI_CODE_BUILTIN_CALL_GET_CLASS (token);
   ViviCodeBuiltinValueCall *call = VIVI_CODE_BUILTIN_VALUE_CALL (token);
-  ViviCodeAsm *code;
 
   g_assert (call->value != NULL);
   vivi_code_compiler_compile_value (compiler, call->value);
 
   g_assert (klass->asm_constructor != NULL);
-  code = klass->asm_constructor ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, klass->asm_constructor ());
 }
 
 static void
diff --git a/vivified/code/vivi_code_builtin_value_statement.c b/vivified/code/vivi_code_builtin_value_statement.c
index d542a14..55cf183 100644
--- a/vivified/code/vivi_code_builtin_value_statement.c
+++ b/vivified/code/vivi_code_builtin_value_statement.c
@@ -67,15 +67,12 @@ vivi_code_builtin_value_statement_compile (ViviCodeToken *token,
     VIVI_CODE_BUILTIN_STATEMENT_GET_CLASS (token);
   ViviCodeBuiltinValueStatement *stmt =
     VIVI_CODE_BUILTIN_VALUE_STATEMENT (token);
-  ViviCodeAsm *code;
 
   g_assert (stmt->value != NULL);
   vivi_code_compiler_compile_value (compiler, stmt->value);
 
   g_assert (klass->asm_constructor != NULL);
-  code = klass->asm_constructor ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, klass->asm_constructor ());
 }
 
 static void
diff --git a/vivified/code/vivi_code_compiler.c b/vivified/code/vivi_code_compiler.c
index a588458..e7cdc45 100644
--- a/vivified/code/vivi_code_compiler.c
+++ b/vivified/code/vivi_code_compiler.c
@@ -64,16 +64,11 @@ void
 vivi_code_compiler_compile_script (ViviCodeCompiler *compiler,
     ViviCodeStatement *statement)
 {
-  ViviCodeAsm *code;
-
   g_return_if_fail (VIVI_IS_CODE_COMPILER (compiler));
   g_return_if_fail (VIVI_IS_CODE_STATEMENT (statement));
 
   vivi_code_compiler_compile_statement (compiler, statement);
-
-  code = vivi_code_asm_end_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_end_new ());
 
   vivi_code_assembler_pool (compiler->assembler);
   vivi_code_assembler_merge_push (compiler->assembler);
@@ -88,6 +83,16 @@ vivi_code_compiler_add_code (ViviCodeCompiler *compiler, ViviCodeAsm *code)
   vivi_code_assembler_add_code (compiler->assembler, code);
 }
 
+void
+vivi_code_compiler_take_code (ViviCodeCompiler *compiler, ViviCodeAsm *code)
+{
+  g_return_if_fail (VIVI_IS_CODE_COMPILER (compiler));
+  g_return_if_fail (VIVI_IS_CODE_ASM (code));
+
+  vivi_code_compiler_add_code (compiler, code);
+  g_object_unref (code);
+}
+
 ViviCodeLabel *
 vivi_code_compiler_create_label (ViviCodeCompiler *compiler,
     const char *prefix)
diff --git a/vivified/code/vivi_code_compiler.h b/vivified/code/vivi_code_compiler.h
index 5b7e83f..ad18dab 100644
--- a/vivified/code/vivi_code_compiler.h
+++ b/vivified/code/vivi_code_compiler.h
@@ -65,6 +65,8 @@ void			vivi_code_compiler_compile_script	(ViviCodeCompiler *	compiler,
 
 void			vivi_code_compiler_add_code		(ViviCodeCompiler	*compiler,
 								 ViviCodeAsm		*code);
+void			vivi_code_compiler_take_code		(ViviCodeCompiler	*compiler,
+								 ViviCodeAsm		*code);
 
 ViviCodeAssembler *	vivi_code_compiler_get_assembler	(ViviCodeCompiler *	compiler);
 guint			vivi_code_compiler_get_version		(ViviCodeCompiler *	compiler);
diff --git a/vivified/code/vivi_code_concat.c b/vivified/code/vivi_code_concat.c
index 01bf74f..ff6668f 100644
--- a/vivified/code/vivi_code_concat.c
+++ b/vivified/code/vivi_code_concat.c
@@ -58,14 +58,11 @@ static void
 vivi_code_concat_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeConcat *concat = VIVI_CODE_CONCAT (token);
-  ViviCodeAsm *code;
 
   vivi_code_compiler_compile_value (compiler, concat->first);
   vivi_code_compiler_compile_value (compiler, concat->second);
 
-  code = vivi_code_asm_string_add_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_string_add_new ());
 }
 
 static void
diff --git a/vivified/code/vivi_code_function.c b/vivified/code/vivi_code_function.c
index 9a349b8..5652022 100644
--- a/vivified/code/vivi_code_function.c
+++ b/vivified/code/vivi_code_function.c
@@ -90,14 +90,12 @@ vivi_code_function_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 	g_ptr_array_index (function->arguments, i), 0);
   }
 
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 
   if (function->body != NULL)
     vivi_code_compiler_compile_statement (compiler, function->body);
 
-  vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_end));
-  g_object_unref (label_end);
+  vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_function_call.c b/vivified/code/vivi_code_function_call.c
index be0037c..20377df 100644
--- a/vivified/code/vivi_code_function_call.c
+++ b/vivified/code/vivi_code_function_call.c
@@ -157,8 +157,7 @@ vivi_code_function_call_compile (ViviCodeToken *token,
     }
   }
 
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_function_declaration.c b/vivified/code/vivi_code_function_declaration.c
index e157bd2..dfcf9d2 100644
--- a/vivified/code/vivi_code_function_declaration.c
+++ b/vivified/code/vivi_code_function_declaration.c
@@ -101,14 +101,12 @@ vivi_code_function_declaration_compile (ViviCodeToken *token,
 	g_ptr_array_index (function->arguments, i), 0);
   }
 
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 
   if (function->body != NULL)
     vivi_code_compiler_compile_statement (compiler, function->body);
 
-  vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_end));
-  g_object_unref (label_end);
+  vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
 }
 
 static void
diff --git a/vivified/code/vivi_code_get.c b/vivified/code/vivi_code_get.c
index 0d3bfcd..5a8654f 100644
--- a/vivified/code/vivi_code_get.c
+++ b/vivified/code/vivi_code_get.c
@@ -90,8 +90,7 @@ vivi_code_get_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
     code = vivi_code_asm_get_variable_new ();
   }
 
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_get_url.c b/vivified/code/vivi_code_get_url.c
index 23b13a5..724e1c3 100644
--- a/vivified/code/vivi_code_get_url.c
+++ b/vivified/code/vivi_code_get_url.c
@@ -72,10 +72,8 @@ vivi_code_get_url_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   vivi_code_value_compile (url->url, assembler);
   vivi_code_value_compile (url->target, assembler);
 
-  code =
-    vivi_code_asm_get_url2_new (url->method, url->internal, url->variables);
-  vivi_code_assembler_add_code (assembler, code);
-  g_object_unref (code);
+  vivi_code_assembler_take_code (assembler,
+      vivi_code_asm_get_url2_new (url->method, url->internal, url->variables));
 #endif
 }
 
diff --git a/vivified/code/vivi_code_goto.c b/vivified/code/vivi_code_goto.c
index 1a7d876..21beb41 100644
--- a/vivified/code/vivi_code_goto.c
+++ b/vivified/code/vivi_code_goto.c
@@ -54,11 +54,9 @@ static void
 vivi_code_goto_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeGoto *gotoo = VIVI_CODE_GOTO (token);
-  ViviCodeAsm *code;
 
-  code = vivi_code_asm_jump_new (gotoo->label);
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler,
+      vivi_code_asm_jump_new (gotoo->label));
 }
 
 static void
diff --git a/vivified/code/vivi_code_if.c b/vivified/code/vivi_code_if.c
index 0a04c0f..0955937 100644
--- a/vivified/code/vivi_code_if.c
+++ b/vivified/code/vivi_code_if.c
@@ -133,40 +133,30 @@ vivi_code_if_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeIf *stmt = VIVI_CODE_IF (token);
   ViviCodeLabel *label_if, *label_end;
-  ViviCodeAsm *code;
 
   vivi_code_compiler_compile_value (compiler, stmt->condition);
 
   if (stmt->else_statement) {
     label_if = vivi_code_compiler_create_label (compiler, "if_true");
-    code = vivi_code_asm_if_new (label_if);
-    vivi_code_compiler_add_code (compiler, code);
-    g_object_unref (code);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_if_new (label_if));
 
     vivi_code_compiler_compile_statement (compiler, stmt->else_statement);
 
     label_end = vivi_code_compiler_create_label (compiler, "if_end");
-    code = vivi_code_asm_jump_new (label_end);
-    vivi_code_compiler_add_code (compiler, code);
-    g_object_unref (code);
+    vivi_code_compiler_take_code (compiler,
+	vivi_code_asm_jump_new (label_end));
 
-    vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_if));
-    g_object_unref (label_if);
+    vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_if));
   } else {
-    code = vivi_code_asm_not_new ();
-    vivi_code_compiler_add_code (compiler, code);
-    g_object_unref (code);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
 
     label_end = vivi_code_compiler_create_label (compiler, "if_end");
-    code = vivi_code_asm_if_new (label_end);
-    vivi_code_compiler_add_code (compiler, code);
-    g_object_unref (code);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_if_new (label_end));
   }
 
   vivi_code_compiler_compile_statement (compiler, stmt->if_statement);
 
-  vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_end));
-  g_object_unref (label_end);
+  vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
 }
 
 static void
diff --git a/vivified/code/vivi_code_increment.c b/vivified/code/vivi_code_increment.c
index 9f2a810..be2c2e6 100644
--- a/vivified/code/vivi_code_increment.c
+++ b/vivified/code/vivi_code_increment.c
@@ -53,13 +53,9 @@ static void
 vivi_code_increment_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (token);
-  ViviCodeAsm *code;
 
   vivi_code_compiler_compile_value (compiler, increment->value);
-
-  code = vivi_code_asm_increment_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_increment_new ());
 }
 
 static void
diff --git a/vivified/code/vivi_code_init_array.c b/vivified/code/vivi_code_init_array.c
index 778b4fe..ecb7b7c 100644
--- a/vivified/code/vivi_code_init_array.c
+++ b/vivified/code/vivi_code_init_array.c
@@ -85,7 +85,6 @@ vivi_code_init_array_compile (ViviCodeToken *token,
 {
   ViviCodeInitArray *array = VIVI_CODE_INIT_ARRAY (token);
   ViviCodeValue *count;
-  ViviCodeAsm *code;
   guint i;
 
   for (i = array->variables->len; i > 0; i--) {
@@ -96,9 +95,7 @@ vivi_code_init_array_compile (ViviCodeToken *token,
   vivi_code_compiler_compile_value (compiler, count);
   g_object_unref (count);
 
-  code = vivi_code_asm_init_array_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_init_array_new ());
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_init_object.c b/vivified/code/vivi_code_init_object.c
index 3521d09..09c02bd 100644
--- a/vivified/code/vivi_code_init_object.c
+++ b/vivified/code/vivi_code_init_object.c
@@ -84,7 +84,6 @@ vivi_code_init_object_compile (ViviCodeToken *token,
 {
   ViviCodeInitObject *object = VIVI_CODE_INIT_OBJECT (token);
   ViviCodeValue *count;
-  ViviCodeAsm *code;
   guint i;
 
   for (i = 0; i < object->variables->len; i++) {
@@ -97,9 +96,7 @@ vivi_code_init_object_compile (ViviCodeToken *token,
   vivi_code_compiler_compile_value (compiler, count);
   g_object_unref (count);
 
-  code = vivi_code_asm_init_object_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_init_object_new ());
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_label.c b/vivified/code/vivi_code_label.c
index 2039ebd..f7533f3 100644
--- a/vivified/code/vivi_code_label.c
+++ b/vivified/code/vivi_code_label.c
@@ -79,12 +79,9 @@ static void
 vivi_code_label_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeLabel *label = VIVI_CODE_LABEL (token);
-  ViviCodeAsm *code;
 
-  code =
-    VIVI_CODE_ASM (vivi_code_compiler_create_label (compiler, label->name));
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler,
+      VIVI_CODE_ASM (vivi_code_compiler_create_label (compiler, label->name)));
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_loop.c b/vivified/code/vivi_code_loop.c
index ae3bdd4..fc6b77f 100644
--- a/vivified/code/vivi_code_loop.c
+++ b/vivified/code/vivi_code_loop.c
@@ -80,7 +80,6 @@ vivi_code_loop_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeLoop *loop = VIVI_CODE_LOOP (token);
   ViviCodeLabel *label_start, *label_end = NULL;
-  ViviCodeAsm *code;
 
   label_start = vivi_code_compiler_create_label (compiler, "loop_start");
   vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_start));
@@ -88,28 +87,20 @@ vivi_code_loop_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   if (loop->condition) {
     vivi_code_compiler_compile_value (compiler, loop->condition);
 
-    code = vivi_code_asm_not_new ();
-    vivi_code_compiler_add_code (compiler, code);
-    g_object_unref (code);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
 
     label_end = vivi_code_compiler_create_label (compiler, "loop_end");
-    code = vivi_code_asm_if_new (label_end);
-    vivi_code_compiler_add_code (compiler, code);
-    g_object_unref (code);
+    vivi_code_compiler_take_code (compiler, vivi_code_asm_if_new (label_end));
   }
 
   if (loop->statement)
     vivi_code_compiler_compile_statement (compiler, loop->statement);
 
-  code = vivi_code_asm_jump_new (label_start);
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_jump_new (label_start));
   g_object_unref (label_start);
 
-  if (loop->condition) {
-    vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_end));
-    g_object_unref (label_end);
-  }
+  if (loop->condition)
+    vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
 }
 
 static void
diff --git a/vivified/code/vivi_code_null.c b/vivified/code/vivi_code_null.c
index b2099f4..2f49c84 100644
--- a/vivified/code/vivi_code_null.c
+++ b/vivified/code/vivi_code_null.c
@@ -45,8 +45,7 @@ vivi_code_null_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 
   code = vivi_code_asm_push_new ();
   vivi_code_asm_push_add_null (VIVI_CODE_ASM_PUSH (code));
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 }
 
 static char *
diff --git a/vivified/code/vivi_code_number.c b/vivified/code/vivi_code_number.c
index e8e17d5..70a990b 100644
--- a/vivified/code/vivi_code_number.c
+++ b/vivified/code/vivi_code_number.c
@@ -75,8 +75,7 @@ vivi_code_number_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
       g_assert_not_reached ();
   }
 
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 }
 
 static void
diff --git a/vivified/code/vivi_code_or.c b/vivified/code/vivi_code_or.c
index 843dfc4..5a6f212 100644
--- a/vivified/code/vivi_code_or.c
+++ b/vivified/code/vivi_code_or.c
@@ -32,28 +32,17 @@ static void
 vivi_code_or_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeBinary *binary = VIVI_CODE_BINARY (token);
-  ViviCodeAsm *code;
   ViviCodeLabel *label_end;
 
   vivi_code_compiler_compile_value (compiler, binary->left);
-
-  code = vivi_code_asm_push_duplicate_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_push_duplicate_new ());
 
   label_end = vivi_code_compiler_create_label (compiler, "or_end");
-  code = vivi_code_asm_if_new (label_end);
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
-
-  code = vivi_code_asm_pop_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_if_new (label_end));
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_pop_new ());
 
   vivi_code_compiler_compile_value (compiler, binary->right);
-
-  vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_end));
-  g_object_unref (label_end);
+  vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
 }
 
 static void
diff --git a/vivified/code/vivi_code_return.c b/vivified/code/vivi_code_return.c
index ce9d51b..77d2c5c 100644
--- a/vivified/code/vivi_code_return.c
+++ b/vivified/code/vivi_code_return.c
@@ -60,20 +60,16 @@ static void
 vivi_code_return_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeReturn *ret = VIVI_CODE_RETURN (token);
-  ViviCodeAsm *code;
 
   if (ret->value) {
     vivi_code_compiler_compile_value (compiler, ret->value);
   } else {
     ViviCodeAsm *push = vivi_code_asm_push_new ();
     vivi_code_asm_push_add_undefined (VIVI_CODE_ASM_PUSH (push));
-    vivi_code_compiler_add_code (compiler, push);
-    g_object_unref (push);
+    vivi_code_compiler_take_code (compiler, push);
   }
 
-  code = vivi_code_asm_return_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_return_new ());
 }
 
 static void
diff --git a/vivified/code/vivi_code_string.c b/vivified/code/vivi_code_string.c
index e4910a8..807442f 100644
--- a/vivified/code/vivi_code_string.c
+++ b/vivified/code/vivi_code_string.c
@@ -60,8 +60,7 @@ vivi_code_string_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 
   code = vivi_code_asm_push_new ();
   vivi_code_asm_push_add_string (VIVI_CODE_ASM_PUSH (code), string->value);
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 }
 
 static char *
diff --git a/vivified/code/vivi_code_substring.c b/vivified/code/vivi_code_substring.c
index 7dcb044..fe1ab0a 100644
--- a/vivified/code/vivi_code_substring.c
+++ b/vivified/code/vivi_code_substring.c
@@ -63,15 +63,12 @@ vivi_code_substring_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   g_printerr ("Implement substring\n");
 #if 0
   ViviCodeSubstring *substring = VIVI_CODE_SUBSTRING (token);
-  ViviCodeAsm *code;
 
   vivi_code_value_compile (substring->string, compiler);
   vivi_code_value_compile (substring->index_, compiler);
   vivi_code_value_compile (substring->count, compiler);
 
-  code = vivi_code_asm_string_extract_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_string_extract_new ());
 #endif
 }
 
diff --git a/vivified/code/vivi_code_throw.c b/vivified/code/vivi_code_throw.c
index df88d2a..b368d43 100644
--- a/vivified/code/vivi_code_throw.c
+++ b/vivified/code/vivi_code_throw.c
@@ -60,15 +60,11 @@ static void
 vivi_code_throw_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeThrow *throw_ = VIVI_CODE_THROW (token);
-  ViviCodeAsm *code;
 
   g_return_if_fail (throw_->value != NULL);
 
   vivi_code_compiler_compile_value (compiler, throw_->value);
-
-  code = vivi_code_asm_throw_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_throw_new ());
 }
 
 static void
diff --git a/vivified/code/vivi_code_unary.c b/vivified/code/vivi_code_unary.c
index 0c5c1be..023f56e 100644
--- a/vivified/code/vivi_code_unary.c
+++ b/vivified/code/vivi_code_unary.c
@@ -73,15 +73,12 @@ static void
 vivi_code_unary_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeUnary *unary = VIVI_CODE_UNARY (token);
-  ViviCodeAsm *code;
 
   g_return_if_fail (unary->operation == '!');
 
   vivi_code_compiler_compile_value (compiler, unary->value);
 
-  code = vivi_code_asm_not_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
 }
 
 static gboolean
diff --git a/vivified/code/vivi_code_undefined.c b/vivified/code/vivi_code_undefined.c
index 32fcbd2..1b74017 100644
--- a/vivified/code/vivi_code_undefined.c
+++ b/vivified/code/vivi_code_undefined.c
@@ -45,8 +45,7 @@ vivi_code_undefined_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 
   code = vivi_code_asm_push_new ();
   vivi_code_asm_push_add_undefined (VIVI_CODE_ASM_PUSH (code));
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, code);
 }
 
 static char *
diff --git a/vivified/code/vivi_code_value_statement.c b/vivified/code/vivi_code_value_statement.c
index b3092ba..18cff57 100644
--- a/vivified/code/vivi_code_value_statement.c
+++ b/vivified/code/vivi_code_value_statement.c
@@ -54,13 +54,9 @@ vivi_code_value_statement_compile (ViviCodeToken *token,
     ViviCodeCompiler *compiler)
 {
   ViviCodeValueStatement *stmt = VIVI_CODE_VALUE_STATEMENT (token);
-  ViviCodeAsm *code;
 
   vivi_code_compiler_compile_value (compiler, stmt->value);
-
-  code = vivi_code_asm_pop_new ();
-  vivi_code_compiler_add_code (compiler, code);
-  g_object_unref (code);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_pop_new ());
 }
 
 static void
commit ce4bfb81dc73b7367a198f79847beb4dbe130c39
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed May 14 09:45:45 2008 +0300

    A fix to the parsing of prefix increment

diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index e7399b8..2011257 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -1948,12 +1948,14 @@ static ViviCodeValue *
 parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
 {
   ViviCodeValue *value, *tmp, *one;
+  gboolean increment = FALSE;
 
   switch ((guint) vivi_parser_scanner_peek_next_token (data->scanner)) {
     /*case TOKEN_DELETE:
     case TOKEN_VOID:
     case TOKEN_TYPEOF:*/
     case TOKEN_INCREASE:
+      increment = TRUE;
     case TOKEN_DESCREASE:
       vivi_parser_start_code_token (data);
 
@@ -1968,8 +1970,8 @@ parse_unary_expression (ParseData *data, ViviCodeStatement **statement)
       }
 
       one = vivi_code_number_new (1);
-      tmp = (vivi_parser_scanner_peek_next_token (data->scanner) == TOKEN_INCREASE ?
-	  vivi_code_add_new : vivi_code_subtract_new) (value, one);
+      tmp = (increment ? vivi_code_increment_new (value) :
+	  vivi_code_subtract_new (value, one));
       g_object_unref (one);
 
       vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (tmp));
commit 618f6eff8b050169a44060130fe7ccdfbdc31eef
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue May 13 15:09:40 2008 +0300

    Add ViviCodeIncrement and use it when parsing

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 93a75c0..cd811f8 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -69,6 +69,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_get_url.c \
 	vivi_code_goto.c \
 	vivi_code_if.c \
+	vivi_code_increment.c \
 	vivi_code_init_array.c \
 	vivi_code_init_object.c \
 	vivi_code_label.c \
@@ -145,6 +146,7 @@ noinst_HEADERS = \
 	vivi_code_get_url.h \
 	vivi_code_goto.h \
 	vivi_code_if.h \
+	vivi_code_increment.h \
 	vivi_code_init_array.h \
 	vivi_code_init_object.h \
 	vivi_code_label.h \
diff --git a/vivified/code/vivi_code_increment.c b/vivified/code/vivi_code_increment.c
new file mode 100644
index 0000000..9f2a810
--- /dev/null
+++ b/vivified/code/vivi_code_increment.c
@@ -0,0 +1,93 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_code_increment.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_compiler.h"
+#include "vivi_code_asm_code_default.h"
+
+G_DEFINE_TYPE (ViviCodeIncrement, vivi_code_increment, VIVI_TYPE_CODE_VALUE)
+
+static void
+vivi_code_increment_dispose (GObject *object)
+{
+  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (object);
+
+  g_object_unref (increment->value);
+
+  G_OBJECT_CLASS (vivi_code_increment_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_increment_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (token);
+
+  vivi_code_printer_print_value (printer, increment->value,
+      VIVI_PRECEDENCE_INCREMENT);
+  vivi_code_printer_print (printer, "++");
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_code_increment_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+{
+  ViviCodeIncrement *increment = VIVI_CODE_INCREMENT (token);
+  ViviCodeAsm *code;
+
+  vivi_code_compiler_compile_value (compiler, increment->value);
+
+  code = vivi_code_asm_increment_new ();
+  vivi_code_compiler_add_code (compiler, code);
+  g_object_unref (code);
+}
+
+static void
+vivi_code_increment_class_init (ViviCodeIncrementClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+
+  object_class->dispose = vivi_code_increment_dispose;
+
+  token_class->print = vivi_code_increment_print;
+  token_class->compile = vivi_code_increment_compile;
+}
+
+static void
+vivi_code_increment_init (ViviCodeIncrement *increment)
+{
+}
+
+ViviCodeValue *
+vivi_code_increment_new (ViviCodeValue *value)
+{
+  ViviCodeIncrement *increment;
+
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
+
+  increment = g_object_new (VIVI_TYPE_CODE_INCREMENT, NULL);
+  increment->value = g_object_ref (value);
+
+  return VIVI_CODE_VALUE (increment);
+}
diff --git a/vivified/code/vivi_code_increment.h b/vivified/code/vivi_code_increment.h
new file mode 100644
index 0000000..f163cef
--- /dev/null
+++ b/vivified/code/vivi_code_increment.h
@@ -0,0 +1,57 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_CODE_INCREMENT_H_
+#define _VIVI_CODE_INCREMENT_H_
+
+#include <vivified/code/vivi_code_value.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeIncrement ViviCodeIncrement;
+typedef struct _ViviCodeIncrementClass ViviCodeIncrementClass;
+
+#define VIVI_TYPE_CODE_INCREMENT                    (vivi_code_increment_get_type())
+#define VIVI_IS_CODE_INCREMENT(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_INCREMENT))
+#define VIVI_IS_CODE_INCREMENT_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_INCREMENT))
+#define VIVI_CODE_INCREMENT(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_INCREMENT, ViviCodeIncrement))
+#define VIVI_CODE_INCREMENT_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_INCREMENT, ViviCodeIncrementClass))
+#define VIVI_CODE_INCREMENT_INCREMENT_CLASS(obj)          (G_TYPE_INSTANCE_INCREMENT_CLASS ((obj), VIVI_TYPE_CODE_INCREMENT, ViviCodeIncrementClass))
+
+struct _ViviCodeIncrement
+{
+  ViviCodeValue		token;
+
+  ViviCodeValue *	value;
+};
+
+struct _ViviCodeIncrementClass
+{
+  ViviCodeValueClass	value_class;
+};
+
+GType			vivi_code_increment_get_type		(void);
+
+ViviCodeValue *	vivi_code_increment_new				(ViviCodeValue *	value);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index b018ac1..e7399b8 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -50,6 +50,7 @@
 #include "vivi_code_get_url.h"
 #include "vivi_code_goto.h"
 #include "vivi_code_if.h"
+#include "vivi_code_increment.h"
 #include "vivi_code_init_array.h"
 #include "vivi_code_init_object.h"
 #include "vivi_code_loop.h"
@@ -1900,7 +1901,7 @@ parse_postfix_expression (ParseData *data, ViviCodeStatement **statement)
   }
 
   one = vivi_code_number_new (1);
-  operation = (add ? vivi_code_add_new : vivi_code_subtract_new) (value, one);
+  operation = (add ? vivi_code_increment_new (value) : vivi_code_subtract_new (value, one));
   g_object_unref (one);
 
   vivi_parser_duplicate_code_token (data);
commit 2c2ececc124a6407a0cb0d7a62c6712887f7935b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue May 13 15:02:04 2008 +0300

    Add a test for compiling asm statements that take no parameters

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index b65167a..1ec22b4 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -20,6 +20,8 @@ EXTRA_DIST = \
 	array_literal.as.expect \
 	asm_empty.as \
 	asm_empty.as.expect \
+	asm_default.as \
+	asm_default.as.expect \
 	assignment.as \
 	assignment.as.expect \
 	assignment_operator.as \
diff --git a/vivified/code/test/compiler/asm_default.as b/vivified/code/test/compiler/asm_default.as
new file mode 100644
index 0000000..3ed95f8
--- /dev/null
+++ b/vivified/code/test/compiler/asm_default.as
@@ -0,0 +1,85 @@
+asm {
+  end
+  next_frame
+  previous_frame
+  play
+  stop
+  toggle_quality
+  stop_sounds
+  add
+  subtract
+  multiply
+  divide
+  equals
+  less
+  and
+  or
+  not
+  string_equals
+  string_length
+  string_extract
+  pop
+  to_integer
+  get_variable
+  set_variable
+  set_target2
+  string_add
+  get_property
+  set_property
+  clone_sprite
+  remove_sprite
+  trace
+  start_drag
+  end_drag
+  string_less
+  throw
+  cast
+  implements
+  random
+  mb_string_length
+  char_to_ascii
+  ascii_to_char
+  get_time
+  mb_string_extract
+  mb_char_to_ascii
+  mb_ascii_to_char
+  delete
+  delete2
+  define_local
+  call_function
+  return
+  modulo
+  new_object
+  define_local2
+  init_array
+  init_object
+  type_of
+  target_path
+  enumerate
+  add2
+  less2
+  equals2
+  to_number
+  to_string
+  push_duplicate
+  swap
+  get_member
+  set_member
+  increment
+  decrement
+  call_method
+  new_method
+  instance_of
+  enumerate2
+  breakpoint
+  bit_and
+  bit_or
+  bit_xor
+  bit_lshift
+  bit_rshift
+  bit_urshift
+  strict_equals
+  greater
+  string_greater
+  extends
+}
diff --git a/vivified/code/test/compiler/asm_default.as.expect b/vivified/code/test/compiler/asm_default.as.expect
new file mode 100644
index 0000000..83d8547
--- /dev/null
+++ b/vivified/code/test/compiler/asm_default.as.expect
@@ -0,0 +1,86 @@
+asm {
+  end
+  next_frame
+  previous_frame
+  play
+  stop
+  toggle_quality
+  stop_sounds
+  add
+  subtract
+  multiply
+  divide
+  equals
+  less
+  and
+  or
+  not
+  string_equals
+  string_length
+  string_extract
+  pop
+  to_integer
+  get_variable
+  set_variable
+  set_target2
+  string_add
+  get_property
+  set_property
+  clone_sprite
+  remove_sprite
+  trace
+  start_drag
+  end_drag
+  string_less
+  throw
+  cast
+  implements
+  random
+  mb_string_length
+  char_to_ascii
+  ascii_to_char
+  get_time
+  mb_string_extract
+  mb_char_to_ascii
+  mb_ascii_to_char
+  delete
+  delete2
+  define_local
+  call_function
+  return
+  modulo
+  new_object
+  define_local2
+  init_array
+  init_object
+  type_of
+  target_path
+  enumerate
+  add2
+  less2
+  equals2
+  to_number
+  to_string
+  push_duplicate
+  swap
+  get_member
+  set_member
+  increment
+  decrement
+  call_method
+  new_method
+  instance_of
+  enumerate2
+  breakpoint
+  bit_and
+  bit_or
+  bit_xor
+  bit_lshift
+  bit_rshift
+  bit_urshift
+  strict_equals
+  greater
+  string_greater
+  extends
+  end
+}
commit 4f85db56196c49cfc89f2cf27ce17d5ec205154c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue May 13 15:00:38 2008 +0300

    Add special handling for few keywords so parsing asm statements using them works

diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index aa74e9c..b018ac1 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -1174,7 +1174,19 @@ parse_asm_code (ParseData *data)
   guint i;
   char *identifier;
 
-  identifier = g_strdup (parse_identifier_value (data));
+  if (try_parse_token (data, TOKEN_THROW)) {
+    identifier = g_strdup ("throw");
+  } else if (try_parse_token (data, TOKEN_IMPLEMENTS)) {
+    identifier = g_strdup ("implements");
+  } else if (try_parse_token (data, TOKEN_DELETE)) {
+    identifier = g_strdup ("delete");
+  } else if (try_parse_token (data, TOKEN_RETURN)) {
+    identifier = g_strdup ("return");
+  } else if (try_parse_token (data, TOKEN_EXTENDS)) {
+    identifier = g_strdup ("extends");
+  } else {
+    identifier = g_strdup (parse_identifier_value (data));
+  }
 
   if (try_parse_token (data, TOKEN_COLON)) {
     ViviCodeAsm *code = VIVI_CODE_ASM (vivi_code_label_new (identifier));
@@ -1234,7 +1246,12 @@ parse_asm_statement (ParseData *data)
       code = parse_asm_code (data);
       vivi_code_assembler_add_code (assembler, code);
       g_object_unref (code);
-    } while (peek_token (data, TOKEN_IDENTIFIER));
+    } while (peek_token (data, TOKEN_IDENTIFIER) ||
+	peek_token (data, TOKEN_THROW) ||
+	peek_token (data, TOKEN_IMPLEMENTS) ||
+	peek_token (data, TOKEN_DELETE) ||
+	peek_token (data, TOKEN_RETURN) ||
+	peek_token (data, TOKEN_EXTENDS));
 
     if (!try_parse_token (data, TOKEN_BRACE_RIGHT)) {
       vivi_parser_error_unexpected_or (data, TOKEN_BRACE_RIGHT,
diff --git a/vivified/code/vivi_parser_scanner.c b/vivified/code/vivi_parser_scanner.c
index 54ab5fb..2cb8eff 100644
--- a/vivified/code/vivi_parser_scanner.c
+++ b/vivified/code/vivi_parser_scanner.c
@@ -196,6 +196,8 @@ static const struct {
   { TOKEN_RESERVED_KEYWORD, "RESERVED KEYWORD" },
 
   // ActionScript specific
+  { TOKEN_EXTENDS, "extends" },
+  { TOKEN_IMPLEMENTS, "implements" },
   { TOKEN_UNDEFINED, "undefined" },
 
   { TOKEN_LAST, NULL }
diff --git a/vivified/code/vivi_parser_scanner.h b/vivified/code/vivi_parser_scanner.h
index 2346e5e..3750052 100644
--- a/vivified/code/vivi_parser_scanner.h
+++ b/vivified/code/vivi_parser_scanner.h
@@ -140,6 +140,8 @@ typedef enum {
   TOKEN_RESERVED_KEYWORD,
 
   // ActionScript specific
+  TOKEN_EXTENDS,
+  TOKEN_IMPLEMENTS,
   TOKEN_UNDEFINED,
 
   TOKEN_LAST
diff --git a/vivified/code/vivi_parser_scanner_lex.l b/vivified/code/vivi_parser_scanner_lex.l
index 76d6c62..c99d836 100644
--- a/vivified/code/vivi_parser_scanner_lex.l
+++ b/vivified/code/vivi_parser_scanner_lex.l
@@ -188,11 +188,9 @@ identifier_part		[$_a-zA-Z0-9]
 "double"		{ return TOKEN_RESERVED_KEYWORD; }
 "enum"			{ return TOKEN_RESERVED_KEYWORD; }
 "export"		{ return TOKEN_RESERVED_KEYWORD; }
-"extends"		{ return TOKEN_RESERVED_KEYWORD; }
 "final"			{ return TOKEN_RESERVED_KEYWORD; }
 "float"			{ return TOKEN_RESERVED_KEYWORD; }
 "goto"			{ return TOKEN_RESERVED_KEYWORD; }
-"implements"		{ return TOKEN_RESERVED_KEYWORD; }
 "import"		{ return TOKEN_RESERVED_KEYWORD; }
 	/*"int"			{ return TOKEN_RESERVED_KEYWORD; }*/
 "interface"		{ return TOKEN_RESERVED_KEYWORD; }
@@ -210,6 +208,8 @@ identifier_part		[$_a-zA-Z0-9]
 "transient"		{ return TOKEN_RESERVED_KEYWORD; }
 "volatile"		{ return TOKEN_RESERVED_KEYWORD; }
 
+"extends"		{ return TOKEN_EXTENDS; }
+"implements"		{ return TOKEN_IMPLEMENTS; }
 "undefined"		{ return TOKEN_UNDEFINED; }
 
 "null"			{ return TOKEN_NULL; }


More information about the Swfdec-commits mailing list