[Swfdec-commits] 23 commits - vivified/code

Pekka Lampila medar at kemper.freedesktop.org
Fri May 23 06:44:21 PDT 2008


 vivified/code/Makefile.am                                     |   16 
 vivified/code/test/compiler/Makefile.am                       |   34 +
 vivified/code/test/compiler/asm_store.as                      |    3 
 vivified/code/test/compiler/asm_store.as.expect               |    4 
 vivified/code/test/compiler/assignment_member_value.as.expect |    3 
 vivified/code/test/compiler/automatic_semicolon.as            |    2 
 vivified/code/test/compiler/automatic_semicolon.as.expect     |    6 
 vivified/code/test/compiler/bitwise_not.as                    |    1 
 vivified/code/test/compiler/bitwise_not.as.expect             |    9 
 vivified/code/test/compiler/break.as                          |   15 
 vivified/code/test/compiler/break.as.expect                   |   40 +
 vivified/code/test/compiler/break_continue_label.as           |    9 
 vivified/code/test/compiler/break_continue_label.as.expect    |   21 
 vivified/code/test/compiler/combine_push.as                   |    5 
 vivified/code/test/compiler/combine_push.as.expect            |   12 
 vivified/code/test/compiler/continue.as                       |   15 
 vivified/code/test/compiler/continue.as.expect                |   38 +
 vivified/code/test/compiler/get_url.as                        |   18 
 vivified/code/test/compiler/get_url.as.expect                 |   19 
 vivified/code/test/compiler/increment_member_value.as.expect  |    9 
 vivified/code/test/compiler/label.as.expect                   |    2 
 vivified/code/test/compiler/misc_literal.as                   |    4 
 vivified/code/test/compiler/misc_literal.as.expect            |    8 
 vivified/code/test/compiler/not.as                            |    1 
 vivified/code/test/compiler/not.as.expect                     |    8 
 vivified/code/test/compiler/number.as                         |   10 
 vivified/code/test/compiler/number.as.expect                  |   14 
 vivified/code/test/compiler/string.as                         |    8 
 vivified/code/test/compiler/string.as.expect                  |   13 
 vivified/code/test/compiler/try.as                            |    7 
 vivified/code/test/compiler/try.as.expect                     |   18 
 vivified/code/test/compiler/try_no_catch.as                   |    5 
 vivified/code/test/compiler/try_no_catch.as.expect            |   13 
 vivified/code/test/compiler/try_no_finally.as                 |    5 
 vivified/code/test/compiler/try_no_finally.as.expect          |   14 
 vivified/code/test/compiler/unary_minus.as                    |    2 
 vivified/code/test/compiler/unary_minus.as.expect             |   10 
 vivified/code/test/compiler/unary_plus.as                     |    2 
 vivified/code/test/compiler/unary_plus.as.expect              |   10 
 vivified/code/test/compiler/var.as.expect                     |    4 
 vivified/code/test/compiler/void.as                           |    1 
 vivified/code/test/compiler/void.as.expect                    |    9 
 vivified/code/vivi_code_asm_get_url2.c                        |  129 ++++
 vivified/code/vivi_code_asm_get_url2.h                        |   60 ++
 vivified/code/vivi_code_asm_try.c                             |   72 +-
 vivified/code/vivi_code_asm_try.h                             |   20 
 vivified/code/vivi_code_bit_not.c                             |  104 +++
 vivified/code/vivi_code_bit_not.h                             |   57 ++
 vivified/code/vivi_code_break.c                               |    8 
 vivified/code/vivi_code_compiler.c                            |   85 ++-
 vivified/code/vivi_code_compiler.h                            |   11 
 vivified/code/vivi_code_continue.c                            |    8 
 vivified/code/vivi_code_get_url.c                             |   11 
 vivified/code/vivi_code_if.c                                  |    4 
 vivified/code/vivi_code_label.c                               |    4 
 vivified/code/vivi_code_label.h                               |    2 
 vivified/code/vivi_code_loop.c                                |   13 
 vivified/code/vivi_code_not.c                                 |  121 ++++
 vivified/code/vivi_code_not.h                                 |   57 ++
 vivified/code/vivi_code_try.c                                 |  142 +++++
 vivified/code/vivi_code_try.h                                 |   63 ++
 vivified/code/vivi_code_unary.c                               |  133 ----
 vivified/code/vivi_code_unary.h                               |   59 --
 vivified/code/vivi_code_void.c                                |  105 +++
 vivified/code/vivi_code_void.h                                |   57 ++
 vivified/code/vivi_compiler_get_temporary.c                   |   56 -
 vivified/code/vivi_compiler_get_temporary.h                   |   55 -
 vivified/code/vivi_compiler_goto_name.c                       |  102 ---
 vivified/code/vivi_compiler_goto_name.h                       |   60 --
 vivified/code/vivi_decompiler.c                               |   16 
 vivified/code/vivi_disassembler.c                             |  283 +++++-----
 vivified/code/vivi_parser.c                                   |  280 +++++++--
 72 files changed, 1876 insertions(+), 748 deletions(-)

New commits:
commit 29770467b0e5bc00085e294f08828ea2f09be1ff
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 16:36:28 2008 +0300

    Compiling try statements: Add small fixes and few test cases

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index dcd94cf..4e494f4 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -122,6 +122,12 @@ EXTRA_DIST = \
 	string.as.expect \
 	trace.as \
 	trace.as.expect \
+	try.as \
+	try.as.expect \
+	try_no_catch.as \
+	try_no_catch.as \
+	try_no_finally.as.expect \
+	try_no_finally.as.expect \
 	unary_minus.as \
 	unary_minus.as.expect \
 	unary_plus.as \
diff --git a/vivified/code/test/compiler/try.as b/vivified/code/test/compiler/try.as
new file mode 100644
index 0000000..a386335
--- /dev/null
+++ b/vivified/code/test/compiler/try.as
@@ -0,0 +1,7 @@
+try {
+  trace ("try");
+} catch (e) {
+  trace (e);
+} finally {
+  trace ("finally");
+};
diff --git a/vivified/code/test/compiler/try.as.expect b/vivified/code/test/compiler/try.as.expect
new file mode 100644
index 0000000..b5a9254
--- /dev/null
+++ b/vivified/code/test/compiler/try.as.expect
@@ -0,0 +1,18 @@
+asm {
+  pool "try", "e", "finally"
+  try has_catch has_finally "e" try_catch_0001 try_finally_0002 try_end_0003
+  push pool 0
+  trace
+
+try_catch_0001:
+  push pool 1
+  get_variable
+  trace
+
+try_finally_0002:
+  push pool 2
+  trace
+
+try_end_0003:
+  end
+}
diff --git a/vivified/code/test/compiler/try_no_catch.as b/vivified/code/test/compiler/try_no_catch.as
new file mode 100644
index 0000000..9b876ad
--- /dev/null
+++ b/vivified/code/test/compiler/try_no_catch.as
@@ -0,0 +1,5 @@
+try {
+  trace ("try");
+} finally {
+  trace ("finally");
+};
diff --git a/vivified/code/test/compiler/try_no_catch.as.expect b/vivified/code/test/compiler/try_no_catch.as.expect
new file mode 100644
index 0000000..03e8009
--- /dev/null
+++ b/vivified/code/test/compiler/try_no_catch.as.expect
@@ -0,0 +1,13 @@
+asm {
+  pool "try", "finally"
+  try has_finally "" try_finally_0001 try_finally_0001 try_end_0002
+  push pool 0
+  trace
+
+try_finally_0001:
+  push pool 1
+  trace
+
+try_end_0002:
+  end
+}
diff --git a/vivified/code/test/compiler/try_no_finally.as b/vivified/code/test/compiler/try_no_finally.as
new file mode 100644
index 0000000..e84b446
--- /dev/null
+++ b/vivified/code/test/compiler/try_no_finally.as
@@ -0,0 +1,5 @@
+try {
+  trace ("try");
+} catch (e) {
+  trace (e);
+};
diff --git a/vivified/code/test/compiler/try_no_finally.as.expect b/vivified/code/test/compiler/try_no_finally.as.expect
new file mode 100644
index 0000000..d4db888
--- /dev/null
+++ b/vivified/code/test/compiler/try_no_finally.as.expect
@@ -0,0 +1,14 @@
+asm {
+  pool "try", "e"
+  try has_catch "e" try_catch_0001 try_end_0002 try_end_0002
+  push pool 0
+  trace
+
+try_catch_0001:
+  push pool 1
+  get_variable
+  trace
+
+try_end_0002:
+  end
+}
diff --git a/vivified/code/vivi_code_asm_try.c b/vivified/code/vivi_code_asm_try.c
index bc36874..1a29f38 100644
--- a/vivified/code/vivi_code_asm_try.c
+++ b/vivified/code/vivi_code_asm_try.c
@@ -208,7 +208,9 @@ vivi_code_asm_try_print (ViviCodeToken *token, ViviCodePrinter *printer)
     vivi_code_printer_print (printer, str);
     g_free (str);
   } else {
-    vivi_code_printer_print (printer, try_->variable_name);
+    char *str = vivi_code_escape_string (try_->variable_name);
+    vivi_code_printer_print (printer, str);
+    g_free (str);
   }
   vivi_code_printer_print (printer, " ");
 
@@ -272,11 +274,17 @@ vivi_code_asm_try_new_internal (ViviCodeLabel *catch_start,
   g_return_val_if_fail (VIVI_IS_CODE_LABEL (end), NULL);
 
   ret = g_object_new (VIVI_TYPE_CODE_ASM_TRY, NULL);
-  if (catch_start != NULL)
-    ret->catch_start = g_object_ref (catch_start);
-  if (finally_start != NULL)
-    ret->finally_start = g_object_ref (finally_start);
   ret->end = g_object_ref (end);
+  if (finally_start != NULL) {
+    ret->finally_start = g_object_ref (finally_start);
+  } else {
+    ret->finally_start = g_object_ref (ret->end);
+  }
+  if (catch_start != NULL) {
+    ret->catch_start = g_object_ref (catch_start);
+  } else {
+    ret->catch_start = g_object_ref (ret->finally_start);
+  }
 
   ret->has_catch = (catch_start != NULL);
   ret->has_finally = (finally_start != NULL);
commit 20ca16e17e5d92e1d416411ac24ae1659d915a89
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 16:24:39 2008 +0300

    Implement compiling try statements. Clean up disassembling of them

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index f42286e..6473df8 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -90,6 +90,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_text_printer.c \
 	vivi_code_throw.c \
 	vivi_code_token.c \
+	vivi_code_try.c \
 	vivi_code_undefined.c \
 	vivi_code_value.c \
 	vivi_code_variable.c \
@@ -170,6 +171,7 @@ noinst_HEADERS = \
 	vivi_code_text_printer.h \
 	vivi_code_throw.h \
 	vivi_code_token.h \
+	vivi_code_try.h \
 	vivi_code_undefined.h \
 	vivi_code_value.h \
 	vivi_code_variable.h \
diff --git a/vivified/code/vivi_code_asm_try.c b/vivified/code/vivi_code_asm_try.c
index 3782582..bc36874 100644
--- a/vivified/code/vivi_code_asm_try.c
+++ b/vivified/code/vivi_code_asm_try.c
@@ -260,63 +260,79 @@ vivi_code_asm_try_init (ViviCodeAsmTry *try_)
 }
 
 static ViviCodeAsmTry *
-vivi_code_asm_try_new_internal (gboolean has_catch, gboolean has_finally,
-    ViviCodeLabel *catch_start, ViviCodeLabel *finally_start,
-    ViviCodeLabel *end)
+vivi_code_asm_try_new_internal (ViviCodeLabel *catch_start,
+    ViviCodeLabel *finally_start, ViviCodeLabel *end)
 {
   ViviCodeAsmTry *ret;
 
-  g_return_val_if_fail (VIVI_IS_CODE_LABEL (catch_start), NULL);
-  g_return_val_if_fail (VIVI_IS_CODE_LABEL (finally_start), NULL);
+  g_return_val_if_fail (
+      catch_start == NULL || VIVI_IS_CODE_LABEL (catch_start), NULL);
+  g_return_val_if_fail (
+      finally_start == NULL || VIVI_IS_CODE_LABEL (finally_start), NULL);
   g_return_val_if_fail (VIVI_IS_CODE_LABEL (end), NULL);
 
   ret = g_object_new (VIVI_TYPE_CODE_ASM_TRY, NULL);
-  ret->catch_start = g_object_ref (catch_start);
-  ret->finally_start = g_object_ref (finally_start);
+  if (catch_start != NULL)
+    ret->catch_start = g_object_ref (catch_start);
+  if (finally_start != NULL)
+    ret->finally_start = g_object_ref (finally_start);
   ret->end = g_object_ref (end);
 
-  ret->has_catch = has_catch;
-  ret->has_finally = has_finally;
+  ret->has_catch = (catch_start != NULL);
+  ret->has_finally = (finally_start != NULL);
   ret->reserved_flags = 0;
 
   return ret;
 }
 
 ViviCodeAsm *
-vivi_code_asm_try_new_variable (const char *name, gboolean has_catch,
-   gboolean has_finally, ViviCodeLabel *catch_start,
-   ViviCodeLabel *finally_start, ViviCodeLabel *end)
+vivi_code_asm_try_new (ViviCodeLabel *catch_start,
+    ViviCodeLabel *finally_start, ViviCodeLabel *end, const char *name)
 {
   ViviCodeAsmTry *try_;
 
-  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (catch_start == NULL || name != NULL, NULL);
 
-  try_ = vivi_code_asm_try_new_internal (has_catch, has_finally, catch_start,
-      finally_start, end);
+  try_ = vivi_code_asm_try_new_internal (catch_start, finally_start, end);
   try_->use_register = FALSE;
-  try_->variable_name = g_strdup (name);
+  try_->variable_name = g_strdup ((name != NULL ? name : ""));
 
   return VIVI_CODE_ASM (try_);
 }
 
 ViviCodeAsm *
-vivi_code_asm_try_new_register (guint register_number, gboolean has_catch,
-    gboolean has_finally, ViviCodeLabel *catch_start,
-    ViviCodeLabel *finally_start, ViviCodeLabel *end)
+vivi_code_asm_try_new_register (ViviCodeLabel *catch_start,
+    ViviCodeLabel *finally_start, ViviCodeLabel *end, guint id)
 {
   ViviCodeAsmTry *try_;
 
-  g_return_val_if_fail (register_number < 256, NULL);
+  g_return_val_if_fail (id < G_MAXUINT8, NULL);
 
-  try_ = vivi_code_asm_try_new_internal (has_catch, has_finally, catch_start,
-      finally_start, end);
+  try_ = vivi_code_asm_try_new_internal (catch_start, finally_start, end);
   try_->use_register = TRUE;
-  try_->register_number = register_number;
+  try_->register_number = id;
 
   return VIVI_CODE_ASM (try_);
 }
 
 void
+vivi_code_asm_try_set_has_catch (ViviCodeAsmTry *try_, gboolean has_catch)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_TRY (try_));
+
+  try_->has_catch = has_catch;
+}
+
+void
+vivi_code_asm_try_set_has_finally (ViviCodeAsmTry *try_, gboolean has_finally)
+{
+  g_return_if_fail (VIVI_IS_CODE_ASM_TRY (try_));
+
+  try_->has_finally = has_finally;
+}
+
+
+void
 vivi_code_asm_try_set_reserved_flags (ViviCodeAsmTry *try_, guint flags)
 {
   g_return_if_fail (VIVI_IS_CODE_ASM_TRY (try_));
diff --git a/vivified/code/vivi_code_asm_try.h b/vivified/code/vivi_code_asm_try.h
index c40afcf..f725856 100644
--- a/vivified/code/vivi_code_asm_try.h
+++ b/vivified/code/vivi_code_asm_try.h
@@ -60,19 +60,19 @@ struct _ViviCodeAsmTryClass
 
 GType			vivi_code_asm_try_get_type	  	(void);
 
-ViviCodeAsm *		vivi_code_asm_try_new_variable		(const char *		name,
-								 gboolean		has_catch,
-								 gboolean		has_finally,
-								 ViviCodeLabel *	catch_start,
+ViviCodeAsm *		vivi_code_asm_try_new			(ViviCodeLabel *	catch_start,
 								 ViviCodeLabel *	finally_start,
-								 ViviCodeLabel *	end);
-ViviCodeAsm *		vivi_code_asm_try_new_register		(guint			register_number,
-								 gboolean		has_catch,
-								 gboolean		has_finally,
-								 ViviCodeLabel *	catch_start,
+								 ViviCodeLabel *	end,
+								 const char *		name);
+ViviCodeAsm *		vivi_code_asm_try_new_register		(ViviCodeLabel *	catch_start,
 								 ViviCodeLabel *	finally_start,
-								 ViviCodeLabel *	end);
+								 ViviCodeLabel *	end,
+								 guint			id);
 
+void			vivi_code_asm_try_set_has_catch		(ViviCodeAsmTry *	try_,
+								 gboolean		has_catch);
+void			vivi_code_asm_try_set_has_finally	(ViviCodeAsmTry *	try_,
+								 gboolean		has_finally);
 void			vivi_code_asm_try_set_reserved_flags	(ViviCodeAsmTry *	try_,
 								 guint			flags);
 
diff --git a/vivified/code/vivi_code_try.c b/vivified/code/vivi_code_try.c
new file mode 100644
index 0000000..b855ea1
--- /dev/null
+++ b/vivified/code/vivi_code_try.c
@@ -0,0 +1,142 @@
+/* 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_try.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_compiler.h"
+#include "vivi_code_asm.h"
+#include "vivi_code_asm_code_default.h"
+#include "vivi_code_asm_try.h"
+
+G_DEFINE_TYPE (ViviCodeTry, vivi_code_try, VIVI_TYPE_CODE_STATEMENT)
+
+static void
+vivi_code_try_dispose (GObject *object)
+{
+  ViviCodeTry *try_ = VIVI_CODE_TRY (object);
+
+  g_object_unref (try_->try_statement);
+  g_free (try_->catch_name);
+  if (try_->catch_statement)
+    g_object_unref (try_->catch_statement);
+  if (try_->finally_statement)
+    g_object_unref (try_->finally_statement);
+
+  G_OBJECT_CLASS (vivi_code_try_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_try_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  ViviCodeTry *try_ = VIVI_CODE_TRY (token);
+
+  vivi_code_printer_print (printer, "try {");
+  vivi_code_printer_new_line (printer, FALSE);
+  vivi_code_printer_print_token (printer,
+      VIVI_CODE_TOKEN (try_->try_statement));
+
+  if (try_->catch_statement) {
+    vivi_code_printer_print (printer, "} catch (");
+    vivi_code_printer_print (printer, try_->catch_name);
+    vivi_code_printer_print (printer, ") {");
+    vivi_code_printer_new_line (printer, FALSE);
+    vivi_code_printer_print_token (printer,
+	VIVI_CODE_TOKEN (try_->catch_statement));
+  }
+
+  if (try_->finally_statement) {
+    vivi_code_printer_print (printer, "} finally {");
+    vivi_code_printer_new_line (printer, FALSE);
+    vivi_code_printer_print_token (printer,
+	VIVI_CODE_TOKEN (try_->finally_statement));
+  }
+
+  vivi_code_printer_print (printer, "};");
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_code_try_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
+{
+  ViviCodeTry *try_ = VIVI_CODE_TRY (token);
+  ViviCodeLabel *label_catch, *label_finally, *label_end;
+
+  if (try_->catch_statement) {
+    label_catch = vivi_code_compiler_create_label (compiler, "try_catch");
+  } else {
+    label_catch = NULL;
+  }
+  if (try_->finally_statement) {
+    label_finally = vivi_code_compiler_create_label (compiler, "try_finally");
+  } else {
+    label_finally = NULL;
+  }
+  label_end = vivi_code_compiler_create_label (compiler, "try_end");
+
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_try_new (label_catch,
+	label_finally, label_end, try_->catch_name));
+
+  vivi_code_compiler_compile_statement (compiler, try_->try_statement);
+  if (try_->catch_statement) {
+    vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_catch));
+    vivi_code_compiler_compile_statement (compiler, try_->catch_statement);
+  }
+  if (try_->finally_statement) {
+    vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_finally));
+    vivi_code_compiler_compile_statement (compiler, try_->finally_statement);
+  }
+  vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
+}
+
+static void
+vivi_code_try_class_init (ViviCodeTryClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+
+  object_class->dispose = vivi_code_try_dispose;
+
+  token_class->print = vivi_code_try_print;
+  token_class->compile = vivi_code_try_compile;
+}
+
+static void
+vivi_code_try_init (ViviCodeTry *token)
+{
+}
+
+ViviCodeStatement *
+vivi_code_try_new (ViviCodeStatement *try_statement, const char *catch_name,
+    ViviCodeStatement *catch_statement, ViviCodeStatement *finally_statement)
+{
+  ViviCodeTry *try_ = g_object_new (VIVI_TYPE_CODE_TRY, NULL);
+
+  try_->try_statement = g_object_ref (try_statement);
+  try_->catch_name = g_strdup (catch_name);
+  if (catch_statement)
+    try_->catch_statement = g_object_ref (catch_statement);
+  if (finally_statement)
+    try_->finally_statement = g_object_ref (finally_statement);
+
+  return VIVI_CODE_STATEMENT (try_);
+}
diff --git a/vivified/code/vivi_code_try.h b/vivified/code/vivi_code_try.h
new file mode 100644
index 0000000..1f7a2e9
--- /dev/null
+++ b/vivified/code/vivi_code_try.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_TRY_H_
+#define _VIVI_CODE_TRY_H_
+
+#include <vivified/code/vivi_code_statement.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeTry ViviCodeTry;
+typedef struct _ViviCodeTryClass ViviCodeTryClass;
+
+#define VIVI_TYPE_CODE_TRY                    (vivi_code_try_get_type())
+#define VIVI_IS_CODE_TRY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_TRY))
+#define VIVI_IS_CODE_TRY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_TRY))
+#define VIVI_CODE_TRY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_TRY, ViviCodeTry))
+#define VIVI_CODE_TRY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_TRY, ViviCodeTryClass))
+#define VIVI_CODE_TRY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_TRY, ViviCodeTryClass))
+
+struct _ViviCodeTry
+{
+  ViviCodeStatement		statement;
+
+  ViviCodeStatement *		try_statement;
+  char *			catch_name;
+  ViviCodeStatement *		catch_statement;
+  ViviCodeStatement *		finally_statement;
+};
+
+struct _ViviCodeTryClass
+{
+  ViviCodeStatementClass	statement_class;
+};
+
+GType			vivi_code_try_get_type		(void);
+
+ViviCodeStatement *	vivi_code_try_new		(ViviCodeStatement *		try_statement,
+							 const char *			catch_name,
+							 ViviCodeStatement *		catch_statement,
+							 ViviCodeStatement *		finally_statement);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_disassembler.c b/vivified/code/vivi_disassembler.c
index 65d8212..34aedc5 100644
--- a/vivified/code/vivi_disassembler.c
+++ b/vivified/code/vivi_disassembler.c
@@ -56,6 +56,94 @@ static ViviCodeAsm * (* simple_commands[0x80]) (void) = {
 #include "vivi_code_defaults.h"
 };
 
+typedef GArray ViviDisassembleLabels;
+typedef struct {
+  const guint8 *	bytecode;
+  ViviCodeLabel *	label;
+} ViviLabelEntry;
+
+static ViviDisassembleLabels *
+vivi_disassemble_labels_new (void)
+{
+  return g_array_new (FALSE, FALSE, sizeof (ViviLabelEntry));
+}
+
+static ViviCodeLabel *
+vivi_disassemble_labels_get_label (ViviDisassembleLabels *labels, const guint8 *bytecode)
+{
+  ViviLabelEntry ins;
+  guint i;
+  char *s;
+
+  for (i = 0; i < labels->len; i++) {
+    ViviLabelEntry *entry = &g_array_index (labels, ViviLabelEntry, i);
+    if (entry->bytecode < bytecode)
+      continue;
+    if (entry->bytecode == bytecode)
+      return entry->label;
+    break;
+  }
+  s = g_strdup_printf ("label_%p", bytecode);
+  ins.bytecode = bytecode;
+  ins.label = VIVI_CODE_LABEL (vivi_code_label_new (s));
+  g_free (s);
+  g_array_insert_val (labels, i, ins);
+  return ins.label;
+}
+
+static void
+vivi_disassemble_labels_resolve (ViviDisassembleLabels *labels,
+    ViviCodeAssembler *assembler, SwfdecScript *script)
+{
+  guint li, ai;
+  const guint8 *pc, *end;
+
+  if (labels->len == 0)
+    return;
+
+  ai = li = 0;
+  pc = script->main;
+  end = script->buffer->data + script->buffer->length;
+  while (pc < end) {
+    ViviLabelEntry *entry = &g_array_index (labels, ViviLabelEntry, li);
+
+    if (entry->bytecode < pc) {
+      char *s = g_strdup_printf ("broken jump: goes to %p, but next bytecode is %p",
+	  entry->bytecode, pc);
+      ViviCodeStatement *comment = vivi_code_comment_new (s);
+      vivi_code_assembler_insert_code (assembler, ai, VIVI_CODE_ASM (comment));
+      ai++;
+      g_object_unref (comment);
+      g_free (s);
+    }
+    if (entry->bytecode <= pc) {
+      vivi_code_assembler_insert_code (assembler, ai, VIVI_CODE_ASM (entry->label));
+      ai++;
+      li++;
+      if (li >= labels->len)
+	break;
+      continue;
+    }
+    if (pc[0] & 0x80) {
+      pc += 3 + (pc[1] | pc[2] << 8);
+    } else {
+      pc++;
+    }
+    ai++;
+  }
+}
+
+static void
+vivi_disassemble_labels_free (ViviDisassembleLabels *labels)
+{
+  guint i;
+
+  for (i = 0; i < labels->len; i++) {
+    g_object_unref (g_array_index (labels, ViviLabelEntry, i).label);
+  }
+  g_array_free (labels, TRUE);
+}
+
 static void
 vivi_disassemble_get_url (ViviCodeAssembler *assembler, SwfdecBits *bits, guint version)
 {
@@ -172,92 +260,59 @@ fail:
   g_object_unref (push);
 }
 
-typedef GArray ViviDisassembleLabels;
-typedef struct {
-  const guint8 *	bytecode;
-  ViviCodeLabel *	label;
-} ViviLabelEntry;
-
-static ViviDisassembleLabels *
-vivi_disassemble_labels_new (void)
-{
-  return g_array_new (FALSE, FALSE, sizeof (ViviLabelEntry));
-}
-
-static ViviCodeLabel *
-vivi_disassemble_labels_get_label (ViviDisassembleLabels *labels, const guint8 *bytecode)
-{
-  ViviLabelEntry ins;
-  guint i;
-  char *s;
-
-  for (i = 0; i < labels->len; i++) {
-    ViviLabelEntry *entry = &g_array_index (labels, ViviLabelEntry, i);
-    if (entry->bytecode < bytecode)
-      continue;
-    if (entry->bytecode == bytecode)
-      return entry->label;
-    break;
-  }
-  s = g_strdup_printf ("label_%p", bytecode);
-  ins.bytecode = bytecode;
-  ins.label = VIVI_CODE_LABEL (vivi_code_label_new (s));
-  g_free (s);
-  g_array_insert_val (labels, i, ins);
-  return ins.label;
-}
-
 static void
-vivi_disassemble_labels_resolve (ViviDisassembleLabels *labels,
-    ViviCodeAssembler *assembler, SwfdecScript *script)
+vivi_disassemble_try (ViviCodeAssembler *assembler, SwfdecBits *bits,
+    guint version, ViviDisassembleLabels *labels, const guint8 *pc)
 {
-  guint li, ai;
-  const guint8 *pc, *end;
+  gboolean has_catch, has_finally, use_register;
+  guint flags, try_size, catch_size, finally_size, register_number;
+  char *name;
+  ViviCodeLabel *catch_start, *finally_start, *end_label;
+  ViviCodeAsm *try;
 
-  if (labels->len == 0)
-    return;
-
-  ai = li = 0;
-  pc = script->main;
-  end = script->buffer->data + script->buffer->length;
-  while (pc < end) {
-    ViviLabelEntry *entry = &g_array_index (labels, ViviLabelEntry, li);
+  flags = swfdec_bits_get_u8 (bits);
 
-    if (entry->bytecode < pc) {
-      char *s = g_strdup_printf ("broken jump: goes to %p, but next bytecode is %p",
-	  entry->bytecode, pc);
-      ViviCodeStatement *comment = vivi_code_comment_new (s);
-      vivi_code_assembler_insert_code (assembler, ai, VIVI_CODE_ASM (comment));
-      ai++;
-      g_object_unref (comment);
-      g_free (s);
-    }
-    if (entry->bytecode <= pc) {
-      vivi_code_assembler_insert_code (assembler, ai, VIVI_CODE_ASM (entry->label));
-      ai++;
-      li++;
-      if (li >= labels->len)
-	break;
-      continue;
-    }
-    if (pc[0] & 0x80) {
-      pc += 3 + (pc[1] | pc[2] << 8);
-    } else {
-      pc++;
-    }
-    ai++;
+  has_catch = flags & (1 << 0);
+  has_finally = flags & (1 << 1);
+  use_register = flags & (1 << 2);
+
+  try_size = swfdec_bits_get_u16 (bits);
+  catch_size = swfdec_bits_get_u16 (bits);
+  finally_size = swfdec_bits_get_u16 (bits);
+  if (use_register) {
+    register_number = swfdec_bits_get_u8 (bits);
+    name = NULL; // shut up compiler warnings
+  } else {
+    register_number = 0;
+    name = swfdec_bits_get_string (bits, version);
   }
-}
 
-static void
-vivi_disassemble_labels_free (ViviDisassembleLabels *labels)
-{
-  guint i;
+  end_label = vivi_disassemble_labels_get_label (labels,
+      pc + try_size + catch_size + finally_size);
+  if (finally_size > 0) {
+    finally_start = vivi_disassemble_labels_get_label (labels,
+	pc + try_size + catch_size);
+  } else {
+    finally_start = end_label;
+  }
+  if (catch_size > 0) {
+    catch_start = vivi_disassemble_labels_get_label (labels,
+	pc + try_size);
+  } else {
+    catch_start = finally_start;
+  }
 
-  for (i = 0; i < labels->len; i++) {
-    g_object_unref (g_array_index (labels, ViviLabelEntry, i).label);
+  if (use_register) {
+    try = vivi_code_asm_try_new_register (catch_start, finally_start,
+	end_label, register_number);
+  } else {
+    try = vivi_code_asm_try_new (catch_start, finally_start, end_label, name);
+    g_free (name);
   }
-  g_array_free (labels, TRUE);
+  vivi_code_asm_try_set_has_catch (VIVI_CODE_ASM_TRY (try), has_catch);
+  vivi_code_asm_try_set_has_finally (VIVI_CODE_ASM_TRY (try), has_finally);
+  vivi_code_asm_try_set_reserved_flags (VIVI_CODE_ASM_TRY (try), flags >> 3);
+  vivi_code_assembler_add_code (assembler, try);
 }
 
 ViviCodeStatement *
@@ -394,58 +449,7 @@ vivi_disassemble_script (SwfdecScript *script)
 	  }
 	  break;
         case SWFDEC_AS_ACTION_TRY:
-	  {
-	    gboolean has_catch, has_finally, use_register;
-	    guint flags, try_size, catch_size, finally_size, register_number;
-	    char *name;
-	    ViviCodeLabel *catch_start, *finally_start, *end_label;
-	    ViviCodeAsm *try;
-
-	    flags = swfdec_bits_get_u8 (&bits);
-
-	    has_catch = flags & (1 << 0);
-	    has_finally = flags & (1 << 1);
-	    use_register = flags & (1 << 2);
-
-	    try_size = swfdec_bits_get_u16 (&bits);
-	    catch_size = swfdec_bits_get_u16 (&bits);
-	    finally_size = swfdec_bits_get_u16 (&bits);
-	    if (use_register) {
-	      register_number = swfdec_bits_get_u8 (&bits);
-	      name = NULL; // shut up compiler warnings
-	    } else {
-	      register_number = 0;
-	      name = swfdec_bits_get_string (&bits, script->version);
-	    }
-
-	    end_label = vivi_disassemble_labels_get_label (labels,
-		pc + try_size + catch_size + finally_size);
-	    if (finally_size > 0) {
-	      finally_start = vivi_disassemble_labels_get_label (labels,
-		  pc + try_size + catch_size);
-	    } else {
-	      finally_start = end_label;
-	    }
-	    if (catch_size > 0) {
-	      catch_start = vivi_disassemble_labels_get_label (labels,
-		  pc + try_size);
-	    } else {
-	      catch_start = finally_start;
-	    }
-
-	    if (use_register) {
-	      try = vivi_code_asm_try_new_register (register_number,
-		  has_catch, has_finally, catch_start, finally_start,
-		  end_label);
-	    } else {
-	      try = vivi_code_asm_try_new_variable (name, has_catch,
-		  has_finally, catch_start, finally_start, end_label);
-	      g_free (name);
-	    }
-	    vivi_code_asm_try_set_reserved_flags (VIVI_CODE_ASM_TRY (try),
-		flags >> 3);
-	    vivi_code_assembler_add_code (assembler, try);
-	  }
+	  vivi_disassemble_try (assembler, &bits, script->version, labels, pc);
 	  break;
         case SWFDEC_AS_ACTION_GET_URL:
 	  vivi_disassemble_get_url (assembler, &bits, script->version);
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index b38e4ee..689be01 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -65,6 +65,7 @@
 #include "vivi_code_string.h"
 #include "vivi_code_substring.h"
 #include "vivi_code_throw.h"
+#include "vivi_code_try.h"
 #include "vivi_code_not.h"
 #include "vivi_code_undefined.h"
 #include "vivi_code_variable.h"
@@ -2440,6 +2441,59 @@ parse_throw_statement (ParseData *data)
   return statement;
 }
 
+static ViviCodeStatement *parse_block (ParseData *data);
+
+static gboolean
+peek_try_statement (ParseData *data)
+{
+  return peek_token (data, TOKEN_TRY);
+}
+
+static ViviCodeStatement *
+parse_try_statement (ParseData *data)
+{
+  ViviCodeStatement *statement;
+  ViviCodeStatement *try_statement, *catch_statement, *finally_statement;
+  char *catch_identifier;
+
+  parse_token (data, TOKEN_TRY);
+
+  try_statement = parse_block (data);
+
+  if (try_parse_token (data, TOKEN_CATCH)) {
+    parse_token (data, TOKEN_PARENTHESIS_LEFT);
+    catch_identifier = g_strdup (parse_identifier_value (data));
+    parse_token (data, TOKEN_PARENTHESIS_RIGHT);
+    catch_statement = parse_block (data);
+  } else {
+    catch_identifier = NULL;
+    catch_statement = NULL;
+  }
+
+  if (try_parse_token (data, TOKEN_FINALLY)) {
+    finally_statement = parse_block (data);
+  } else {
+    finally_statement = NULL;
+  }
+
+  if (catch_statement == NULL && finally_statement == NULL) {
+    vivi_parser_error_unexpected_or (data, TOKEN_CATCH, TOKEN_FINALLY,
+	TOKEN_NONE);
+    finally_statement = vivi_code_block_new ();
+  }
+
+  statement = vivi_code_try_new (try_statement, catch_identifier,
+      catch_statement, finally_statement);
+  g_object_unref (try_statement);
+  g_free (catch_identifier);
+  if (catch_statement != NULL)
+    g_object_unref (catch_statement);
+  if (finally_statement != NULL)
+    g_object_unref (finally_statement);
+
+  return statement;
+}
+
 static gboolean
 peek_return_statement (ParseData *data)
 {
@@ -2840,7 +2894,7 @@ static const struct {
   //{ peek_with_statement, parse_with_statement },
   //{ peek_switch_statement, parse_switch_statement },
   { peek_throw_statement, parse_throw_statement },
-  //{ peek_try_statement, parse_try_statement },
+  { peek_try_statement, parse_try_statement },
   { NULL, NULL }
 };
 
commit 2cc7d1a4d95b2d473499a91642b6707de29e4b49
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 14:23:09 2008 +0300

    Add tests for compiling break and continue

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 86450aa..dcd94cf 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -48,6 +48,8 @@ EXTRA_DIST = \
 	bitwise_not.as.expect \
 	builtin_statement.as \
 	builtin_statement.as.expect \
+	break.as \
+	break.as.expect \
 	break_continue_label.as \
 	break_continue_label.as.expect \
 	call_function.as \
@@ -58,6 +60,8 @@ EXTRA_DIST = \
 	comment.as.expect \
 	conditional.as \
 	conditional.as.expect \
+	continue.as \
+	continue.as.expect \
 	decrement.as \
 	decrement.as.expect \
 	do_while.as \
diff --git a/vivified/code/test/compiler/break.as b/vivified/code/test/compiler/break.as
new file mode 100644
index 0000000..4651481
--- /dev/null
+++ b/vivified/code/test/compiler/break.as
@@ -0,0 +1,15 @@
+while (a) {
+  if (b) {
+    break;
+  } else {
+    break;
+  }
+}
+
+do {
+  if (b) {
+    break;
+  } else {
+    break;
+  }
+} while (a);
diff --git a/vivified/code/test/compiler/break.as.expect b/vivified/code/test/compiler/break.as.expect
new file mode 100644
index 0000000..9cd3518
--- /dev/null
+++ b/vivified/code/test/compiler/break.as.expect
@@ -0,0 +1,40 @@
+asm {
+  pool "a", "b"
+
+loop_start_0001:
+  push pool 0
+  get_variable
+  not
+  if loop_end_0002
+  push pool 1
+  get_variable
+  if if_true_0003
+  jump loop_end_0002
+  jump if_end_0004
+
+if_true_0003:
+  jump loop_end_0002
+
+if_end_0004:
+  jump loop_start_0001
+
+loop_end_0002:
+
+loop_start_0005:
+  push pool 1
+  get_variable
+  if if_true_0007
+  jump loop_end_0006
+  jump if_end_0008
+
+if_true_0007:
+  jump loop_end_0006
+
+if_end_0008:
+  push pool 0
+  get_variable
+  if loop_start_0005
+
+loop_end_0006:
+  end
+}
diff --git a/vivified/code/test/compiler/continue.as b/vivified/code/test/compiler/continue.as
new file mode 100644
index 0000000..12908c9
--- /dev/null
+++ b/vivified/code/test/compiler/continue.as
@@ -0,0 +1,15 @@
+while (a) {
+  if (b) {
+    continue;
+  } else {
+    continue;
+  }
+}
+
+do {
+  if (b) {
+    continue;
+  } else {
+    continue;
+  }
+} while (a);
diff --git a/vivified/code/test/compiler/continue.as.expect b/vivified/code/test/compiler/continue.as.expect
new file mode 100644
index 0000000..fa2d054
--- /dev/null
+++ b/vivified/code/test/compiler/continue.as.expect
@@ -0,0 +1,38 @@
+asm {
+  pool "a", "b"
+
+loop_start_0001:
+  push pool 0
+  get_variable
+  not
+  if loop_end_0002
+  push pool 1
+  get_variable
+  if if_true_0003
+  jump loop_start_0001
+  jump if_end_0004
+
+if_true_0003:
+  jump loop_start_0001
+
+if_end_0004:
+  jump loop_start_0001
+
+loop_end_0002:
+
+loop_start_0005:
+  push pool 1
+  get_variable
+  if if_true_0007
+  jump loop_start_0005
+  jump if_end_0008
+
+if_true_0007:
+  jump loop_start_0005
+
+if_end_0008:
+  push pool 0
+  get_variable
+  if loop_start_0005
+  end
+}
commit 95c71e785316038db4b5dae99c81f9714f119aeb
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 14:22:14 2008 +0300

    Implement the compiling of break and continue statements

diff --git a/vivified/code/vivi_code_break.c b/vivified/code/vivi_code_break.c
index 9286fa5..c28da1a 100644
--- a/vivified/code/vivi_code_break.c
+++ b/vivified/code/vivi_code_break.c
@@ -24,6 +24,7 @@
 #include "vivi_code_break.h"
 #include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
+#include "vivi_code_asm_jump.h"
 
 G_DEFINE_TYPE (ViviCodeBreak, vivi_code_break, VIVI_TYPE_CODE_STATEMENT)
 
@@ -37,7 +38,12 @@ vivi_code_break_print (ViviCodeToken *token, ViviCodePrinter *printer)
 static void
 vivi_code_break_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
-  g_printerr ("Implement break\n");
+  ViviCodeLabel *label;
+
+  label = vivi_code_compiler_use_break_label (compiler);
+  g_return_if_fail (label != NULL); // FIXME
+
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_jump_new (label));
 }
 
 static void
diff --git a/vivified/code/vivi_code_compiler.c b/vivified/code/vivi_code_compiler.c
index 343992a..7a5c91e 100644
--- a/vivified/code/vivi_code_compiler.c
+++ b/vivified/code/vivi_code_compiler.c
@@ -31,6 +31,8 @@ vivi_code_compiler_dispose (GObject *object)
 {
   ViviCodeCompiler *compiler = VIVI_CODE_COMPILER (object);
 
+  g_assert (compiler->loop_labels == NULL);
+
   g_object_unref (compiler->assembler);
 
   G_OBJECT_CLASS (vivi_code_compiler_parent_class)->dispose (object);
@@ -126,6 +128,87 @@ vivi_code_compiler_create_label (ViviCodeCompiler *compiler,
   return label;
 }
 
+typedef struct {
+  ViviCodeLabel *	continue_label;
+  ViviCodeLabel *	break_label;
+  guint			continue_used;
+  guint			break_used;
+} LoopLabels;
+
+void
+vivi_code_compiler_push_loop_labels (ViviCodeCompiler *compiler,
+    ViviCodeLabel *continue_label, ViviCodeLabel *break_label)
+{
+  LoopLabels *labels;
+
+  g_return_if_fail (VIVI_IS_CODE_COMPILER (compiler));
+  g_return_if_fail (continue_label == NULL ||
+      VIVI_IS_CODE_LABEL (continue_label));
+  g_return_if_fail (break_label == NULL || VIVI_IS_CODE_LABEL (break_label));
+
+  if (continue_label != NULL)
+      g_object_ref (continue_label);
+  if (break_label != NULL)
+      g_object_ref (break_label);
+
+  labels = g_new0 (LoopLabels, 1);
+  labels->continue_label = continue_label;
+  labels->break_label = break_label;
+
+  compiler->loop_labels = g_slist_prepend (compiler->loop_labels, labels);
+}
+
+void
+vivi_code_compiler_pop_loop_labels (ViviCodeCompiler *compiler,
+    guint *continue_used, guint *break_used)
+{
+  LoopLabels *labels;
+
+  g_return_if_fail (VIVI_IS_CODE_COMPILER (compiler));
+  g_return_if_fail (compiler->loop_labels != NULL);
+
+  labels = compiler->loop_labels->data;
+
+  if (continue_used != NULL)
+    *continue_used = labels->continue_used;
+  if (break_used != NULL)
+    *break_used = labels->break_used;
+
+  if (labels->continue_label != NULL)
+    g_object_unref (labels->continue_label);
+  if (labels->break_label != NULL)
+    g_object_unref (labels->break_label);
+
+  compiler->loop_labels =
+    g_slist_delete_link (compiler->loop_labels, compiler->loop_labels);
+}
+
+ViviCodeLabel *
+vivi_code_compiler_use_continue_label (ViviCodeCompiler *compiler)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_COMPILER (compiler), NULL);
+
+  if (compiler->loop_labels == NULL)
+    return NULL;
+
+  ((LoopLabels *)compiler->loop_labels->data)->continue_used++;
+  return VIVI_CODE_LABEL (
+      ((LoopLabels *)compiler->loop_labels->data)->continue_label);
+}
+
+ViviCodeLabel *
+vivi_code_compiler_use_break_label (ViviCodeCompiler *compiler)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_COMPILER (compiler), NULL);
+
+  if (compiler->loop_labels == NULL)
+    return NULL;
+
+  ((LoopLabels *)compiler->loop_labels->data)->break_used++;
+  return VIVI_CODE_LABEL (
+      ((LoopLabels *)compiler->loop_labels->data)->break_label);
+}
+
 ViviCodeCompiler *
 vivi_code_compiler_new (guint version)
 {
diff --git a/vivified/code/vivi_code_compiler.h b/vivified/code/vivi_code_compiler.h
index 5215425..a8f6562 100644
--- a/vivified/code/vivi_code_compiler.h
+++ b/vivified/code/vivi_code_compiler.h
@@ -46,6 +46,8 @@ struct _ViviCodeCompiler
   ViviCodeAssembler *	assembler;
 
   guint			num_labels;
+
+  GSList *		loop_labels;
 };
 
 struct _ViviCodeCompilerClass
@@ -75,5 +77,14 @@ guint			vivi_code_compiler_get_version		(ViviCodeCompiler *	compiler);
 ViviCodeLabel *		vivi_code_compiler_create_label		(ViviCodeCompiler *	compiler,
 								 const char *		prefix);
 
+void			vivi_code_compiler_push_loop_labels	(ViviCodeCompiler *	compiler,
+								 ViviCodeLabel *	continue_label,
+								 ViviCodeLabel *	break_label);
+void			vivi_code_compiler_pop_loop_labels	(ViviCodeCompiler *	compiler,
+								 guint *		continue_used,
+								 guint *		break_used);
+ViviCodeLabel *		vivi_code_compiler_use_break_label	(ViviCodeCompiler *	compiler);
+ViviCodeLabel *		vivi_code_compiler_use_continue_label	(ViviCodeCompiler *	compiler);
+
 G_END_DECLS
 #endif
diff --git a/vivified/code/vivi_code_continue.c b/vivified/code/vivi_code_continue.c
index cb6ab77..ea65fad 100644
--- a/vivified/code/vivi_code_continue.c
+++ b/vivified/code/vivi_code_continue.c
@@ -24,6 +24,7 @@
 #include "vivi_code_continue.h"
 #include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
+#include "vivi_code_asm_jump.h"
 
 G_DEFINE_TYPE (ViviCodeContinue, vivi_code_continue, VIVI_TYPE_CODE_STATEMENT)
 
@@ -37,7 +38,12 @@ vivi_code_continue_print (ViviCodeToken *token, ViviCodePrinter *printer)
 static void
 vivi_code_continue_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
-  g_printerr ("Implement continue\n");
+  ViviCodeLabel *label;
+
+  label = vivi_code_compiler_use_continue_label (compiler);
+  g_return_if_fail (label != NULL); // FIXME
+
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_jump_new (label));
 }
 
 static void
diff --git a/vivified/code/vivi_code_loop.c b/vivified/code/vivi_code_loop.c
index 134d491..9b27a60 100644
--- a/vivified/code/vivi_code_loop.c
+++ b/vivified/code/vivi_code_loop.c
@@ -80,8 +80,12 @@ vivi_code_loop_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
   ViviCodeLoop *loop = VIVI_CODE_LOOP (token);
   ViviCodeLabel *label_start, *label_end = NULL;
+  guint break_used;
 
   label_start = vivi_code_compiler_create_label (compiler, "loop_start");
+  label_end = vivi_code_compiler_create_label (compiler, "loop_end");
+  vivi_code_compiler_push_loop_labels (compiler, label_start, label_end);
+
   vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_start));
 
   if (loop->post_condition && loop->statement)
@@ -92,7 +96,6 @@ vivi_code_loop_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 
     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));
     }
@@ -110,8 +113,11 @@ vivi_code_loop_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   }
   g_object_unref (label_start);
 
-  if (loop->condition && !loop->post_condition)
-    vivi_code_compiler_take_code (compiler, VIVI_CODE_ASM (label_end));
+  vivi_code_compiler_pop_loop_labels (compiler, NULL, &break_used);
+
+  if ((loop->condition && !loop->post_condition) || break_used > 0)
+    vivi_code_compiler_add_code (compiler, VIVI_CODE_ASM (label_end));
+  g_object_unref (label_end);
 }
 
 static void
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 263ea54..b38e4ee 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -109,6 +109,7 @@ static const struct {
 typedef struct {
   GSList			*labels;
   GSList			*waiting_labels;
+  guint				loop_count;
 } ParseLevel;
 
 typedef struct {
@@ -2369,8 +2370,16 @@ parse_continue_or_break_statement (ParseData *data,
 
     parse_automatic_semicolon (data);
   } else {
-    // FIXME
-    statement = vivi_code_break_new ();
+    g_assert (data->level != NULL);
+    if (data->level->loop_count == 0) {
+      vivi_parser_error (data,
+	  "Break or continue without label outside of loop");
+    }
+    if (token == TOKEN_CONTINUE) {
+      statement = vivi_code_continue_new ();
+    } else {
+      statement = vivi_code_break_new ();
+    }
   }
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (statement));
@@ -2485,6 +2494,9 @@ parse_iteration_statement (ParseData *data)
   enumerate_local = FALSE;
   enumerate_variable = NULL;
 
+  g_assert (data->level != NULL);
+  data->level->loop_count++;
+
   if (try_parse_token (data, TOKEN_DO))
   {
     loop_statement = parse_statement (data);
@@ -2649,6 +2661,8 @@ parse_iteration_statement (ParseData *data)
     statement = block;
   }
 
+  data->level->loop_count--;
+
   return statement;
 }
 
commit 6ac5e6430f14ba8932c1c07eae2c9294ad5d9593
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 13:13:41 2008 +0300

    Implement the compiling of unary bitwise not operator. Add a test

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 24706ae..f42286e 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -45,6 +45,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_assignment.c \
 	vivi_code_binary.c \
 	vivi_code_binary_default.c \
+	vivi_code_bit_not.c \
 	vivi_code_block.c \
 	vivi_code_boolean.c \
 	vivi_code_break.c \
@@ -123,6 +124,7 @@ noinst_HEADERS = \
 	vivi_code_assignment.h \
 	vivi_code_binary.h \
 	vivi_code_binary_default.h \
+	vivi_code_bit_not.h \
 	vivi_code_block.h \
 	vivi_code_boolean.h \
 	vivi_code_break.h \
diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 3cfc032..86450aa 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -44,6 +44,8 @@ EXTRA_DIST = \
 	assignment_value.as.expect \
 	automatic_semicolon.as \
 	automatic_semicolon.as.expect \
+	bitwise_not.as \
+	bitwise_not.as.expect \
 	builtin_statement.as \
 	builtin_statement.as.expect \
 	break_continue_label.as \
diff --git a/vivified/code/test/compiler/bitwise_not.as b/vivified/code/test/compiler/bitwise_not.as
new file mode 100644
index 0000000..e405d5b
--- /dev/null
+++ b/vivified/code/test/compiler/bitwise_not.as
@@ -0,0 +1 @@
+trace (~a);
diff --git a/vivified/code/test/compiler/bitwise_not.as.expect b/vivified/code/test/compiler/bitwise_not.as.expect
new file mode 100644
index 0000000..0b2be3b
--- /dev/null
+++ b/vivified/code/test/compiler/bitwise_not.as.expect
@@ -0,0 +1,9 @@
+asm {
+  pool "a"
+  push pool 0
+  get_variable
+  push -1
+  bit_xor
+  trace
+  end
+}
diff --git a/vivified/code/vivi_code_bit_not.c b/vivified/code/vivi_code_bit_not.c
new file mode 100644
index 0000000..92a8d04
--- /dev/null
+++ b/vivified/code/vivi_code_bit_not.c
@@ -0,0 +1,104 @@
+/* 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 bit_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_bit_not.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_compiler.h"
+#include "vivi_code_asm.h"
+#include "vivi_code_asm_code_default.h"
+#include "vivi_code_asm_push.h"
+
+G_DEFINE_TYPE (ViviCodeBitNot, vivi_code_bit_not, VIVI_TYPE_CODE_VALUE)
+
+static void
+vivi_code_bit_not_dispose (GObject *object)
+{
+  ViviCodeBitNot *bit_not = VIVI_CODE_BIT_NOT (object);
+
+  g_object_unref (bit_not->value);
+
+  G_OBJECT_CLASS (vivi_code_bit_not_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_bit_not_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
+{
+  ViviCodeBitNot *bit_not = VIVI_CODE_BIT_NOT (value);
+
+  vivi_code_printer_print (printer, "~");
+  vivi_code_printer_print_value (printer, bit_not->value, VIVI_PRECEDENCE_UNARY);
+}
+
+static void
+vivi_code_bit_not_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
+{
+  ViviCodeBitNot *bit_not = VIVI_CODE_BIT_NOT (value);
+  ViviCodeAsm *push;
+
+  vivi_code_compiler_compile_value (compiler, bit_not->value);
+  push = vivi_code_asm_push_new ();
+  vivi_code_asm_push_add_integer (VIVI_CODE_ASM_PUSH (push), -1);
+  vivi_code_compiler_take_code (compiler, push);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_bit_xor_new ());
+}
+
+static void
+vivi_code_bit_not_class_init (ViviCodeBitNotClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
+
+  object_class->dispose = vivi_code_bit_not_dispose;
+
+  value_class->print_value = vivi_code_bit_not_print_value;
+  value_class->compile_value = vivi_code_bit_not_compile_value;
+}
+
+static void
+vivi_code_bit_not_init (ViviCodeBitNot *bit_not)
+{
+  ViviCodeValue *value = VIVI_CODE_VALUE (bit_not);
+
+  vivi_code_value_set_precedence (value, VIVI_PRECEDENCE_UNARY);
+}
+
+ViviCodeValue *
+vivi_code_bit_not_new (ViviCodeValue *value)
+{
+  ViviCodeBitNot *bit_not;
+
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
+
+  bit_not = g_object_new (VIVI_TYPE_CODE_BIT_NOT, NULL);
+  bit_not->value = g_object_ref (value);
+
+  return VIVI_CODE_VALUE (bit_not);
+}
+
+ViviCodeValue *
+vivi_code_bit_not_get_value (ViviCodeBitNot *bit_not)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_BIT_NOT (bit_not), NULL);
+
+  return bit_not->value;
+}
diff --git a/vivified/code/vivi_code_bit_not.h b/vivified/code/vivi_code_bit_not.h
new file mode 100644
index 0000000..a1625fe
--- /dev/null
+++ b/vivified/code/vivi_code_bit_not.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 bit_not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_CODE_BIT_NOT_H_
+#define _VIVI_CODE_BIT_NOT_H_
+
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeBitNot ViviCodeBitNot;
+typedef struct _ViviCodeBitNotClass ViviCodeBitNotClass;
+
+#define VIVI_TYPE_CODE_BIT_NOT                    (vivi_code_bit_not_get_type())
+#define VIVI_IS_CODE_BIT_NOT(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_BIT_NOT))
+#define VIVI_IS_CODE_BIT_NOT_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_BIT_NOT))
+#define VIVI_CODE_BIT_NOT(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_BIT_NOT, ViviCodeBitNot))
+#define VIVI_CODE_BIT_NOT_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_BIT_NOT, ViviCodeBitNotClass))
+#define VIVI_CODE_BIT_NOT_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_BIT_NOT, ViviCodeBitNotClass))
+
+struct _ViviCodeBitNot
+{
+  ViviCodeValue		parent;
+
+  ViviCodeValue *	value;
+};
+
+struct _ViviCodeBitNotClass
+{
+  ViviCodeValueClass	value_class;
+};
+
+GType			vivi_code_bit_not_get_type	(void);
+
+ViviCodeValue *		vivi_code_bit_not_new		(ViviCodeValue *	value);
+
+ViviCodeValue *		vivi_code_bit_not_get_value	(ViviCodeBitNot *		bit_not);
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 28239d6..263ea54 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -34,6 +34,7 @@
 #include "vivi_code_asm_store.h"
 #include "vivi_code_assignment.h"
 #include "vivi_code_binary_default.h"
+#include "vivi_code_bit_not.h"
 #include "vivi_code_block.h"
 #include "vivi_code_boolean.h"
 #include "vivi_code_break.h"
@@ -1847,13 +1848,13 @@ peek_unary_expression (ParseData *data)
 {
   switch ((guint) vivi_parser_scanner_peek_next_token (data->scanner)) {
     //case TOKEN_DELETE:
-    case TOKEN_VOID:
     //case TOKEN_TYPEOF:
     case TOKEN_INCREASE:
     case TOKEN_DESCREASE:
     case TOKEN_PLUS:
     case TOKEN_MINUS:
-    //case TOKEN_BITWISE_NOT:
+    case TOKEN_VOID:
+    case TOKEN_BITWISE_NOT:
     case TOKEN_LOGICAL_NOT:
       return TRUE;
     default:
@@ -1866,25 +1867,14 @@ peek_unary_expression (ParseData *data)
 static ViviCodeValue *
 parse_unary_expression (ParseData *data)
 {
+  ViviCodeValue *(*constructor) (ViviCodeValue *value);
   ViviCodeValue *value, *tmp;
   ViviCodeGet *get;
   gboolean increment = FALSE;
 
+  constructor = NULL;
   switch ((guint) vivi_parser_scanner_peek_next_token (data->scanner)) {
     //case TOKEN_DELETE:
-    case TOKEN_VOID:
-      vivi_parser_start_code_token (data);
-
-      vivi_parser_scanner_get_next_token (data->scanner);
-
-      value = parse_unary_expression (data);
-
-      tmp = VIVI_CODE_VALUE (value);
-      value = vivi_code_void_new (tmp);
-      g_object_unref (tmp);
-
-      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
-      break;
     //case TOKEN_TYPEOF:
     case TOKEN_INCREASE:
       increment = TRUE;
@@ -1940,8 +1930,16 @@ parse_unary_expression (ParseData *data)
 	g_object_unref (number);
       }
       break;
-    //case TOKEN_BITWISE_NOT:
+    case TOKEN_VOID:
+      if (constructor == NULL)
+	constructor = vivi_code_void_new;
+    case TOKEN_BITWISE_NOT:
+      if (constructor == NULL)
+	constructor = vivi_code_bit_not_new;
     case TOKEN_LOGICAL_NOT:
+      if (constructor == NULL)
+	constructor = vivi_code_not_new;
+
       vivi_parser_start_code_token (data);
 
       vivi_parser_scanner_get_next_token (data->scanner);
@@ -1949,7 +1947,7 @@ parse_unary_expression (ParseData *data)
       value = parse_unary_expression (data);
 
       tmp = VIVI_CODE_VALUE (value);
-      value = vivi_code_not_new (tmp);
+      value = constructor (tmp);
       g_object_unref (tmp);
 
       vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
commit acdb85e79fea2f73d11593e06bf35223583f0555
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 12:07:07 2008 +0300

    Forgot to add not test in an earlier commit

diff --git a/vivified/code/test/compiler/not.as b/vivified/code/test/compiler/not.as
new file mode 100644
index 0000000..cad339e
--- /dev/null
+++ b/vivified/code/test/compiler/not.as
@@ -0,0 +1 @@
+trace (!a);
diff --git a/vivified/code/test/compiler/not.as.expect b/vivified/code/test/compiler/not.as.expect
new file mode 100644
index 0000000..384128c
--- /dev/null
+++ b/vivified/code/test/compiler/not.as.expect
@@ -0,0 +1,8 @@
+asm {
+  pool "a"
+  push pool 0
+  get_variable
+  not
+  trace
+  end
+}
commit b00a620edc17597ebae015cb8a3dcaa57ac3f3c4
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 12:06:36 2008 +0300

    Implement compiling of void unary operator. Add a test

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 9e6f698..24706ae 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -92,6 +92,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_undefined.c \
 	vivi_code_value.c \
 	vivi_code_variable.c \
+	vivi_code_void.c \
 	vivi_compiler_empty_statement.c \
 	vivi_decompiler_block.c \
 	vivi_decompiler_duplicate.c \
@@ -170,6 +171,7 @@ noinst_HEADERS = \
 	vivi_code_undefined.h \
 	vivi_code_value.h \
 	vivi_code_variable.h \
+	vivi_code_void.h \
 	vivi_compiler_empty_statement.h \
 	vivi_decompiler.h \
 	vivi_decompiler_block.h \
diff --git a/vivified/code/test/compiler/void.as b/vivified/code/test/compiler/void.as
new file mode 100644
index 0000000..82e8569
--- /dev/null
+++ b/vivified/code/test/compiler/void.as
@@ -0,0 +1 @@
+trace (void a);
diff --git a/vivified/code/test/compiler/void.as.expect b/vivified/code/test/compiler/void.as.expect
new file mode 100644
index 0000000..f1d376f
--- /dev/null
+++ b/vivified/code/test/compiler/void.as.expect
@@ -0,0 +1,9 @@
+asm {
+  pool "a"
+  push pool 0
+  get_variable
+  pop
+  push undefined
+  trace
+  end
+}
diff --git a/vivified/code/vivi_code_void.c b/vivified/code/vivi_code_void.c
new file mode 100644
index 0000000..81c39a1
--- /dev/null
+++ b/vivified/code/vivi_code_void.c
@@ -0,0 +1,105 @@
+/* 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 void, 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_void.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_compiler.h"
+#include "vivi_code_asm.h"
+#include "vivi_code_asm_code_default.h"
+#include "vivi_code_asm_push.h"
+
+G_DEFINE_TYPE (ViviCodeVoid, vivi_code_void, VIVI_TYPE_CODE_VALUE)
+
+static void
+vivi_code_void_dispose (GObject *object)
+{
+  ViviCodeVoid *void_ = VIVI_CODE_VOID (object);
+
+  g_object_unref (void_->value);
+
+  G_OBJECT_CLASS (vivi_code_void_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_void_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
+{
+  ViviCodeVoid *void_ = VIVI_CODE_VOID (value);
+
+  vivi_code_printer_print (printer, "void ");
+  vivi_code_printer_print_value (printer, void_->value, VIVI_PRECEDENCE_UNARY);
+}
+
+static void
+vivi_code_void_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
+{
+  ViviCodeVoid *void_ = VIVI_CODE_VOID (value);
+  ViviCodeAsm *push;
+
+  vivi_code_compiler_compile_value (compiler, void_->value);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_pop_new ());
+
+  push = vivi_code_asm_push_new ();
+  vivi_code_asm_push_add_undefined (VIVI_CODE_ASM_PUSH (push));
+  vivi_code_compiler_take_code (compiler, push);
+}
+
+static void
+vivi_code_void_class_init (ViviCodeVoidClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
+
+  object_class->dispose = vivi_code_void_dispose;
+
+  value_class->print_value = vivi_code_void_print_value;
+  value_class->compile_value = vivi_code_void_compile_value;
+}
+
+static void
+vivi_code_void_init (ViviCodeVoid *void_)
+{
+  ViviCodeValue *value = VIVI_CODE_VALUE (void_);
+
+  vivi_code_value_set_precedence (value, VIVI_PRECEDENCE_UNARY);
+}
+
+ViviCodeValue *
+vivi_code_void_new (ViviCodeValue *value)
+{
+  ViviCodeVoid *void_;
+
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
+
+  void_ = g_object_new (VIVI_TYPE_CODE_VOID, NULL);
+  void_->value = g_object_ref (value);
+
+  return VIVI_CODE_VALUE (void_);
+}
+
+ViviCodeValue *
+vivi_code_void_get_value (ViviCodeVoid *void_)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_VOID (void_), NULL);
+
+  return void_->value;
+}
diff --git a/vivified/code/vivi_code_void.h b/vivified/code/vivi_code_void.h
new file mode 100644
index 0000000..f241605
--- /dev/null
+++ b/vivified/code/vivi_code_void.h
@@ -0,0 +1,57 @@
+/* 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 void, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_CODE_VOID_H_
+#define _VIVI_CODE_VOID_H_
+
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeVoid ViviCodeVoid;
+typedef struct _ViviCodeVoidClass ViviCodeVoidClass;
+
+#define VIVI_TYPE_CODE_VOID                    (vivi_code_void_get_type())
+#define VIVI_IS_CODE_VOID(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_VOID))
+#define VIVI_IS_CODE_VOID_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_VOID))
+#define VIVI_CODE_VOID(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_VOID, ViviCodeVoid))
+#define VIVI_CODE_VOID_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_VOID, ViviCodeVoidClass))
+#define VIVI_CODE_VOID_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_VOID, ViviCodeVoidClass))
+
+struct _ViviCodeVoid
+{
+  ViviCodeValue		parent;
+
+  ViviCodeValue *	value;
+};
+
+struct _ViviCodeVoidClass
+{
+  ViviCodeValueClass	value_class;
+};
+
+GType			vivi_code_void_get_type		(void);
+
+ViviCodeValue *		vivi_code_void_new		(ViviCodeValue *	value);
+
+ViviCodeValue *		vivi_code_void_get_value	(ViviCodeVoid *		void_);
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index a451e07..28239d6 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -67,6 +67,7 @@
 #include "vivi_code_not.h"
 #include "vivi_code_undefined.h"
 #include "vivi_code_variable.h"
+#include "vivi_code_void.h"
 #include "vivi_compiler_empty_statement.h"
 
 #include "vivi_code_text_printer.h"
@@ -1845,14 +1846,14 @@ static gboolean
 peek_unary_expression (ParseData *data)
 {
   switch ((guint) vivi_parser_scanner_peek_next_token (data->scanner)) {
-    /*case TOKEN_DELETE:
+    //case TOKEN_DELETE:
     case TOKEN_VOID:
-    case TOKEN_TYPEOF:*/
+    //case TOKEN_TYPEOF:
     case TOKEN_INCREASE:
     case TOKEN_DESCREASE:
     case TOKEN_PLUS:
     case TOKEN_MINUS:
-    /*case TOKEN_BITWISE_NOT:*/
+    //case TOKEN_BITWISE_NOT:
     case TOKEN_LOGICAL_NOT:
       return TRUE;
     default:
@@ -1870,9 +1871,21 @@ parse_unary_expression (ParseData *data)
   gboolean increment = FALSE;
 
   switch ((guint) vivi_parser_scanner_peek_next_token (data->scanner)) {
-    /*case TOKEN_DELETE:
+    //case TOKEN_DELETE:
     case TOKEN_VOID:
-    case TOKEN_TYPEOF:*/
+      vivi_parser_start_code_token (data);
+
+      vivi_parser_scanner_get_next_token (data->scanner);
+
+      value = parse_unary_expression (data);
+
+      tmp = VIVI_CODE_VALUE (value);
+      value = vivi_code_void_new (tmp);
+      g_object_unref (tmp);
+
+      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
+      break;
+    //case TOKEN_TYPEOF:
     case TOKEN_INCREASE:
       increment = TRUE;
     case TOKEN_DESCREASE:
@@ -1939,7 +1952,7 @@ parse_unary_expression (ParseData *data)
       value = vivi_code_not_new (tmp);
       g_object_unref (tmp);
 
-      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (tmp));
+      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
       break;
     default:
       value = parse_postfix_expression (data);
commit 8aeddfcda32c1fabd0e5778cd50df7b5df3f925f
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 11:56:38 2008 +0300

    Rename ViviCodeUnary to ViviCodeNot and change it accordingly

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 7f6668f..9e6f698 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -77,6 +77,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_init_object.c \
 	vivi_code_label.c \
 	vivi_code_loop.c \
+	vivi_code_not.c \
 	vivi_code_null.c \
 	vivi_code_number.c \
 	vivi_code_or.c \
@@ -88,7 +89,6 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_text_printer.c \
 	vivi_code_throw.c \
 	vivi_code_token.c \
-	vivi_code_unary.c \
 	vivi_code_undefined.c \
 	vivi_code_value.c \
 	vivi_code_variable.c \
@@ -155,6 +155,7 @@ noinst_HEADERS = \
 	vivi_code_init_object.h \
 	vivi_code_label.h \
 	vivi_code_loop.h \
+	vivi_code_not.h \
 	vivi_code_null.h \
 	vivi_code_number.h \
 	vivi_code_or.h \
@@ -166,7 +167,6 @@ noinst_HEADERS = \
 	vivi_code_text_printer.h \
 	vivi_code_throw.h \
 	vivi_code_token.h \
-	vivi_code_unary.h \
 	vivi_code_undefined.h \
 	vivi_code_value.h \
 	vivi_code_variable.h \
diff --git a/vivified/code/vivi_code_if.c b/vivified/code/vivi_code_if.c
index c0601b7..b3d230e 100644
--- a/vivified/code/vivi_code_if.c
+++ b/vivified/code/vivi_code_if.c
@@ -22,7 +22,7 @@
 #endif
 
 #include "vivi_code_if.h"
-#include "vivi_code_unary.h"
+#include "vivi_code_not.h"
 #include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
 #include "vivi_code_asm_if.h"
@@ -58,7 +58,7 @@ vivi_code_if_optimize (ViviCodeStatement *statement)
     return NULL;
 
   if (if_stmt == NULL && else_stmt != NULL) {
-    tmp = VIVI_CODE_VALUE (vivi_code_unary_new (stmt->condition, '!'));
+    tmp = VIVI_CODE_VALUE (vivi_code_not_new (stmt->condition));
     cond = vivi_code_value_optimize (tmp, SWFDEC_AS_TYPE_BOOLEAN);
     g_object_unref (tmp);
     if_stmt = else_stmt;
diff --git a/vivified/code/vivi_code_loop.c b/vivified/code/vivi_code_loop.c
index cf9a375..134d491 100644
--- a/vivified/code/vivi_code_loop.c
+++ b/vivified/code/vivi_code_loop.c
@@ -23,7 +23,6 @@
 
 #include "vivi_code_loop.h"
 #include "vivi_code_printer.h"
-#include "vivi_code_unary.h"
 #include "vivi_code_compiler.h"
 #include "vivi_code_label.h"
 #include "vivi_code_asm_if.h"
diff --git a/vivified/code/vivi_code_not.c b/vivified/code/vivi_code_not.c
new file mode 100644
index 0000000..7e2c0f7
--- /dev/null
+++ b/vivified/code/vivi_code_not.c
@@ -0,0 +1,121 @@
+/* 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_not.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 (ViviCodeNot, vivi_code_not, VIVI_TYPE_CODE_VALUE)
+
+static void
+vivi_code_not_dispose (GObject *object)
+{
+  ViviCodeNot *not = VIVI_CODE_NOT (object);
+
+  g_object_unref (not->value);
+
+  G_OBJECT_CLASS (vivi_code_not_parent_class)->dispose (object);
+}
+
+static ViviCodeValue * 
+vivi_code_not_optimize (ViviCodeValue *value, SwfdecAsValueType hint)
+{
+  ViviCodeNot *not = VIVI_CODE_NOT (value);
+
+  if (hint == SWFDEC_AS_TYPE_BOOLEAN && VIVI_IS_CODE_NOT (not->value)) {
+    return vivi_code_value_optimize (VIVI_CODE_NOT (not->value)->value, hint);
+  }
+
+  /* FIXME: optimize not->value */
+  return g_object_ref (not);
+}
+
+static void
+vivi_code_not_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
+{
+  ViviCodeNot *not = VIVI_CODE_NOT (value);
+
+  vivi_code_printer_print (printer, "!");
+  vivi_code_printer_print_value (printer, not->value, VIVI_PRECEDENCE_UNARY);
+}
+
+static void
+vivi_code_not_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
+{
+  ViviCodeNot *not = VIVI_CODE_NOT (value);
+
+  vivi_code_compiler_compile_value (compiler, not->value);
+  vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
+}
+
+static gboolean
+vivi_code_not_is_constant (ViviCodeValue *value)
+{
+  return vivi_code_value_is_constant (VIVI_CODE_NOT (value)->value);
+}
+
+static void
+vivi_code_not_class_init (ViviCodeNotClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
+
+  object_class->dispose = vivi_code_not_dispose;
+
+  value_class->print_value = vivi_code_not_print_value;
+  value_class->compile_value = vivi_code_not_compile_value;
+  value_class->is_constant = vivi_code_not_is_constant;
+  value_class->optimize = vivi_code_not_optimize;
+}
+
+static void
+vivi_code_not_init (ViviCodeNot *not)
+{
+  ViviCodeValue *value = VIVI_CODE_VALUE (not);
+
+  vivi_code_value_set_precedence (value, VIVI_PRECEDENCE_UNARY);
+}
+
+ViviCodeValue *
+vivi_code_not_new (ViviCodeValue *value)
+{
+  ViviCodeNot *not;
+
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
+
+  not = g_object_new (VIVI_TYPE_CODE_NOT, NULL);
+  not->value = g_object_ref (value);
+
+  return VIVI_CODE_VALUE (not);
+}
+
+ViviCodeValue *
+vivi_code_not_get_value (ViviCodeNot *not)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_NOT (not), NULL);
+
+  return not->value;
+}
+
diff --git a/vivified/code/vivi_code_not.h b/vivified/code/vivi_code_not.h
new file mode 100644
index 0000000..7be3177
--- /dev/null
+++ b/vivified/code/vivi_code_not.h
@@ -0,0 +1,57 @@
+/* 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_NOT_H_
+#define _VIVI_CODE_NOT_H_
+
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeNot ViviCodeNot;
+typedef struct _ViviCodeNotClass ViviCodeNotClass;
+
+#define VIVI_TYPE_CODE_NOT                    (vivi_code_not_get_type())
+#define VIVI_IS_CODE_NOT(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_NOT))
+#define VIVI_IS_CODE_NOT_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_NOT))
+#define VIVI_CODE_NOT(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_NOT, ViviCodeNot))
+#define VIVI_CODE_NOT_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_NOT, ViviCodeNotClass))
+#define VIVI_CODE_NOT_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_NOT, ViviCodeNotClass))
+
+struct _ViviCodeNot
+{
+  ViviCodeValue		parent;
+
+  ViviCodeValue *	value;
+};
+
+struct _ViviCodeNotClass
+{
+  ViviCodeValueClass	value_class;
+};
+
+GType			vivi_code_not_get_type		(void);
+
+ViviCodeValue *		vivi_code_not_new		(ViviCodeValue *	value);
+
+ViviCodeValue *		vivi_code_not_get_value		(ViviCodeNot *		not);
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_code_unary.c b/vivified/code/vivi_code_unary.c
deleted file mode 100644
index 609827b..0000000
--- a/vivified/code/vivi_code_unary.c
+++ /dev/null
@@ -1,133 +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_unary.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 (ViviCodeUnary, vivi_code_unary, VIVI_TYPE_CODE_VALUE)
-
-static void
-vivi_code_unary_dispose (GObject *object)
-{
-  ViviCodeUnary *unary = VIVI_CODE_UNARY (object);
-
-  g_object_unref (unary->value);
-
-  G_OBJECT_CLASS (vivi_code_unary_parent_class)->dispose (object);
-}
-
-static ViviCodeValue * 
-vivi_code_unary_optimize (ViviCodeValue *value, SwfdecAsValueType hint)
-{
-  ViviCodeUnary *unary = VIVI_CODE_UNARY (value);
-
-  if (unary->operation == '!' && 
-      hint == SWFDEC_AS_TYPE_BOOLEAN &&
-      VIVI_IS_CODE_UNARY (unary->value) && 
-      VIVI_CODE_UNARY (unary->value)->operation == unary->operation) {
-    return vivi_code_value_optimize (VIVI_CODE_UNARY (unary->value)->value, hint);
-  }
-
-  /* FIXME: optimize unary->value */
-  return g_object_ref (unary);
-}
-
-static void
-vivi_code_unary_print_value (ViviCodeValue *value, ViviCodePrinter *printer)
-{
-  ViviCodeUnary *unary = VIVI_CODE_UNARY (value);
-  char *sign;
-
-  /* FIXME: ugly! */
-  sign = g_strndup (&unary->operation, 1);
-  vivi_code_printer_print (printer, sign);
-  g_free (sign);
-
-  vivi_code_printer_print_value (printer, unary->value, VIVI_PRECEDENCE_UNARY);
-}
-
-static void
-vivi_code_unary_compile_value (ViviCodeValue *value, ViviCodeCompiler *compiler)
-{
-  ViviCodeUnary *unary = VIVI_CODE_UNARY (value);
-
-  g_return_if_fail (unary->operation == '!');
-
-  vivi_code_compiler_compile_value (compiler, unary->value);
-
-  vivi_code_compiler_take_code (compiler, vivi_code_asm_not_new ());
-}
-
-static gboolean
-vivi_code_unary_is_constant (ViviCodeValue *value)
-{
-  return vivi_code_value_is_constant (VIVI_CODE_UNARY (value)->value);
-}
-
-static void
-vivi_code_unary_class_init (ViviCodeUnaryClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
-
-  object_class->dispose = vivi_code_unary_dispose;
-
-  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;
-}
-
-static void
-vivi_code_unary_init (ViviCodeUnary *unary)
-{
-  ViviCodeValue *value = VIVI_CODE_VALUE (unary);
-
-  vivi_code_value_set_precedence (value, VIVI_PRECEDENCE_UNARY);
-}
-
-ViviCodeValue *
-vivi_code_unary_new (ViviCodeValue *value, char operation)
-{
-  ViviCodeUnary *unary;
-
-  g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
-
-  unary = g_object_new (VIVI_TYPE_CODE_UNARY, NULL);
-  unary->value = g_object_ref (value);
-  unary->operation = operation;
-
-  return VIVI_CODE_VALUE (unary);
-}
-
-ViviCodeValue *
-vivi_code_unary_get_value (ViviCodeUnary *unary)
-{
-  g_return_val_if_fail (VIVI_IS_CODE_UNARY (unary), NULL);
-
-  return unary->value;
-}
-
diff --git a/vivified/code/vivi_code_unary.h b/vivified/code/vivi_code_unary.h
deleted file mode 100644
index 70eeeb8..0000000
--- a/vivified/code/vivi_code_unary.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_UNARY_H_
-#define _VIVI_CODE_UNARY_H_
-
-#include <vivified/code/vivi_code_value.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _ViviCodeUnary ViviCodeUnary;
-typedef struct _ViviCodeUnaryClass ViviCodeUnaryClass;
-
-#define VIVI_TYPE_CODE_UNARY                    (vivi_code_unary_get_type())
-#define VIVI_IS_CODE_UNARY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_UNARY))
-#define VIVI_IS_CODE_UNARY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_UNARY))
-#define VIVI_CODE_UNARY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_UNARY, ViviCodeUnary))
-#define VIVI_CODE_UNARY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_UNARY, ViviCodeUnaryClass))
-#define VIVI_CODE_UNARY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_UNARY, ViviCodeUnaryClass))
-
-struct _ViviCodeUnary
-{
-  ViviCodeValue		parent;
-
-  char			operation;
-  ViviCodeValue *	value;
-};
-
-struct _ViviCodeUnaryClass
-{
-  ViviCodeValueClass	value_class;
-};
-
-GType			vivi_code_unary_get_type   	(void);
-
-ViviCodeValue *		vivi_code_unary_new		(ViviCodeValue *	value,
-							 char			operation);
-
-ViviCodeValue *		vivi_code_unary_get_value	(ViviCodeUnary *	unary);
-
-G_END_DECLS
-#endif
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index 9412807..0d49678 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -50,7 +50,7 @@
 #include "vivi_code_or.h"
 #include "vivi_code_return.h"
 #include "vivi_code_string.h"
-#include "vivi_code_unary.h"
+#include "vivi_code_not.h"
 #include "vivi_code_undefined.h"
 #include "vivi_code_variable.h"
 #include "vivi_decompiler_block.h"
@@ -317,11 +317,11 @@ static gboolean
 vivi_decompile_not (ViviDecompilerBlock *block, ViviDecompilerState *state,
     guint code, const guint8 *data, guint len)
 {
-  ViviCodeValue *val, *unary;
+  ViviCodeValue *val, *not;
 
   val = vivi_decompiler_state_pop (state);
-  unary = vivi_code_unary_new (val, '!');
-  vivi_decompiler_state_push (state, unary);
+  not = vivi_code_not_new (val);
+  vivi_decompiler_state_push (state, not);
   g_object_unref (val);
   return TRUE;
 }
@@ -1102,8 +1102,8 @@ vivi_decompiler_merge_andor (GList **list)
       continue;
     /* extract the value */
     value = vivi_decompiler_block_get_branch_condition (block);
-    if (VIVI_IS_CODE_UNARY (value)) {
-      value = vivi_code_unary_get_value (VIVI_CODE_UNARY (value));
+    if (VIVI_IS_CODE_NOT (value)) {
+      value = vivi_code_not_get_value (VIVI_CODE_NOT (value));
       func = vivi_code_and_new;
     } else {
       func = vivi_code_or_new;
@@ -1348,7 +1348,7 @@ vivi_decompiler_merge_loops (GList **list)
 	  vivi_decompiler_block_get_next (start) == end))) {
       if (vivi_decompiler_block_get_branch (start) == end) {
 	ViviCodeValue *value, *opt;
-	value = vivi_code_unary_new (vivi_decompiler_block_get_branch_condition (start), '!');
+	value = vivi_code_not_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, FALSE);
@@ -1373,7 +1373,7 @@ vivi_decompiler_merge_loops (GList **list)
       vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), VIVI_CODE_STATEMENT (loop));
       if (vivi_decompiler_block_get_branch (start)) {
 	ViviCodeValue *value, *opt;
-	value = vivi_code_unary_new (vivi_decompiler_block_get_branch_condition (start), '!');
+	value = vivi_code_not_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, FALSE);
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index fb87718..a451e07 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -64,7 +64,7 @@
 #include "vivi_code_string.h"
 #include "vivi_code_substring.h"
 #include "vivi_code_throw.h"
-#include "vivi_code_unary.h"
+#include "vivi_code_not.h"
 #include "vivi_code_undefined.h"
 #include "vivi_code_variable.h"
 #include "vivi_compiler_empty_statement.h"
@@ -1936,7 +1936,7 @@ parse_unary_expression (ParseData *data)
       value = parse_unary_expression (data);
 
       tmp = VIVI_CODE_VALUE (value);
-      value = vivi_code_unary_new (tmp, '!');
+      value = vivi_code_not_new (tmp);
       g_object_unref (tmp);
 
       vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (tmp));
@@ -2022,7 +2022,7 @@ again:
 	    tokens[i] == TOKEN_NOT_STRICT_EQUAL ||
 	    tokens[i] == TOKEN_LESS_THAN_OR_EQUAL ||
 	    tokens[i] == TOKEN_GREATER_THAN_OR_EQUAL) {
-	  left = vivi_code_unary_new (value, '!');
+	  left = vivi_code_not_new (value);
 	  g_object_unref (value);
 	  value = left;
 
commit c32906225f4980b7abca61cd42c93b5145f6cb45
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 11:48:18 2008 +0300

    Remove unused ViviCompilerGetTemporary class

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index b07bd6b..7f6668f 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -93,7 +93,6 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_value.c \
 	vivi_code_variable.c \
 	vivi_compiler_empty_statement.c \
-	vivi_compiler_get_temporary.c \
 	vivi_decompiler_block.c \
 	vivi_decompiler_duplicate.c \
 	vivi_decompiler_state.c \
@@ -172,7 +171,6 @@ noinst_HEADERS = \
 	vivi_code_value.h \
 	vivi_code_variable.h \
 	vivi_compiler_empty_statement.h \
-	vivi_compiler_get_temporary.h \
 	vivi_decompiler.h \
 	vivi_decompiler_block.h \
 	vivi_decompiler_duplicate.h \
diff --git a/vivified/code/vivi_compiler_get_temporary.c b/vivified/code/vivi_compiler_get_temporary.c
deleted file mode 100644
index 1b7e2c7..0000000
--- a/vivified/code/vivi_compiler_get_temporary.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* 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_compiler_get_temporary.h"
-
-#include "vivi_code_get.h"
-#include "vivi_code_printer.h"
-#include "vivi_code_string.h"
-
-G_DEFINE_TYPE (ViviCompilerGetTemporary, vivi_compiler_get_temporary, VIVI_TYPE_CODE_GET)
-
-static void
-vivi_compiler_get_temporary_class_init (ViviCompilerGetTemporaryClass *klass)
-{
-}
-
-static void
-vivi_compiler_get_temporary_init (ViviCompilerGetTemporary *get)
-{
-}
-
-ViviCodeValue *
-vivi_compiler_get_temporary_new (void)
-{
-  static int counter = 0;
-  ViviCompilerGetTemporary *get;
-  char *name = g_strdup_printf ("$%i", ++counter);
-
-  get = g_object_new (VIVI_TYPE_COMPILER_GET_TEMPORARY, NULL);
-  VIVI_CODE_GET (get)->name = vivi_code_string_new (name);
-
-  g_free (name);
-
-  return VIVI_CODE_VALUE (get);
-}
diff --git a/vivified/code/vivi_compiler_get_temporary.h b/vivified/code/vivi_compiler_get_temporary.h
deleted file mode 100644
index 5a748f2..0000000
--- a/vivified/code/vivi_compiler_get_temporary.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* 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_COMPILER_GET_TEMPORARY_H_
-#define _VIVI_COMPILER_GET_TEMPORARY_H_
-
-#include <vivified/code/vivi_code_get.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _ViviCompilerGetTemporary ViviCompilerGetTemporary;
-typedef struct _ViviCompilerGetTemporaryClass ViviCompilerGetTemporaryClass;
-
-#define VIVI_TYPE_COMPILER_GET_TEMPORARY                    (vivi_compiler_get_temporary_get_type())
-#define VIVI_IS_COMPILER_GET_TEMPORARY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_COMPILER_GET_TEMPORARY))
-#define VIVI_IS_COMPILER_GET_TEMPORARY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_COMPILER_GET_TEMPORARY))
-#define VIVI_COMPILER_GET_TEMPORARY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_COMPILER_GET_TEMPORARY, ViviCompilerGetTemporary))
-#define VIVI_COMPILER_GET_TEMPORARY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_COMPILER_GET_TEMPORARY, ViviCompilerGetTemporaryClass))
-#define VIVI_COMPILER_GET_TEMPORARY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_COMPILER_GET_TEMPORARY, ViviCompilerGetTemporaryClass))
-
-struct _ViviCompilerGetTemporary
-{
-  ViviCodeGet		value;
-};
-
-struct _ViviCompilerGetTemporaryClass
-{
-  ViviCodeGetClass	value_class;
-};
-
-GType			vivi_compiler_get_temporary_get_type   	(void);
-
-ViviCodeValue *		vivi_compiler_get_temporary_new		(void);
-
-
-G_END_DECLS
-#endif
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index af92a73..fb87718 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -68,7 +68,6 @@
 #include "vivi_code_undefined.h"
 #include "vivi_code_variable.h"
 #include "vivi_compiler_empty_statement.h"
-#include "vivi_compiler_get_temporary.h"
 
 #include "vivi_code_text_printer.h"
 #include "vivi_code_assembler.h"
commit df255edb2791c98e292d0f66687d55a051f0613d
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 11:40:04 2008 +0300

    Add a vivi-compile test for not

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 60cf6eb..3cfc032 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -98,6 +98,8 @@ EXTRA_DIST = \
 	label.as.expect \
 	misc_literal.as \
 	misc_literal.as.expect \
+	not.as \
+	not.as.expect \
 	number.as \
 	number.as.expect \
 	operator.as \
commit 971e8457bce8989c2d063a7937dcb0954b0fa21d
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 11:38:15 2008 +0300

    Fix bugs in unary plus/minus and add tests

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 06c6ccb..60cf6eb 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -114,6 +114,10 @@ EXTRA_DIST = \
 	string.as.expect \
 	trace.as \
 	trace.as.expect \
+	unary_minus.as \
+	unary_minus.as.expect \
+	unary_plus.as \
+	unary_plus.as.expect \
 	var.as \
 	var.as.expect \
 	while.as \
diff --git a/vivified/code/test/compiler/unary_minus.as b/vivified/code/test/compiler/unary_minus.as
new file mode 100644
index 0000000..1bfb46a
--- /dev/null
+++ b/vivified/code/test/compiler/unary_minus.as
@@ -0,0 +1,2 @@
+trace (-a);
+trace (-5);
diff --git a/vivified/code/test/compiler/unary_minus.as.expect b/vivified/code/test/compiler/unary_minus.as.expect
new file mode 100644
index 0000000..696d288
--- /dev/null
+++ b/vivified/code/test/compiler/unary_minus.as.expect
@@ -0,0 +1,10 @@
+asm {
+  pool "a"
+  push -1, pool 0
+  get_variable
+  multiply
+  trace
+  push -5
+  trace
+  end
+}
diff --git a/vivified/code/test/compiler/unary_plus.as b/vivified/code/test/compiler/unary_plus.as
new file mode 100644
index 0000000..d3d5761
--- /dev/null
+++ b/vivified/code/test/compiler/unary_plus.as
@@ -0,0 +1,2 @@
+trace (+a);
+trace (+5);
diff --git a/vivified/code/test/compiler/unary_plus.as.expect b/vivified/code/test/compiler/unary_plus.as.expect
new file mode 100644
index 0000000..5f7fffd
--- /dev/null
+++ b/vivified/code/test/compiler/unary_plus.as.expect
@@ -0,0 +1,10 @@
+asm {
+  pool "a"
+  push pool 0
+  get_variable
+  to_number
+  trace
+  push 5
+  trace
+  end
+}
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 50432a4..af92a73 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -1851,9 +1851,9 @@ peek_unary_expression (ParseData *data)
     case TOKEN_TYPEOF:*/
     case TOKEN_INCREASE:
     case TOKEN_DESCREASE:
-    /*case TOKEN_PLUS:
+    case TOKEN_PLUS:
     case TOKEN_MINUS:
-    case TOKEN_BITWISE_NOT:*/
+    /*case TOKEN_BITWISE_NOT:*/
     case TOKEN_LOGICAL_NOT:
       return TRUE;
     default:
@@ -1921,10 +1921,6 @@ parse_unary_expression (ParseData *data)
       } else {
 	ViviCodeValue *number;
 
-	tmp = value;
-	value = vivi_code_to_number_new (tmp);
-	g_object_unref (tmp);
-
 	number = vivi_code_number_new (-1);
 	tmp = value;
 	value = vivi_code_multiply_new (number, tmp);
commit db01e67941b333c4d25113fa2e9daefe7af9a414
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 11:27:46 2008 +0300

    Implement compiling of get_url2 statements. Add a test

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 05676b3..06c6ccb 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -80,6 +80,8 @@ EXTRA_DIST = \
 	function_declaration.as.expect \
 	function_expression.as \
 	function_expression.as.expect \
+	get_url.as \
+	get_url.as.expect \
 	if.as \
 	if.as.expect \
 	if_else.as \
diff --git a/vivified/code/test/compiler/get_url.as b/vivified/code/test/compiler/get_url.as
new file mode 100644
index 0000000..0464027
--- /dev/null
+++ b/vivified/code/test/compiler/get_url.as
@@ -0,0 +1,18 @@
+getURL ("url");
+getURL ("url", "target");
+getURL ("url", "target", "POST");
+getURL ("url", "target", "GET");
+getURL ("url", "target", "POST");
+getURL ("url", "target", "GET");
+
+loadMovie ("url", "target");
+loadMovie ("url", "target", "POST");
+
+loadMovieNum ("url", 1);
+loadMovieNum ("url", 1, "POST");
+
+loadVariables ("url", "target");
+loadVariables ("url", "target", "POST");
+
+loadVariablesNum ("url", 1);
+loadVariablesNum ("url", 1, "POST");
diff --git a/vivified/code/test/compiler/get_url.as.expect b/vivified/code/test/compiler/get_url.as.expect
new file mode 100644
index 0000000..5b02ead
--- /dev/null
+++ b/vivified/code/test/compiler/get_url.as.expect
@@ -0,0 +1,19 @@
+asm {
+  pool "url", "", "target", "_level1"
+  push pool 0, pool 3, pool 0, pool 3, pool 0, pool 2, pool 0, pool 2, pool 0, pool 3, pool 0, pool 3, pool 0, pool 2, pool 0, pool 2, pool 0, pool 2, pool 0, pool 2, pool 0, pool 2, pool 0, pool 2, pool 0, pool 2, pool 0, pool 1
+  get_url2
+  get_url2
+  get_url2 post
+  get_url2 get
+  get_url2 post
+  get_url2 get
+  get_url2 internal
+  get_url2 post internal
+  get_url2
+  get_url2 post
+  get_url2 internal variables
+  get_url2 post internal variables
+  get_url2 variables
+  get_url2 post variables
+  end
+}
diff --git a/vivified/code/vivi_code_get_url.c b/vivified/code/vivi_code_get_url.c
index ea1bb2a..9d36316 100644
--- a/vivified/code/vivi_code_get_url.c
+++ b/vivified/code/vivi_code_get_url.c
@@ -24,6 +24,7 @@
 #include "vivi_code_get_url.h"
 #include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
+#include "vivi_code_asm_get_url2.h"
 
 G_DEFINE_TYPE (ViviCodeGetUrl, vivi_code_get_url, VIVI_TYPE_CODE_STATEMENT)
 
@@ -64,17 +65,13 @@ vivi_code_get_url_print (ViviCodeToken *token, ViviCodePrinter *printer)
 static void
 vivi_code_get_url_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
 {
-  g_printerr ("Implement getURL2");
-#if 0
   ViviCodeGetUrl *url = VIVI_CODE_GET_URL (token);
-  guint bits;
 
-  vivi_code_value_compile (url->url, assembler);
-  vivi_code_value_compile (url->target, assembler);
+  vivi_code_compiler_compile_value (compiler, url->url);
+  vivi_code_compiler_compile_value (compiler, url->target);
 
-  vivi_code_assembler_take_code (assembler,
+  vivi_code_compiler_take_code (compiler,
       vivi_code_asm_get_url2_new (url->method, url->internal, url->variables));
-#endif
 }
 
 static void
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 55bd54a..50432a4 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -1307,7 +1307,7 @@ parse_get_url2 (ParseData *data, gboolean require_two, gboolean level,
       method = SWFDEC_LOADER_REQUEST_DEFAULT;
     }
   } else {
-    target = vivi_code_undefined_new ();
+    target = vivi_code_string_new ("");
     method = SWFDEC_LOADER_REQUEST_DEFAULT;
   }
 
@@ -1335,13 +1335,13 @@ parse_load_movie (ParseData *data)
 static ViviCodeStatement *
 parse_load_movie_num (ParseData *data)
 {
-  return parse_get_url2 (data, TRUE, TRUE, TRUE, FALSE);
+  return parse_get_url2 (data, TRUE, TRUE, FALSE, FALSE);
 }
 
 static ViviCodeStatement *
 parse_load_variables (ParseData *data)
 {
-  return parse_get_url2 (data, TRUE, FALSE, FALSE, TRUE);
+  return parse_get_url2 (data, TRUE, FALSE, TRUE, TRUE);
 }
 
 static ViviCodeStatement *
commit dc083b778f67e4921823c2ad0bdb78ed0b4493a0
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 11:10:57 2008 +0300

    Add support for disassembling get_url2

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 7cd5dcc..b07bd6b 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -33,6 +33,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_asm_function.c \
 	vivi_code_asm_function2.c \
 	vivi_code_asm_get_url.c \
+	vivi_code_asm_get_url2.c \
 	vivi_code_asm_if.c \
 	vivi_code_asm_jump.c \
 	vivi_code_asm_pool.c \
@@ -110,6 +111,7 @@ noinst_HEADERS = \
 	vivi_code_asm_function.h \
 	vivi_code_asm_function2.h \
 	vivi_code_asm_get_url.h \
+	vivi_code_asm_get_url2.h \
 	vivi_code_asm_if.h \
 	vivi_code_asm_jump.h \
 	vivi_code_asm_pool.h \
diff --git a/vivified/code/vivi_code_asm_get_url2.c b/vivified/code/vivi_code_asm_get_url2.c
new file mode 100644
index 0000000..210eb33
--- /dev/null
+++ b/vivified/code/vivi_code_asm_get_url2.c
@@ -0,0 +1,129 @@
+/* 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 <swfdec/swfdec_as_interpret.h>
+#include <swfdec/swfdec_bots.h>
+
+#include "vivi_code_asm_get_url2.h"
+#include "vivi_code_asm.h"
+#include "vivi_code_emitter.h"
+#include "vivi_code_printer.h"
+
+static gboolean
+vivi_code_asm_get_url2_emit (ViviCodeAsm *code, ViviCodeEmitter *emitter,
+    GError **error)
+{
+  ViviCodeAsmGetUrl2 *get_url = VIVI_CODE_ASM_GET_URL2 (code);
+  SwfdecBots *emit = vivi_code_emitter_get_bots (emitter);
+
+  swfdec_bots_put_u8 (emit, SWFDEC_AS_ACTION_GET_URL2);
+  swfdec_bots_put_u8 (emit, get_url->flags);
+
+  return TRUE;
+}
+
+static void
+vivi_code_asm_get_url2_asm_init (ViviCodeAsmInterface *iface)
+{
+  iface->emit = vivi_code_asm_get_url2_emit;
+}
+
+G_DEFINE_TYPE_WITH_CODE (ViviCodeAsmGetUrl2, vivi_code_asm_get_url2, VIVI_TYPE_CODE_ASM_CODE,
+    G_IMPLEMENT_INTERFACE (VIVI_TYPE_CODE_ASM, vivi_code_asm_get_url2_asm_init))
+
+
+/* FIXME: export for compiler */
+static const char *flag_names[16] = {
+  "get",
+  "post",
+  "reserved1",
+  "reserved2",
+  "reserved3",
+  "reserved4",
+  "internal",
+  "variables"
+};
+
+static void
+vivi_code_asm_get_url2_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  ViviCodeAsmGetUrl2 *get_url = VIVI_CODE_ASM_GET_URL2 (token);
+  guint i;
+
+  vivi_code_printer_print (printer, "get_url2");
+  for (i = 0; i < G_N_ELEMENTS (flag_names); i++) {
+    if (get_url->flags & (1 << i)) {
+      vivi_code_printer_print (printer, " ");
+      vivi_code_printer_print (printer, flag_names[i]);
+    }
+  }
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_code_asm_get_url2_class_init (ViviCodeAsmGetUrl2Class *klass)
+{
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeAsmCodeClass *code_class = VIVI_CODE_ASM_CODE_CLASS (klass);
+
+  token_class->print = vivi_code_asm_get_url2_print;
+
+  code_class->bytecode = SWFDEC_AS_ACTION_GET_URL2;
+}
+
+static void
+vivi_code_asm_get_url2_init (ViviCodeAsmGetUrl2 *get_url)
+{
+}
+
+ViviCodeAsm *
+vivi_code_asm_get_url2_new_from_flags (guint flags)
+{
+  ViviCodeAsmGetUrl2 *get_url;
+
+  g_return_val_if_fail (flags < G_MAXUINT8, NULL);
+
+  get_url = g_object_new (VIVI_TYPE_CODE_ASM_GET_URL2, NULL);
+  get_url->flags = flags;
+
+  return VIVI_CODE_ASM (get_url);
+}
+
+ViviCodeAsm *
+vivi_code_asm_get_url2_new (SwfdecLoaderRequest method, gboolean internal,
+    gboolean variables)
+{
+  guint flags = 0;
+
+  if (method == SWFDEC_LOADER_REQUEST_GET) {
+    flags |= (1 << 0);
+  } else if (method == SWFDEC_LOADER_REQUEST_POST) {
+    flags |= (1 << 1);
+  }
+  if (internal)
+    flags |= (1 << 6);
+  if (variables)
+    flags |= (1 << 7);
+
+  return vivi_code_asm_get_url2_new_from_flags (flags);
+}
diff --git a/vivified/code/vivi_code_asm_get_url2.h b/vivified/code/vivi_code_asm_get_url2.h
new file mode 100644
index 0000000..82e39f7
--- /dev/null
+++ b/vivified/code/vivi_code_asm_get_url2.h
@@ -0,0 +1,60 @@
+/* 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_ASM_GET_URL2_H_
+#define _VIVI_CODE_ASM_GET_URL2_H_
+
+#include <vivified/code/vivi_code_asm.h>
+#include <vivified/code/vivi_code_asm_code.h>
+
+G_BEGIN_DECLS
+
+typedef struct _ViviCodeAsmGetUrl2 ViviCodeAsmGetUrl2;
+typedef struct _ViviCodeAsmGetUrl2Class ViviCodeAsmGetUrl2Class;
+
+#define VIVI_TYPE_CODE_ASM_GET_URL2                    (vivi_code_asm_get_url2_get_type())
+#define VIVI_IS_CODE_ASM_GET_URL2(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_ASM_GET_URL2))
+#define VIVI_IS_CODE_ASM_GET_URL2_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_ASM_GET_URL2))
+#define VIVI_CODE_ASM_GET_URL2(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_ASM_GET_URL2, ViviCodeAsmGetUrl2))
+#define VIVI_CODE_ASM_GET_URL2_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_ASM_GET_URL2, ViviCodeAsmGetUrl2Class))
+#define VIVI_CODE_ASM_GET_URL2_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_ASM_GET_URL2, ViviCodeAsmGetUrl2Class))
+
+struct _ViviCodeAsmGetUrl2
+{
+  ViviCodeAsmCode	code;
+
+  guint			flags;
+};
+
+struct _ViviCodeAsmGetUrl2Class
+{
+  ViviCodeAsmCodeClass	code_class;
+};
+
+GType		vivi_code_asm_get_url2_get_type	  	(void);
+
+ViviCodeAsm *	vivi_code_asm_get_url2_new		(SwfdecLoaderRequest		method,
+							 gboolean			internal,
+							 gboolean			variables);
+
+ViviCodeAsm *	vivi_code_asm_get_url2_new_from_flags	(guint				flags);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_disassembler.c b/vivified/code/vivi_disassembler.c
index 69be97c..65d8212 100644
--- a/vivified/code/vivi_disassembler.c
+++ b/vivified/code/vivi_disassembler.c
@@ -30,6 +30,7 @@
 #include "vivi_code_asm_function.h"
 #include "vivi_code_asm_function2.h"
 #include "vivi_code_asm_get_url.h"
+#include "vivi_code_asm_get_url2.h"
 #include "vivi_code_asm_if.h"
 #include "vivi_code_asm_jump.h"
 #include "vivi_code_asm_pool.h"
@@ -71,6 +72,18 @@ vivi_disassemble_get_url (ViviCodeAssembler *assembler, SwfdecBits *bits, guint
 }
 
 static void
+vivi_disassemble_get_url2 (ViviCodeAssembler *assembler, SwfdecBits *bits, guint version)
+{
+  ViviCodeAsm *code;
+  guint flags;
+
+  flags = swfdec_bits_get_u8 (bits);
+  code = vivi_code_asm_get_url2_new_from_flags (flags);
+  vivi_code_assembler_add_code (assembler, code);
+  g_object_unref (code);
+}
+
+static void
 vivi_disassemble_store (ViviCodeAssembler *assembler, SwfdecBits *bits)
 {
   ViviCodeAsm *code;
@@ -444,6 +457,8 @@ vivi_disassemble_script (SwfdecScript *script)
         case SWFDEC_AS_ACTION_GOTO_LABEL:
         case SWFDEC_AS_ACTION_WAIT_FOR_FRAME2:
         case SWFDEC_AS_ACTION_GET_URL2:
+	  vivi_disassemble_get_url2 (assembler, &bits, script->version);
+	  break;
         case SWFDEC_AS_ACTION_CALL:
         case SWFDEC_AS_ACTION_GOTO_FRAME2:
 	default:
commit 6df190a6c7438c427d6ad6b28edfebc76b147dd6
Merge: db46181... ad54529...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri May 23 10:20:19 2008 +0300

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

commit db46181386bcdccd81defebc20b7c378399ddb82
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 16:07:49 2008 +0300

    Add a test for compiling break and continue statements with labels

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index ea9b63c..05676b3 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -46,6 +46,8 @@ EXTRA_DIST = \
 	automatic_semicolon.as.expect \
 	builtin_statement.as \
 	builtin_statement.as.expect \
+	break_continue_label.as \
+	break_continue_label.as.expect \
 	call_function.as \
 	call_function.as.expect \
 	combine_push.as \
diff --git a/vivified/code/test/compiler/break_continue_label.as b/vivified/code/test/compiler/break_continue_label.as
new file mode 100644
index 0000000..efb73e0
--- /dev/null
+++ b/vivified/code/test/compiler/break_continue_label.as
@@ -0,0 +1,9 @@
+before:
+trace ("Hello");
+if (a) {
+  break before;
+} else {
+  continue after;
+}
+trace ("World");
+after:
diff --git a/vivified/code/test/compiler/break_continue_label.as.expect b/vivified/code/test/compiler/break_continue_label.as.expect
new file mode 100644
index 0000000..4898bfb
--- /dev/null
+++ b/vivified/code/test/compiler/break_continue_label.as.expect
@@ -0,0 +1,21 @@
+asm {
+  pool "Hello", "a", "World"
+
+before:
+  push pool 1, pool 0
+  trace
+  get_variable
+  if if_true_0001
+  jump after
+  jump if_end_0002
+
+if_true_0001:
+  jump before
+
+if_end_0002:
+  push pool 2
+  trace
+
+after:
+  end
+}
commit d016b0255b89f976d45491760c94423697ee6a78
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 15:57:10 2008 +0300

    Fix compiling of ViviCodeLabels
    
    And fix two test cases that were wrong...

diff --git a/vivified/code/test/compiler/combine_push.as.expect b/vivified/code/test/compiler/combine_push.as.expect
index b8a5fc0..77cd064 100644
--- a/vivified/code/test/compiler/combine_push.as.expect
+++ b/vivified/code/test/compiler/combine_push.as.expect
@@ -4,7 +4,7 @@ asm {
   trace
   trace
 
-hello_0001:
+hello:
   push pool 1, pool 0
   trace
   trace
diff --git a/vivified/code/test/compiler/label.as.expect b/vivified/code/test/compiler/label.as.expect
index 63e6efe..5990cff 100644
--- a/vivified/code/test/compiler/label.as.expect
+++ b/vivified/code/test/compiler/label.as.expect
@@ -1,7 +1,7 @@
 asm {
   play
 
-hello_0001:
+hello:
   stop
   end
 }
diff --git a/vivified/code/vivi_code_label.c b/vivified/code/vivi_code_label.c
index 6d6d7fa..672da77 100644
--- a/vivified/code/vivi_code_label.c
+++ b/vivified/code/vivi_code_label.c
@@ -81,7 +81,7 @@ vivi_code_label_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
   ViviCodeLabel *label = VIVI_CODE_LABEL (token);
 
   vivi_code_compiler_take_code (compiler,
-      VIVI_CODE_ASM (vivi_code_compiler_create_label (compiler, label->name)));
+      VIVI_CODE_ASM (vivi_code_label_new (label->name)));
 }
 
 static gboolean
commit 9267b1eb3f35db4a47d6d4fdc7995382a30d68f8
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 15:53:30 2008 +0300

    Fix some stupid mistakes in last commit

diff --git a/vivified/code/vivi_code_label.c b/vivified/code/vivi_code_label.c
index f7533f3..6d6d7fa 100644
--- a/vivified/code/vivi_code_label.c
+++ b/vivified/code/vivi_code_label.c
@@ -124,7 +124,7 @@ vivi_code_label_new (const char *name)
 }
 
 const char *
-vivi_code_label_get_name (ViviCodeLabel *label)
+vivi_code_label_get_name (const ViviCodeLabel *label)
 {
   g_return_val_if_fail (VIVI_IS_CODE_LABEL (label), NULL);
 
diff --git a/vivified/code/vivi_code_label.h b/vivified/code/vivi_code_label.h
index 342e728..c5f3938 100644
--- a/vivified/code/vivi_code_label.h
+++ b/vivified/code/vivi_code_label.h
@@ -51,7 +51,7 @@ GType			vivi_code_label_get_type   	(void);
 
 ViviCodeStatement *	vivi_code_label_new		(const char *		name);
 
-const char *		vivi_code_label_get_name	(ViviCodeLabel *	label);
+const char *		vivi_code_label_get_name	(const ViviCodeLabel *	label);
 
 
 G_END_DECLS
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 65565df..55bd54a 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -473,9 +473,9 @@ vivi_parser_add_waiting_label (ParseData *data, ViviCodeLabel *label)
   g_return_if_fail (data->level != NULL);
   g_return_if_fail (VIVI_IS_CODE_LABEL (label));
   g_return_if_fail (vivi_parser_get_waiting_label (data,
-	vivi_code_label_get_name (label)));
+	vivi_code_label_get_name (label)) == NULL);
 
-  data->level->labels =
+  data->level->waiting_labels =
     g_slist_prepend (data->level->waiting_labels, g_object_ref (label));
 }
 
commit b3ab9fb47241a1f1892f66d27037d051e99afb2a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 15:37:29 2008 +0300

    Improve label/goto handling in the parser. Get rid of ViviCompilerGotoName

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 87409e4..7cd5dcc 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -93,7 +93,6 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_variable.c \
 	vivi_compiler_empty_statement.c \
 	vivi_compiler_get_temporary.c \
-	vivi_compiler_goto_name.c \
 	vivi_decompiler_block.c \
 	vivi_decompiler_duplicate.c \
 	vivi_decompiler_state.c \
@@ -172,7 +171,6 @@ noinst_HEADERS = \
 	vivi_code_variable.h \
 	vivi_compiler_empty_statement.h \
 	vivi_compiler_get_temporary.h \
-	vivi_compiler_goto_name.h \
 	vivi_decompiler.h \
 	vivi_decompiler_block.h \
 	vivi_decompiler_duplicate.h \
diff --git a/vivified/code/vivi_compiler_goto_name.c b/vivified/code/vivi_compiler_goto_name.c
deleted file mode 100644
index e8f5df9..0000000
--- a/vivified/code/vivi_compiler_goto_name.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* 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_compiler_goto_name.h"
-#include "vivi_code_printer.h"
-
-G_DEFINE_TYPE (ViviCompilerGotoName, vivi_compiler_goto_name, VIVI_TYPE_CODE_GOTO)
-
-static void
-vivi_compiler_goto_name_dispose (GObject *object)
-{
-  ViviCompilerGotoName *goto_ = VIVI_COMPILER_GOTO_NAME (object);
-
-  g_free (goto_->name);
-
-  G_OBJECT_CLASS (vivi_compiler_goto_name_parent_class)->dispose (object);
-}
-
-static void
-vivi_compiler_goto_name_print (ViviCodeToken *token, ViviCodePrinter *printer)
-{
-  ViviCompilerGotoName *goto_ = VIVI_COMPILER_GOTO_NAME (token);
-
-  if (VIVI_CODE_GOTO (goto_)->label != NULL) {
-    VIVI_CODE_TOKEN_CLASS (vivi_compiler_goto_name_parent_class)->print (token,
-	printer);
-    return;
-  }
-
-  vivi_code_printer_print (printer, "goto ");
-  vivi_code_printer_print (printer, goto_->name);
-  vivi_code_printer_print (printer, ";");
-  vivi_code_printer_new_line (printer, FALSE);
-}
-
-static void
-vivi_compiler_goto_name_class_init (ViviCompilerGotoNameClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
-
-  object_class->dispose = vivi_compiler_goto_name_dispose;
-
-  token_class->print = vivi_compiler_goto_name_print;
-}
-
-static void
-vivi_compiler_goto_name_init (ViviCompilerGotoName *token)
-{
-}
-
-const char *
-vivi_compiler_goto_name_get_name (ViviCompilerGotoName *goto_)
-{
-  g_return_val_if_fail (VIVI_IS_COMPILER_GOTO_NAME (goto_), NULL);
-
-  return goto_->name;
-}
-
-void
-vivi_compiler_goto_name_set_label (ViviCompilerGotoName *goto_,
-    ViviCodeLabel *label)
-{
-  g_return_if_fail (VIVI_IS_COMPILER_GOTO_NAME (goto_));
-  g_return_if_fail (VIVI_IS_CODE_LABEL (label));
-
-  VIVI_CODE_GOTO (goto_)->label = g_object_ref (label);
-}
-
-ViviCodeStatement *
-vivi_compiler_goto_name_new (const char *name)
-{
-  ViviCompilerGotoName *goto_;
-
-  g_return_val_if_fail (name != NULL, NULL);
-
-  goto_ = g_object_new (VIVI_TYPE_COMPILER_GOTO_NAME, NULL);
-  goto_->name = g_strdup (name);
-
-  return VIVI_CODE_STATEMENT (goto_);
-}
diff --git a/vivified/code/vivi_compiler_goto_name.h b/vivified/code/vivi_compiler_goto_name.h
deleted file mode 100644
index 7c92983..0000000
--- a/vivified/code/vivi_compiler_goto_name.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* 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_COMPILER_GOTO_NAME_H_
-#define _VIVI_COMPILER_GOTO_NAME_H_
-
-#include <vivified/code/vivi_code_goto.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _ViviCompilerGotoName ViviCompilerGotoName;
-typedef struct _ViviCompilerGotoNameClass ViviCompilerGotoNameClass;
-
-#define VIVI_TYPE_COMPILER_GOTO_NAME                    (vivi_compiler_goto_name_get_type())
-#define VIVI_IS_COMPILER_GOTO_NAME(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_COMPILER_GOTO_NAME))
-#define VIVI_IS_COMPILER_GOTO_NAME_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_COMPILER_GOTO_NAME))
-#define VIVI_COMPILER_GOTO_NAME(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_COMPILER_GOTO_NAME, ViviCompilerGotoName))
-#define VIVI_COMPILER_GOTO_NAME_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_COMPILER_GOTO_NAME, ViviCompilerGotoNameClass))
-#define VIVI_COMPILER_GOTO_NAME_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_COMPILER_GOTO_NAME, ViviCompilerGotoNameClass))
-
-struct _ViviCompilerGotoName
-{
-  ViviCodeGoto		statement;
-
-  char *		name;
-};
-
-struct _ViviCompilerGotoNameClass
-{
-  ViviCodeGotoClass	statement_class;
-};
-
-GType			vivi_compiler_goto_name_get_type	(void);
-
-ViviCodeStatement *	vivi_compiler_goto_name_new		(const char *		name);
-const char *		vivi_compiler_goto_name_get_name	(ViviCompilerGotoName *	goto_);
-void			vivi_compiler_goto_name_set_label	(ViviCompilerGotoName *	goto_,
-								 ViviCodeLabel *	label);
-
-
-G_END_DECLS
-#endif
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 9771d86..65565df 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -69,7 +69,6 @@
 #include "vivi_code_variable.h"
 #include "vivi_compiler_empty_statement.h"
 #include "vivi_compiler_get_temporary.h"
-#include "vivi_compiler_goto_name.h"
 
 #include "vivi_code_text_printer.h"
 #include "vivi_code_assembler.h"
@@ -108,7 +107,7 @@ static const struct {
 
 typedef struct {
   GSList			*labels;
-  GSList			*gotos;
+  GSList			*waiting_labels;
 } ParseLevel;
 
 typedef struct {
@@ -372,20 +371,53 @@ vivi_parser_start_level (ParseData *data)
 }
 
 static ViviCodeLabel *
-vivi_parser_find_label (ParseData *data, const char *name)
+vivi_parser_get_waiting_label (ParseData *data, const char *name)
 {
   GSList *iter;
 
-  for (iter = data->level->labels; iter != NULL; iter = iter->next) {
-    if (g_str_equal (vivi_code_label_get_name (VIVI_CODE_LABEL (iter->data)),
-	  name))
-      return VIVI_CODE_LABEL (iter->data);
+  g_return_val_if_fail (data != NULL, NULL);
+  g_return_val_if_fail (data->level != NULL, NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  for (iter = data->level->waiting_labels; iter != NULL; iter = iter->next) {
+    ViviCodeLabel *label = VIVI_CODE_LABEL (iter->data);
+    if (g_str_equal (vivi_code_label_get_name (label), name))
+      return label;
   }
 
   return NULL;
 }
 
 static void
+vivi_parser_remove_waiting_label (ParseData *data, const ViviCodeLabel *label)
+{
+  g_return_if_fail (data != NULL);
+  g_return_if_fail (data->level != NULL);
+  g_return_if_fail (VIVI_IS_CODE_LABEL (label));
+
+  data->level->waiting_labels =
+    g_slist_remove (data->level->waiting_labels, label);
+}
+
+static ViviCodeLabel *
+vivi_parser_get_label (ParseData *data, const char *name)
+{
+  GSList *iter;
+
+  g_return_val_if_fail (data != NULL, NULL);
+  g_return_val_if_fail (data->level != NULL, NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  for (iter = data->level->labels; iter != NULL; iter = iter->next) {
+    ViviCodeLabel *label = VIVI_CODE_LABEL (iter->data);
+    if (g_str_equal (vivi_code_label_get_name (label), name))
+      return label;
+  }
+
+  return vivi_parser_get_waiting_label (data, name);
+}
+
+static void
 vivi_parser_end_level (ParseData *data)
 {
   GSList *iter;
@@ -393,24 +425,15 @@ vivi_parser_end_level (ParseData *data)
   g_return_if_fail (data != NULL);
   g_return_if_fail (data->level != NULL);
 
-  for (iter = data->level->gotos; iter != NULL; iter = iter->next) {
-    ViviCompilerGotoName *goto_;
-    ViviCodeLabel *label;
-
-    goto_ = VIVI_COMPILER_GOTO_NAME (iter->data);
-    label = vivi_parser_find_label (data,
-	vivi_compiler_goto_name_get_name (goto_));
+  for (iter = data->level->waiting_labels; iter != NULL; iter = iter->next) {
+    ViviCodeLabel *label = VIVI_CODE_LABEL (iter->data);
 
-    if (label != NULL) {
-      vivi_compiler_goto_name_set_label (goto_, label);
-    } else {
-      vivi_parser_error (data, "Label named '%s' doesn't exist in this block",
-	  vivi_compiler_goto_name_get_name (goto_));
-    }
+    vivi_parser_error (data, "Label named '%s' doesn't exist in this block",
+	vivi_code_label_get_name (label));
 
-    g_object_unref (goto_);
+    g_object_unref (label);
   }
-  g_slist_free (data->level->gotos);
+  g_slist_free (data->level->waiting_labels);
 
   for (iter = data->level->labels; iter != NULL; iter = iter->next) {
     g_object_unref (VIVI_CODE_LABEL (iter->data));
@@ -427,31 +450,15 @@ vivi_parser_end_level (ParseData *data)
   }
 }
 
-static void
-vivi_parser_add_goto (ParseData *data, ViviCompilerGotoName *goto_)
-{
-  g_return_if_fail (data != NULL);
-  g_return_if_fail (data->level != NULL);
-  g_return_if_fail (VIVI_IS_COMPILER_GOTO_NAME (goto_));
-
-  data->level->gotos =
-    g_slist_prepend (data->level->gotos, g_object_ref (goto_));
-}
-
 static gboolean
 vivi_parser_add_label (ParseData *data, ViviCodeLabel *label)
 {
-  GSList *iter;
-
   g_return_val_if_fail (data != NULL, FALSE);
   g_return_val_if_fail (data->level != NULL, FALSE);
   g_return_val_if_fail (VIVI_IS_CODE_LABEL (label), FALSE);
 
-  for (iter = data->level->labels; iter != NULL; iter = iter->next) {
-    if (g_str_equal (vivi_code_label_get_name (VIVI_CODE_LABEL (iter->data)),
-	  vivi_code_label_get_name (label)))
+  if (vivi_parser_get_label (data, vivi_code_label_get_name (label)) != NULL)
       return FALSE;
-  }
 
   data->level->labels =
     g_slist_prepend (data->level->labels, g_object_ref (label));
@@ -459,6 +466,19 @@ vivi_parser_add_label (ParseData *data, ViviCodeLabel *label)
   return TRUE;
 }
 
+static void
+vivi_parser_add_waiting_label (ParseData *data, ViviCodeLabel *label)
+{
+  g_return_if_fail (data != NULL);
+  g_return_if_fail (data->level != NULL);
+  g_return_if_fail (VIVI_IS_CODE_LABEL (label));
+  g_return_if_fail (vivi_parser_get_waiting_label (data,
+	vivi_code_label_get_name (label)));
+
+  data->level->labels =
+    g_slist_prepend (data->level->waiting_labels, g_object_ref (label));
+}
+
 static gsize
 vivi_parser_get_position (ParseData *data)
 {
@@ -1142,9 +1162,18 @@ parse_asm_code (ParseData *data)
   }
 
   if (try_parse_token (data, TOKEN_COLON)) {
-    ViviCodeAsm *code = VIVI_CODE_ASM (vivi_code_label_new (identifier));
+    ViviCodeLabel *label;
+
+    label = vivi_parser_get_waiting_label (data, identifier);
+    if (label != NULL) {
+      vivi_parser_remove_waiting_label (data, label);
+    } else {
+      label = VIVI_CODE_LABEL (vivi_code_label_new (identifier));
+    }
+    vivi_parser_add_label (data, label);
+
     g_free (identifier);
-    return code;
+    return VIVI_CODE_ASM (label);
   } else {
     for (i = 0; i < G_N_ELEMENTS (asm_statements); i++) {
       if (g_ascii_strcasecmp (identifier, asm_statements[i].name) == 0)
@@ -2322,9 +2351,15 @@ parse_continue_or_break_statement (ParseData *data,
   parse_token (data, token);
 
   if (!try_parse_restricted_semicolon (data)) {
-    statement = vivi_compiler_goto_name_new (parse_identifier_value (data));
+    ViviCodeLabel *label;
+    const char *name = parse_identifier_value (data);
 
-    vivi_parser_add_goto (data, VIVI_COMPILER_GOTO_NAME (statement));
+    label = vivi_parser_get_label (data, name);
+    if (label == NULL) {
+      label = VIVI_CODE_LABEL (vivi_code_label_new (name));
+      vivi_parser_add_waiting_label (data, label);
+    }
+    statement = vivi_code_goto_new (label);
 
     parse_automatic_semicolon (data);
   } else {
@@ -2689,16 +2724,24 @@ peek_label_statement (ParseData *data)
 static ViviCodeStatement *
 parse_label_statement (ParseData *data)
 {
-  ViviCodeStatement *statement;
+  ViviCodeLabel *label;
+  const char *name;
 
-  statement = vivi_code_label_new (parse_identifier_value (data));
+  name = parse_identifier_value (data);
+
+  label = vivi_parser_get_waiting_label (data, name);
+  if (label != NULL) {
+    vivi_parser_remove_waiting_label (data, label);
+  } else {
+    label = VIVI_CODE_LABEL (vivi_code_label_new (name));
+  }
 
   parse_token (data, TOKEN_COLON);
 
-  if (!vivi_parser_add_label (data, VIVI_CODE_LABEL (statement)))
+  if (!vivi_parser_add_label (data, label))
     vivi_parser_error (data, "Same label name used twice");
 
-  return statement;
+  return VIVI_CODE_STATEMENT (label);
 }
 
 static gboolean
commit cec3934b110c9a2e4df74e82d55742b168963045
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 14:12:36 2008 +0300

    Implement the parsing of asm store statement. Add test

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 7a03c86..ea9b63c 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -30,6 +30,8 @@ EXTRA_DIST = \
 	asm_label.as.expect \
 	asm_push.as \
 	asm_push.as.expect \
+	asm_store.as \
+	asm_store.as.expect \
 	assignment.as \
 	assignment.as.expect \
 	assignment_member.as \
diff --git a/vivified/code/test/compiler/asm_store.as b/vivified/code/test/compiler/asm_store.as
new file mode 100644
index 0000000..7303508
--- /dev/null
+++ b/vivified/code/test/compiler/asm_store.as
@@ -0,0 +1,3 @@
+asm {
+  store 0
+}
diff --git a/vivified/code/test/compiler/asm_store.as.expect b/vivified/code/test/compiler/asm_store.as.expect
new file mode 100644
index 0000000..fee9bc4
--- /dev/null
+++ b/vivified/code/test/compiler/asm_store.as.expect
@@ -0,0 +1,4 @@
+asm {
+  store 0
+  end
+}
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index a6961df..9771d86 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -31,6 +31,7 @@
 #include "vivi_code_and.h"
 #include "vivi_code_asm_code_default.h"
 #include "vivi_code_asm_push.h"
+#include "vivi_code_asm_store.h"
 #include "vivi_code_assignment.h"
 #include "vivi_code_binary_default.h"
 #include "vivi_code_block.h"
@@ -967,6 +968,23 @@ parse_variable_declaration (ParseData *data)
 // asm functions
 
 static ViviCodeAsm *
+parse_asm_store (ParseData *data)
+{
+  int id;
+
+  // TODO: error/warn if not an integer
+  id = swfdec_as_double_to_integer (parse_numeric_value (data));
+  if (id < 0 || id >= 256) {
+    vivi_parser_error (data, "Invalid register number: %i", id);
+    id = 0;
+  }
+
+  parse_automatic_semicolon (data);
+
+  return vivi_code_asm_store_new (id);
+}
+
+static ViviCodeAsm *
 parse_asm_push (ParseData *data)
 {
   ViviCodeAsmPush *push;
@@ -1078,7 +1096,8 @@ static const AsmStatement asm_statements[] = {
   { G_STRINGIFY (underscore_name), vivi_code_asm_ ## underscore_name ## _new, NULL },
 #include "vivi_code_defaults.h"
 #undef DEFAULT_ASM
-  { "push", NULL, parse_asm_push }
+  { "push", NULL, parse_asm_push },
+  { "store", NULL, parse_asm_store }
 };
 #if 0
 DEFAULT_ASM (GotoFrame, goto_frame, SWFDEC_AS_ACTION_GOTO_FRAME)
commit 49d5eb44e0e28d2d621d21534972071a3178dacc
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 13:47:55 2008 +0300

    Add a vivi-compile test for automatic semicolons

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index 24bdaba..7a03c86 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -40,6 +40,8 @@ EXTRA_DIST = \
 	assignment_operator.as.expect \
 	assignment_value.as \
 	assignment_value.as.expect \
+	automatic_semicolon.as \
+	automatic_semicolon.as.expect \
 	builtin_statement.as \
 	builtin_statement.as.expect \
 	call_function.as \
diff --git a/vivified/code/test/compiler/automatic_semicolon.as b/vivified/code/test/compiler/automatic_semicolon.as
new file mode 100644
index 0000000..6351134
--- /dev/null
+++ b/vivified/code/test/compiler/automatic_semicolon.as
@@ -0,0 +1,2 @@
+stop () { play ()
+} stop ()
\ No newline at end of file
diff --git a/vivified/code/test/compiler/automatic_semicolon.as.expect b/vivified/code/test/compiler/automatic_semicolon.as.expect
new file mode 100644
index 0000000..7324911
--- /dev/null
+++ b/vivified/code/test/compiler/automatic_semicolon.as.expect
@@ -0,0 +1,6 @@
+asm {
+  stop
+  play
+  stop
+  end
+}
commit 55e9e5737ac5aa4548d9bb572db457c0fa9134f4
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 13:28:47 2008 +0300

    Add combine push test for vivi-compile to make sure that label stops combining

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index dd3513a..24bdaba 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -44,6 +44,8 @@ EXTRA_DIST = \
 	builtin_statement.as.expect \
 	call_function.as \
 	call_function.as.expect \
+	combine_push.as \
+	combine_push.as.expect \
 	comment.as \
 	comment.as.expect \
 	conditional.as \
diff --git a/vivified/code/test/compiler/combine_push.as b/vivified/code/test/compiler/combine_push.as
new file mode 100644
index 0000000..fb90ee8
--- /dev/null
+++ b/vivified/code/test/compiler/combine_push.as
@@ -0,0 +1,5 @@
+trace ("a");
+trace ("b");
+hello:
+trace ("a");
+trace ("b");
diff --git a/vivified/code/test/compiler/combine_push.as.expect b/vivified/code/test/compiler/combine_push.as.expect
new file mode 100644
index 0000000..b8a5fc0
--- /dev/null
+++ b/vivified/code/test/compiler/combine_push.as.expect
@@ -0,0 +1,12 @@
+asm {
+  pool "a", "b"
+  push pool 1, pool 0
+  trace
+  trace
+
+hello_0001:
+  push pool 1, pool 0
+  trace
+  trace
+  end
+}
commit efdbb4b1e130a3b12c600111a90bc7b2ef0a427b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 13:20:50 2008 +0300

    Add vivi-compile tests for different literals

diff --git a/vivified/code/test/compiler/Makefile.am b/vivified/code/test/compiler/Makefile.am
index d979ea0..dd3513a 100644
--- a/vivified/code/test/compiler/Makefile.am
+++ b/vivified/code/test/compiler/Makefile.am
@@ -86,6 +86,10 @@ EXTRA_DIST = \
 	increment_value.as.expect \
 	label.as \
 	label.as.expect \
+	misc_literal.as \
+	misc_literal.as.expect \
+	number.as \
+	number.as.expect \
 	operator.as \
 	operator.as.expect \
 	operator_precedence.as \
@@ -96,6 +100,8 @@ EXTRA_DIST = \
 	object_literal_empty.as.expect \
 	or.as \
 	or.as.expect \
+	string.as \
+	string.as.expect \
 	trace.as \
 	trace.as.expect \
 	var.as \
diff --git a/vivified/code/test/compiler/misc_literal.as b/vivified/code/test/compiler/misc_literal.as
new file mode 100644
index 0000000..3799c79
--- /dev/null
+++ b/vivified/code/test/compiler/misc_literal.as
@@ -0,0 +1,4 @@
+trace (null);
+trace (undefined);
+trace (true);
+trace (false);
diff --git a/vivified/code/test/compiler/misc_literal.as.expect b/vivified/code/test/compiler/misc_literal.as.expect
new file mode 100644
index 0000000..4433821
--- /dev/null
+++ b/vivified/code/test/compiler/misc_literal.as.expect
@@ -0,0 +1,8 @@
+asm {
+  push false, true, undefined, null
+  trace
+  trace
+  trace
+  trace
+  end
+}
diff --git a/vivified/code/test/compiler/number.as b/vivified/code/test/compiler/number.as
new file mode 100644
index 0000000..a8a9190
--- /dev/null
+++ b/vivified/code/test/compiler/number.as
@@ -0,0 +1,10 @@
+trace (1);
+trace (3.5);
+trace (5e3);
+trace (-2);
+trace (3.5e7);
+trace (-5e3);
+trace (-3.5e7);
+trace (5e3);
+trace (.5e7);
+trace (-.5e7);
diff --git a/vivified/code/test/compiler/number.as.expect b/vivified/code/test/compiler/number.as.expect
new file mode 100644
index 0000000..a2fe314
--- /dev/null
+++ b/vivified/code/test/compiler/number.as.expect
@@ -0,0 +1,14 @@
+asm {
+  push -5000000, 5000000, 5000, -35000000, -5000, 35000000, -2, 5000, 3.5, 1
+  trace
+  trace
+  trace
+  trace
+  trace
+  trace
+  trace
+  trace
+  trace
+  trace
+  end
+}
diff --git a/vivified/code/test/compiler/string.as b/vivified/code/test/compiler/string.as
new file mode 100644
index 0000000..a28cd81
--- /dev/null
+++ b/vivified/code/test/compiler/string.as
@@ -0,0 +1,8 @@
+trace ("'Hello, world!'");
+trace ('"Hello, world!"');
+trace ("\"");
+trace ('\'');
+trace ("\x48");
+trace ("\123");
+trace ("\u2208");
+trace ("\n\r\b\f\n\r\t\v");
diff --git a/vivified/code/test/compiler/string.as.expect b/vivified/code/test/compiler/string.as.expect
new file mode 100644
index 0000000..9bedbe2
--- /dev/null
+++ b/vivified/code/test/compiler/string.as.expect
@@ -0,0 +1,13 @@
+asm {
+  pool "'Hello, world!'", "\"Hello, world!\"", "\"", "'", "H", "S", "∈", "\n\r\b\f\n\r\t\v"
+  push pool 7, pool 6, pool 5, pool 4, pool 3, pool 2, pool 1, pool 0
+  trace
+  trace
+  trace
+  trace
+  trace
+  trace
+  trace
+  trace
+  end
+}
commit 482b8ade497d65f6e6c53e7484850d9fe656429c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu May 22 13:15:16 2008 +0300

    Enable the merging of pushes over asm statements that take values from stack
    
    Fix test cases accordingly

diff --git a/vivified/code/test/compiler/assignment_member_value.as.expect b/vivified/code/test/compiler/assignment_member_value.as.expect
index 1445ed3..07e0e24 100644
--- a/vivified/code/test/compiler/assignment_member_value.as.expect
+++ b/vivified/code/test/compiler/assignment_member_value.as.expect
@@ -5,9 +5,8 @@ asm {
   push pool 1, 1
   store 0
   set_member
-  push reg 0
+  push pool 0, reg 0
   trace
-  push pool 0
   get_variable
   push pool 1
   get_variable
diff --git a/vivified/code/test/compiler/increment_member_value.as.expect b/vivified/code/test/compiler/increment_member_value.as.expect
index ca70c78..4458558 100644
--- a/vivified/code/test/compiler/increment_member_value.as.expect
+++ b/vivified/code/test/compiler/increment_member_value.as.expect
@@ -10,9 +10,8 @@ asm {
   store 0
   increment
   set_member
-  push reg 0
+  push pool 1, reg 0
   trace
-  push pool 1
   get_variable
   push pool 0
   get_variable
@@ -25,9 +24,8 @@ asm {
   store 0
   increment
   set_member
-  push reg 0
+  push pool 0, reg 0
   trace
-  push pool 0
   get_variable
   push_duplicate
   push pool 1
@@ -37,9 +35,8 @@ asm {
   increment
   store 0
   set_member
-  push reg 0
+  push pool 1, reg 0
   trace
-  push pool 1
   get_variable
   push pool 0
   get_variable
diff --git a/vivified/code/test/compiler/var.as.expect b/vivified/code/test/compiler/var.as.expect
index 961a71b..3cf3447 100644
--- a/vivified/code/test/compiler/var.as.expect
+++ b/vivified/code/test/compiler/var.as.expect
@@ -1,10 +1,8 @@
 asm {
   pool "a", "b", "c"
-  push pool 0
+  push pool 2, undefined, pool 1, 1, pool 0
   define_local2
-  push pool 1, 1
   define_local
-  push pool 2, undefined
   define_local
   end
 }
diff --git a/vivified/code/vivi_code_compiler.c b/vivified/code/vivi_code_compiler.c
index a25ded0..343992a 100644
--- a/vivified/code/vivi_code_compiler.c
+++ b/vivified/code/vivi_code_compiler.c
@@ -85,7 +85,7 @@ vivi_code_compiler_compile_script (ViviCodeCompiler *compiler,
   vivi_code_compiler_take_code (compiler, vivi_code_asm_end_new ());
 
   vivi_code_assembler_pool (compiler->assembler);
-  vivi_code_assembler_merge_push (compiler->assembler, 0);
+  vivi_code_assembler_merge_push (compiler->assembler, G_MAXUINT);
 }
 
 void


More information about the Swfdec-commits mailing list