[Swfdec-commits] 2 commits - vivified/code

Benjamin Otte company at kemper.freedesktop.org
Thu Apr 17 11:13:54 PDT 2008


 vivified/code/Makefile.am                   |   12 +
 vivified/code/vivi_code_asm.h               |    6 
 vivified/code/vivi_code_asm_code_default.c  |    5 
 vivified/code/vivi_code_asm_code_default.h  |    4 
 vivified/code/vivi_code_assignment.c        |   11 -
 vivified/code/vivi_code_boolean.c           |   79 +++++++++
 vivified/code/vivi_code_boolean.h           |   58 ++++++
 vivified/code/vivi_code_constant.c          |  242 ----------------------------
 vivified/code/vivi_code_constant.h          |   16 -
 vivified/code/vivi_code_emitter.c           |  150 +++++++++++++++++
 vivified/code/vivi_code_emitter.h           |   76 ++++++++
 vivified/code/vivi_code_function_call.c     |    6 
 vivified/code/vivi_code_get.c               |    6 
 vivified/code/vivi_code_init_array.c        |   11 -
 vivified/code/vivi_code_null.c              |   66 +++++++
 vivified/code/vivi_code_null.h              |   54 ++++++
 vivified/code/vivi_code_number.c            |   71 ++++++++
 vivified/code/vivi_code_number.h            |   58 ++++++
 vivified/code/vivi_code_string.c            |  150 +++++++++++++++++
 vivified/code/vivi_code_string.h            |   58 ++++++
 vivified/code/vivi_code_undefined.c         |   66 +++++++
 vivified/code/vivi_code_undefined.h         |   54 ++++++
 vivified/code/vivi_compiler_get_temporary.c |    4 
 vivified/code/vivi_decompiler.c             |   41 ++--
 vivified/code/vivi_decompiler_block.c       |    4 
 vivified/code/vivi_decompiler_state.c       |    6 
 vivified/code/vivi_parser.c                 |   53 +++---
 27 files changed, 1047 insertions(+), 320 deletions(-)

New commits:
commit 3aca0af237d694345aa78379a05e9a671f455fc2
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 20:06:12 2008 +0200

    split the constant class
    
    Now there's a seperate class for Number, Boolean, String, Null and Undefined

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index ec268b2..5819543 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -25,6 +25,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_binary.c \
 	vivi_code_binary_default.c \
 	vivi_code_block.c \
+	vivi_code_boolean.c \
 	vivi_code_break.c \
 	vivi_code_builtin_call.c \
 	vivi_code_builtin_statement.c \
@@ -50,15 +51,19 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_init_object.c \
 	vivi_code_label.c \
 	vivi_code_loop.c \
+	vivi_code_null.c \
+	vivi_code_number.c \
 	vivi_code_or.c \
 	vivi_code_printer.c \
 	vivi_code_return.c \
 	vivi_code_statement.c \
+	vivi_code_string.c \
 	vivi_code_substring.c \
 	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_value_statement.c \
 	vivi_compiler_empty_statement.c \
@@ -82,6 +87,7 @@ noinst_HEADERS = \
 	vivi_code_binary.h \
 	vivi_code_binary_default.h \
 	vivi_code_block.h \
+	vivi_code_boolean.h \
 	vivi_code_break.h \
 	vivi_code_builtin_call.h \
 	vivi_code_builtin_statement.h \
@@ -108,15 +114,19 @@ noinst_HEADERS = \
 	vivi_code_init_object.h \
 	vivi_code_label.h \
 	vivi_code_loop.h \
+	vivi_code_null.h \
+	vivi_code_number.h \
 	vivi_code_or.h \
 	vivi_code_printer.h \
 	vivi_code_return.h \
 	vivi_code_statement.h \
+	vivi_code_string.h \
 	vivi_code_substring.h \
 	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_value_statement.h \
 	vivi_compiler_empty_statement.h \
diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index 1045031..e16367b 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -22,10 +22,11 @@
 #endif
 
 #include "vivi_code_assignment.h"
-#include "vivi_code_constant.h"
+#include "vivi_code_compiler.h"
 #include "vivi_code_get.h"
 #include "vivi_code_printer.h"
-#include "vivi_code_compiler.h"
+#include "vivi_code_string.h"
+#include "vivi_code_undefined.h"
 
 G_DEFINE_TYPE (ViviCodeAssignment, vivi_code_assignment, VIVI_TYPE_CODE_STATEMENT)
 
@@ -79,9 +80,7 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
       goto finalize;
     }
   }
-  if (!assignment->local || !VIVI_IS_CODE_CONSTANT (assignment->value) ||
-      vivi_code_constant_get_value_type (
-	VIVI_CODE_CONSTANT (assignment->value)) != SWFDEC_AS_TYPE_UNDEFINED) {
+  if (!assignment->local || !VIVI_IS_CODE_UNDEFINED (assignment->value)) {
     vivi_code_printer_print (printer, " = ");
     vivi_code_printer_print_value (printer, assignment->value, VIVI_PRECEDENCE_ASSIGNMENT);
   }
@@ -165,7 +164,7 @@ vivi_code_assignment_new_name (const char *name, ViviCodeValue *value)
   g_return_val_if_fail (name != NULL, NULL);
   g_return_val_if_fail (VIVI_IS_CODE_VALUE (value), NULL);
 
-  constant = vivi_code_constant_new_string (name);
+  constant = vivi_code_string_new (name);
   result = vivi_code_assignment_new (NULL, constant, value);
   g_object_unref (constant);
   return result;
diff --git a/vivified/code/vivi_code_boolean.c b/vivified/code/vivi_code_boolean.c
new file mode 100644
index 0000000..5076cf7
--- /dev/null
+++ b/vivified/code/vivi_code_boolean.c
@@ -0,0 +1,79 @@
+/* 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_boolean.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCodeBoolean, vivi_code_boolean, VIVI_TYPE_CODE_CONSTANT)
+
+static void
+vivi_code_boolean_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  ViviCodeBoolean *b = VIVI_CODE_BOOLEAN (token);
+
+  vivi_code_printer_print (printer, b->value ? "true" : "false");
+}
+
+static char *
+vivi_code_boolean_get_variable_name (ViviCodeConstant *constant)
+{
+  ViviCodeBoolean *b = VIVI_CODE_BOOLEAN (constant);
+
+  return g_strdup (b->value ? "true" : "false");
+}
+
+static void
+vivi_code_boolean_class_init (ViviCodeBooleanClass *klass)
+{
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeConstantClass *constant_class = VIVI_CODE_CONSTANT_CLASS (klass);
+
+  token_class->print = vivi_code_boolean_print;
+
+  constant_class->get_variable_name = vivi_code_boolean_get_variable_name;
+}
+
+static void
+vivi_code_boolean_init (ViviCodeBoolean *boolean)
+{
+}
+
+ViviCodeValue *
+vivi_code_boolean_new (gboolean value)
+{
+  ViviCodeBoolean *b;
+
+  b = g_object_new (VIVI_TYPE_CODE_BOOLEAN, NULL);
+  b->value = value;
+
+  return VIVI_CODE_VALUE (b);
+}
+
+gboolean
+vivi_code_boolean_get_value (ViviCodeBoolean *b)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_BOOLEAN (b), FALSE);
+
+  return b->value;
+}
+
diff --git a/vivified/code/vivi_code_boolean.h b/vivified/code/vivi_code_boolean.h
new file mode 100644
index 0000000..0e27729
--- /dev/null
+++ b/vivified/code/vivi_code_boolean.h
@@ -0,0 +1,58 @@
+/* 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_BOOLEAN_H_
+#define _VIVI_CODE_BOOLEAN_H_
+
+#include <vivified/code/vivi_code_constant.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeBoolean ViviCodeBoolean;
+typedef struct _ViviCodeBooleanClass ViviCodeBooleanClass;
+
+#define VIVI_TYPE_CODE_BOOLEAN                    (vivi_code_boolean_get_type())
+#define VIVI_IS_CODE_BOOLEAN(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_BOOLEAN))
+#define VIVI_IS_CODE_BOOLEAN_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_BOOLEAN))
+#define VIVI_CODE_BOOLEAN(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_BOOLEAN, ViviCodeBoolean))
+#define VIVI_CODE_BOOLEAN_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_BOOLEAN, ViviCodeBooleanClass))
+#define VIVI_CODE_BOOLEAN_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_BOOLEAN, ViviCodeBooleanClass))
+
+struct _ViviCodeBoolean
+{
+  ViviCodeConstant	constant;
+
+  gboolean		value;
+};
+
+struct _ViviCodeBooleanClass
+{
+  ViviCodeConstantClass constant_class;
+};
+
+GType			vivi_code_boolean_get_type   	(void);
+
+ViviCodeValue *		vivi_code_boolean_new		(gboolean		value);
+
+gboolean		vivi_code_boolean_get_value	(ViviCodeBoolean *	b);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_code_constant.c b/vivified/code/vivi_code_constant.c
index 5fd6519..f7e2211 100644
--- a/vivified/code/vivi_code_constant.c
+++ b/vivified/code/vivi_code_constant.c
@@ -29,133 +29,7 @@
 #include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
 
-G_DEFINE_TYPE (ViviCodeConstant, vivi_code_constant, VIVI_TYPE_CODE_VALUE)
-
-static void
-vivi_code_constant_dispose (GObject *object)
-{
-  ViviCodeConstant *constant = VIVI_CODE_CONSTANT (object);
-
-  if (SWFDEC_AS_VALUE_IS_STRING (&constant->value))
-    g_free ((char *) SWFDEC_AS_VALUE_GET_STRING (&constant->value));
-
-  G_OBJECT_CLASS (vivi_code_constant_parent_class)->dispose (object);
-}
-
-static char *
-escape_string (const char *s)
-{
-  GString *str;
-  char *next;
-
-  str = g_string_new ("\"");
-  while ((next = strpbrk (s, "\"\\\b\f\n\r\t\v"))) {
-    g_string_append_len (str, s, next - s);
-    switch (*next) {
-      case '"':
-	g_string_append (str, "\\\"");
-	break;
-      case '\\':
-	g_string_append (str, "\\\\");
-	break;
-      case '\b':
-	g_string_append (str, "\\b");
-	break;
-      case '\f':
-	g_string_append (str, "\\f");
-	break;
-      case '\n':
-	g_string_append (str, "\\n");
-	break;
-      case '\r':
-	g_string_append (str, "\\r");
-	break;
-      case '\t':
-	g_string_append (str, "\\t");
-	break;
-      case '\v':
-	g_string_append (str, "\\v");
-	break;
-      default:
-	g_assert_not_reached ();
-    }
-    s = next + 1;
-  }
-  g_string_append (str, s);
-  g_string_append_c (str, '"');
-  return g_string_free (str, FALSE);
-}
-
-static void
-vivi_code_constant_print (ViviCodeToken *token, ViviCodePrinter *printer)
-{
-  ViviCodeConstant *constant = VIVI_CODE_CONSTANT (token);
-  char *s;
-
-  switch (constant->value.type) {
-    case SWFDEC_AS_TYPE_UNDEFINED:
-      vivi_code_printer_print (printer, "undefined");
-      break;
-    case SWFDEC_AS_TYPE_NULL:
-      vivi_code_printer_print (printer, "null");
-      break;
-    case SWFDEC_AS_TYPE_BOOLEAN:
-      vivi_code_printer_print (printer, SWFDEC_AS_VALUE_GET_BOOLEAN (&constant->value) ? "true" : "false");
-      break;
-    case SWFDEC_AS_TYPE_NUMBER:
-      s = g_strdup_printf ("%.16g", SWFDEC_AS_VALUE_GET_NUMBER (&constant->value));
-      vivi_code_printer_print (printer, s);
-      g_free (s);
-      break;
-    case SWFDEC_AS_TYPE_STRING:
-      s = escape_string (SWFDEC_AS_VALUE_GET_STRING (&constant->value));
-      vivi_code_printer_print (printer, s);
-      g_free (s);
-      break;
-    case SWFDEC_AS_TYPE_INT:
-    case SWFDEC_AS_TYPE_OBJECT:
-    default:
-      g_assert_not_reached ();
-  }
-}
-
-static void
-vivi_code_constant_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
-{
-  ViviCodeConstant *constant = VIVI_CODE_CONSTANT (token);
-
-  vivi_code_compiler_begin_action (compiler, SWFDEC_AS_ACTION_PUSH);
-
-  switch (constant->value.type) {
-    case SWFDEC_AS_TYPE_UNDEFINED:
-      vivi_code_compiler_write_u8 (compiler, 3);
-      break;
-    case SWFDEC_AS_TYPE_NULL:
-      vivi_code_compiler_write_u8 (compiler, 2);
-      break;
-    case SWFDEC_AS_TYPE_BOOLEAN:
-      vivi_code_compiler_write_u8 (compiler, 5);
-      vivi_code_compiler_write_u8 (compiler,
-	  SWFDEC_AS_VALUE_GET_BOOLEAN (&constant->value));
-      break;
-    case SWFDEC_AS_TYPE_NUMBER:
-      vivi_code_compiler_write_u8 (compiler, 6);
-      vivi_code_compiler_write_double (compiler,
-	  SWFDEC_AS_VALUE_GET_NUMBER (&constant->value));
-      break;
-    case SWFDEC_AS_TYPE_STRING:
-      vivi_code_compiler_write_u8 (compiler, 0);
-      vivi_code_compiler_write_string (compiler,
-	  SWFDEC_AS_VALUE_GET_STRING (&constant->value));
-      break;
-    case SWFDEC_AS_TYPE_INT:
-    case SWFDEC_AS_TYPE_OBJECT:
-    default:
-      g_assert_not_reached ();
-  }
-
-  vivi_code_compiler_end_action (compiler);
-}
+G_DEFINE_ABSTRACT_TYPE (ViviCodeConstant, vivi_code_constant, VIVI_TYPE_CODE_VALUE)
 
 static gboolean
 vivi_code_constant_is_constant (ViviCodeValue *value)
@@ -166,15 +40,8 @@ vivi_code_constant_is_constant (ViviCodeValue *value)
 static void
 vivi_code_constant_class_init (ViviCodeConstantClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
   ViviCodeValueClass *value_class = VIVI_CODE_VALUE_CLASS (klass);
 
-  object_class->dispose = vivi_code_constant_dispose;
-
-  token_class->print = vivi_code_constant_print;
-  token_class->compile = vivi_code_constant_compile;
-
   value_class->is_constant = vivi_code_constant_is_constant;
 }
 
@@ -184,112 +51,17 @@ vivi_code_constant_init (ViviCodeConstant *constant)
   vivi_code_value_set_precedence (VIVI_CODE_VALUE (constant), VIVI_PRECEDENCE_MAX);
 }
 
-static ViviCodeValue *
-vivi_code_constant_new (const SwfdecAsValue *value)
-{
-  ViviCodeConstant *constant;
-
-  constant = g_object_new (VIVI_TYPE_CODE_CONSTANT, NULL);
-  constant->value = *value;
-
-  return VIVI_CODE_VALUE (constant);
-}
-
-ViviCodeValue *
-vivi_code_constant_new_undefined (void)
-{
-  SwfdecAsValue val = { 0, };
-  return vivi_code_constant_new (&val);
-}
-
-ViviCodeValue *
-vivi_code_constant_new_null (void)
-{
-  SwfdecAsValue val;
-
-  SWFDEC_AS_VALUE_SET_NULL (&val);
-  return vivi_code_constant_new (&val);
-}
-
-ViviCodeValue *
-vivi_code_constant_new_string (const char *string)
-{
-  SwfdecAsValue val;
-
-  g_return_val_if_fail (string != NULL, NULL);
-
-  SWFDEC_AS_VALUE_SET_STRING (&val, g_strdup (string));
-  return vivi_code_constant_new (&val);
-}
-
-ViviCodeValue *
-vivi_code_constant_new_number (double number)
-{
-  SwfdecAsValue val;
-
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, number);
-  return vivi_code_constant_new (&val);
-}
-
-ViviCodeValue *
-vivi_code_constant_new_boolean (gboolean boolean)
-{
-  SwfdecAsValue val;
-
-  SWFDEC_AS_VALUE_SET_BOOLEAN (&val, boolean);
-  return vivi_code_constant_new (&val);
-}
-
 char *
 vivi_code_constant_get_variable_name (ViviCodeConstant *constant)
 {
-  static const char *accept = G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_$";
+  ViviCodeConstantClass *klass;
 
   g_return_val_if_fail (VIVI_IS_CODE_CONSTANT (constant), NULL);
 
-  switch (constant->value.type) {
-    case SWFDEC_AS_TYPE_UNDEFINED:
-      return g_strdup ("undefined");
-    case SWFDEC_AS_TYPE_NULL:
-      return g_strdup ("null");
-      break;
-    case SWFDEC_AS_TYPE_BOOLEAN:
-      return g_strdup (SWFDEC_AS_VALUE_GET_BOOLEAN (&constant->value) ? "true" : "false");
-      break;
-    case SWFDEC_AS_TYPE_STRING:
-      {
-	const char *s = SWFDEC_AS_VALUE_GET_STRING (&constant->value);
-	gsize len = strspn (s, accept);
-	if (s[len] == '\0')
-	  return g_strdup (s);
-	else
-	  return NULL;
-      }
-    case SWFDEC_AS_TYPE_NUMBER:
-      return NULL;
-    case SWFDEC_AS_TYPE_INT:
-    case SWFDEC_AS_TYPE_OBJECT:
-    default:
-      g_assert_not_reached ();
-  }
-}
-
-SwfdecAsValueType
-vivi_code_constant_get_value_type (ViviCodeConstant *constant)
-{
-  g_return_val_if_fail (VIVI_IS_CODE_CONSTANT (constant), SWFDEC_AS_TYPE_UNDEFINED);
-
-  return constant->value.type;
-}
+  klass = VIVI_CODE_CONSTANT_GET_CLASS (constant);
+  if (klass->get_variable_name == NULL)
+    return NULL;
 
-double
-vivi_code_constant_get_number (ViviCodeConstant *constant)
-{
-  g_return_val_if_fail (VIVI_IS_CODE_CONSTANT (constant), NAN);
-
-  if (SWFDEC_AS_VALUE_IS_NUMBER (&constant->value))
-    return SWFDEC_AS_VALUE_GET_NUMBER (&constant->value);
-  else
-    return NAN;
-}
+  return klass->get_variable_name (constant);
+};
 
diff --git a/vivified/code/vivi_code_constant.h b/vivified/code/vivi_code_constant.h
index bf46a4b..455ca3d 100644
--- a/vivified/code/vivi_code_constant.h
+++ b/vivified/code/vivi_code_constant.h
@@ -38,30 +38,20 @@ typedef struct _ViviCodeConstantClass ViviCodeConstantClass;
 struct _ViviCodeConstant
 {
   ViviCodeValue		parent;
-
-  SwfdecAsValue		value;
 };
 
 struct _ViviCodeConstantClass
 {
   ViviCodeValueClass  	value_class;
+
+  char *		(* get_variable_name)		(ViviCodeConstant *	constant);
 };
 
 GType			vivi_code_constant_get_type   	(void);
 
-ViviCodeValue *		vivi_code_constant_new_null	(void);
-ViviCodeValue *		vivi_code_constant_new_undefined(void);
-ViviCodeValue *		vivi_code_constant_new_string	(const char *		string);
-#define vivi_code_constant_new_int vivi_code_constant_new_number
-ViviCodeValue *		vivi_code_constant_new_number	(double			number);
-ViviCodeValue *		vivi_code_constant_new_boolean	(gboolean		boolean);
-
 char *			vivi_code_constant_get_variable_name
 							(ViviCodeConstant *	constant);
-SwfdecAsValueType	vivi_code_constant_get_value_type
-							(ViviCodeConstant *	constant);
-double			vivi_code_constant_get_number	(ViviCodeConstant *	constant);
-const char *		vivi_code_constant_get_string	(ViviCodeConstant *	constant);
+
 
 G_END_DECLS
 #endif
diff --git a/vivified/code/vivi_code_function_call.c b/vivified/code/vivi_code_function_call.c
index 2b8b974..14dc4d6 100644
--- a/vivified/code/vivi_code_function_call.c
+++ b/vivified/code/vivi_code_function_call.c
@@ -22,9 +22,9 @@
 #endif
 
 #include "vivi_code_function_call.h"
-#include "vivi_code_constant.h"
-#include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
+#include "vivi_code_number.h"
+#include "vivi_code_printer.h"
 
 G_DEFINE_TYPE (ViviCodeFunctionCall, vivi_code_function_call, VIVI_TYPE_CODE_VALUE)
 
@@ -133,7 +133,7 @@ vivi_code_function_call_compile (ViviCodeToken *token,
     vivi_code_compiler_compile_value (compiler,
 	g_ptr_array_index (call->arguments, i));
   }
-  count = vivi_code_constant_new_number (call->arguments->len);
+  count = vivi_code_number_new (call->arguments->len);
   vivi_code_compiler_compile_value (compiler, count);
   g_object_unref (count);
 
diff --git a/vivified/code/vivi_code_get.c b/vivified/code/vivi_code_get.c
index 787c822..dced1f1 100644
--- a/vivified/code/vivi_code_get.c
+++ b/vivified/code/vivi_code_get.c
@@ -22,9 +22,9 @@
 #endif
 
 #include "vivi_code_get.h"
-#include "vivi_code_constant.h"
-#include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_string.h"
 
 G_DEFINE_TYPE (ViviCodeGet, vivi_code_get, VIVI_TYPE_CODE_VALUE)
 
@@ -157,7 +157,7 @@ vivi_code_get_new_name (const char *name)
 
   g_return_val_if_fail (name != NULL, NULL);
 
-  constant = vivi_code_constant_new_string (name);
+  constant = vivi_code_string_new (name);
   result = vivi_code_get_new (NULL, constant);
   g_object_unref (constant);
   return result;
diff --git a/vivified/code/vivi_code_init_array.c b/vivified/code/vivi_code_init_array.c
index ec73801..e61522f 100644
--- a/vivified/code/vivi_code_init_array.c
+++ b/vivified/code/vivi_code_init_array.c
@@ -23,9 +23,10 @@
 #endif
 
 #include "vivi_code_init_array.h"
-#include "vivi_code_constant.h"
-#include "vivi_code_printer.h"
 #include "vivi_code_compiler.h"
+#include "vivi_code_number.h"
+#include "vivi_code_printer.h"
+#include "vivi_code_undefined.h"
 
 G_DEFINE_TYPE (ViviCodeInitArray, vivi_code_init_array, VIVI_TYPE_CODE_VALUE)
 
@@ -71,9 +72,7 @@ vivi_code_init_array_print (ViviCodeToken *token, ViviCodePrinter *printer)
       vivi_code_printer_print (printer, ", ");
     /* FIXME: precedences? */
     // don't write undefined values
-    if (!VIVI_IS_CODE_CONSTANT (value) ||
-	vivi_code_constant_get_value_type (VIVI_CODE_CONSTANT (value))
-	!= SWFDEC_AS_TYPE_UNDEFINED)
+    if (!VIVI_IS_CODE_UNDEFINED (value))
       vivi_code_printer_print_value (printer, value, VIVI_PRECEDENCE_COMMA);
   }
   vivi_code_printer_print (printer, "]");
@@ -90,7 +89,7 @@ vivi_code_init_array_compile (ViviCodeToken *token, ViviCodeCompiler *compiler)
     vivi_code_compiler_compile_value (compiler,
 	VIVI_CODE_VALUE (g_ptr_array_index (array->variables, i)));
   }
-  count = vivi_code_constant_new_number (array->variables->len);
+  count = vivi_code_number_new (array->variables->len);
   vivi_code_compiler_compile_value (compiler, count);
   g_object_unref (count);
 
diff --git a/vivified/code/vivi_code_null.c b/vivified/code/vivi_code_null.c
new file mode 100644
index 0000000..322e5d7
--- /dev/null
+++ b/vivified/code/vivi_code_null.c
@@ -0,0 +1,66 @@
+/* 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 <ctype.h>
+#include <math.h>
+#include <string.h>
+
+#include "vivi_code_null.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCodeNull, vivi_code_null, VIVI_TYPE_CODE_CONSTANT)
+
+static void
+vivi_code_null_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  vivi_code_printer_print (printer, "null");
+}
+
+static char *
+vivi_code_null_get_variable_name (ViviCodeConstant *constant)
+{
+  return g_strdup ("null");
+}
+
+static void
+vivi_code_null_class_init (ViviCodeNullClass *klass)
+{
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeConstantClass *constant_class = VIVI_CODE_CONSTANT_CLASS (klass);
+
+  token_class->print = vivi_code_null_print;
+
+  constant_class->get_variable_name = vivi_code_null_get_variable_name;
+}
+
+static void
+vivi_code_null_init (ViviCodeNull *null)
+{
+}
+
+ViviCodeValue *
+vivi_code_null_new (void)
+{
+  return g_object_new (VIVI_TYPE_CODE_NULL, NULL);
+}
+
diff --git a/vivified/code/vivi_code_null.h b/vivified/code/vivi_code_null.h
new file mode 100644
index 0000000..c16b924
--- /dev/null
+++ b/vivified/code/vivi_code_null.h
@@ -0,0 +1,54 @@
+/* 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_NULL_H_
+#define _VIVI_CODE_NULL_H_
+
+#include <vivified/code/vivi_code_constant.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeNull ViviCodeNull;
+typedef struct _ViviCodeNullClass ViviCodeNullClass;
+
+#define VIVI_TYPE_CODE_NULL                    (vivi_code_null_get_type())
+#define VIVI_IS_CODE_NULL(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_NULL))
+#define VIVI_IS_CODE_NULL_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_NULL))
+#define VIVI_CODE_NULL(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_NULL, ViviCodeNull))
+#define VIVI_CODE_NULL_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_NULL, ViviCodeNullClass))
+#define VIVI_CODE_NULL_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_NULL, ViviCodeNullClass))
+
+struct _ViviCodeNull
+{
+  ViviCodeConstant	constant;
+};
+
+struct _ViviCodeNullClass
+{
+  ViviCodeConstantClass constant_class;
+};
+
+GType			vivi_code_null_get_type   	(void);
+
+ViviCodeValue *		vivi_code_null_new		(void);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_code_number.c b/vivified/code/vivi_code_number.c
new file mode 100644
index 0000000..24b0e84
--- /dev/null
+++ b/vivified/code/vivi_code_number.c
@@ -0,0 +1,71 @@
+/* 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_number.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCodeNumber, vivi_code_number, VIVI_TYPE_CODE_CONSTANT)
+
+static void
+vivi_code_number_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  ViviCodeNumber *number = VIVI_CODE_NUMBER (token);
+  char *s;
+
+  s = g_strdup_printf ("%g", number->value);
+  vivi_code_printer_print (printer, s);
+  g_free (s);
+}
+
+static void
+vivi_code_number_class_init (ViviCodeNumberClass *klass)
+{
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+
+  token_class->print = vivi_code_number_print;
+}
+
+static void
+vivi_code_number_init (ViviCodeNumber *number)
+{
+}
+
+ViviCodeValue *
+vivi_code_number_new (double value)
+{
+  ViviCodeNumber *number;
+
+  number = g_object_new (VIVI_TYPE_CODE_NUMBER, NULL);
+  number->value = value;
+
+  return VIVI_CODE_VALUE (number);
+}
+
+double
+vivi_code_number_get_value (ViviCodeNumber *number)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_NUMBER (number), 0.0);
+
+  return number->value;
+}
+
diff --git a/vivified/code/vivi_code_number.h b/vivified/code/vivi_code_number.h
new file mode 100644
index 0000000..943041e
--- /dev/null
+++ b/vivified/code/vivi_code_number.h
@@ -0,0 +1,58 @@
+/* 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_NUMBER_H_
+#define _VIVI_CODE_NUMBER_H_
+
+#include <vivified/code/vivi_code_constant.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeNumber ViviCodeNumber;
+typedef struct _ViviCodeNumberClass ViviCodeNumberClass;
+
+#define VIVI_TYPE_CODE_NUMBER                    (vivi_code_number_get_type())
+#define VIVI_IS_CODE_NUMBER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_NUMBER))
+#define VIVI_IS_CODE_NUMBER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_NUMBER))
+#define VIVI_CODE_NUMBER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_NUMBER, ViviCodeNumber))
+#define VIVI_CODE_NUMBER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_NUMBER, ViviCodeNumberClass))
+#define VIVI_CODE_NUMBER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_NUMBER, ViviCodeNumberClass))
+
+struct _ViviCodeNumber
+{
+  ViviCodeConstant	constant;
+
+  double		value;
+};
+
+struct _ViviCodeNumberClass
+{
+  ViviCodeConstantClass constant_class;
+};
+
+GType		vivi_code_number_get_type   	(void);
+
+ViviCodeValue *	vivi_code_number_new		(double			value);
+
+double		vivi_code_number_get_value	(ViviCodeNumber *	number);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_code_string.c b/vivified/code/vivi_code_string.c
new file mode 100644
index 0000000..a561f7d
--- /dev/null
+++ b/vivified/code/vivi_code_string.c
@@ -0,0 +1,150 @@
+/* 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 <string.h>
+
+#include "vivi_code_string.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCodeString, vivi_code_string, VIVI_TYPE_CODE_CONSTANT)
+
+static void
+vivi_code_string_dispose (GObject *object)
+{
+  ViviCodeString *string = VIVI_CODE_STRING (object);
+
+  g_free (string->value);
+  string->value = NULL;
+
+  G_OBJECT_CLASS (vivi_code_string_parent_class)->dispose (object);
+}
+
+static char *
+escape_string (const char *s)
+{
+  GString *str;
+  char *next;
+
+  str = g_string_new ("\"");
+  while ((next = strpbrk (s, "\"\\\b\f\n\r\t\v"))) {
+    g_string_append_len (str, s, next - s);
+    switch (*next) {
+      case '"':
+	g_string_append (str, "\\\"");
+	break;
+      case '\\':
+	g_string_append (str, "\\\\");
+	break;
+      case '\b':
+	g_string_append (str, "\\b");
+	break;
+      case '\f':
+	g_string_append (str, "\\f");
+	break;
+      case '\n':
+	g_string_append (str, "\\n");
+	break;
+      case '\r':
+	g_string_append (str, "\\r");
+	break;
+      case '\t':
+	g_string_append (str, "\\t");
+	break;
+      case '\v':
+	g_string_append (str, "\\v");
+	break;
+      default:
+	g_assert_not_reached ();
+    }
+    s = next + 1;
+  }
+  g_string_append (str, s);
+  g_string_append_c (str, '"');
+  return g_string_free (str, FALSE);
+}
+
+static void
+vivi_code_string_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  ViviCodeString *string = VIVI_CODE_STRING (token);
+  char *s;
+
+  s = escape_string (string->value);
+  vivi_code_printer_print (printer, s);
+  g_free (s);
+}
+
+static char *
+vivi_code_string_get_variable_name (ViviCodeConstant *constant)
+{
+  static const char *accept = G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_$";
+  ViviCodeString *string = VIVI_CODE_STRING (constant);
+  gsize len;
+
+  len = strspn (string->value, accept);
+  if (string->value[len] == '\0')
+    return g_strdup (string->value);
+  else
+    return NULL;
+}
+
+static void
+vivi_code_string_class_init (ViviCodeStringClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeConstantClass *constant_class = VIVI_CODE_CONSTANT_CLASS (klass);
+
+  object_class->dispose = vivi_code_string_dispose;
+
+  token_class->print = vivi_code_string_print;
+
+  constant_class->get_variable_name = vivi_code_string_get_variable_name;
+}
+
+static void
+vivi_code_string_init (ViviCodeString *string)
+{
+}
+
+ViviCodeValue *
+vivi_code_string_new (const char *value)
+{
+  ViviCodeString *string;
+
+  g_return_val_if_fail (value != NULL, NULL);
+
+  string = g_object_new (VIVI_TYPE_CODE_STRING, NULL);
+  string->value = g_strdup (value);
+
+  return VIVI_CODE_VALUE (string);
+}
+
+const char *
+vivi_code_string_get_value (ViviCodeString *string)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_STRING (string), NULL);
+
+  return string->value;
+}
+
diff --git a/vivified/code/vivi_code_string.h b/vivified/code/vivi_code_string.h
new file mode 100644
index 0000000..b5aa1ee
--- /dev/null
+++ b/vivified/code/vivi_code_string.h
@@ -0,0 +1,58 @@
+/* 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_STRING_H_
+#define _VIVI_CODE_STRING_H_
+
+#include <vivified/code/vivi_code_constant.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeString ViviCodeString;
+typedef struct _ViviCodeStringClass ViviCodeStringClass;
+
+#define VIVI_TYPE_CODE_STRING                    (vivi_code_string_get_type())
+#define VIVI_IS_CODE_STRING(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_STRING))
+#define VIVI_IS_CODE_STRING_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_STRING))
+#define VIVI_CODE_STRING(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_STRING, ViviCodeString))
+#define VIVI_CODE_STRING_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_STRING, ViviCodeStringClass))
+#define VIVI_CODE_STRING_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_STRING, ViviCodeStringClass))
+
+struct _ViviCodeString
+{
+  ViviCodeConstant	constant;
+
+  char *		value;
+};
+
+struct _ViviCodeStringClass
+{
+  ViviCodeConstantClass constant_class;
+};
+
+GType			vivi_code_string_get_type   	(void);
+
+ViviCodeValue *		vivi_code_string_new		(const char *		value);
+
+const char *		vivi_code_string_get_value	(ViviCodeString *	string);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_code_undefined.c b/vivified/code/vivi_code_undefined.c
new file mode 100644
index 0000000..2cadf78
--- /dev/null
+++ b/vivified/code/vivi_code_undefined.c
@@ -0,0 +1,66 @@
+/* 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 <ctype.h>
+#include <math.h>
+#include <string.h>
+
+#include "vivi_code_undefined.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCodeUndefined, vivi_code_undefined, VIVI_TYPE_CODE_CONSTANT)
+
+static void
+vivi_code_undefined_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  vivi_code_printer_print (printer, "undefined");
+}
+
+static char *
+vivi_code_undefined_get_variable_name (ViviCodeConstant *constant)
+{
+  return g_strdup ("undefined");
+}
+
+static void
+vivi_code_undefined_class_init (ViviCodeUndefinedClass *klass)
+{
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeConstantClass *constant_class = VIVI_CODE_CONSTANT_CLASS (klass);
+
+  token_class->print = vivi_code_undefined_print;
+
+  constant_class->get_variable_name = vivi_code_undefined_get_variable_name;
+}
+
+static void
+vivi_code_undefined_init (ViviCodeUndefined *undefined)
+{
+}
+
+ViviCodeValue *
+vivi_code_undefined_new (void)
+{
+  return g_object_new (VIVI_TYPE_CODE_UNDEFINED, NULL);
+}
+
diff --git a/vivified/code/vivi_code_undefined.h b/vivified/code/vivi_code_undefined.h
new file mode 100644
index 0000000..30cb1ec
--- /dev/null
+++ b/vivified/code/vivi_code_undefined.h
@@ -0,0 +1,54 @@
+/* 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_UNDEFINED_H_
+#define _VIVI_CODE_UNDEFINED_H_
+
+#include <vivified/code/vivi_code_constant.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeUndefined ViviCodeUndefined;
+typedef struct _ViviCodeUndefinedClass ViviCodeUndefinedClass;
+
+#define VIVI_TYPE_CODE_UNDEFINED                    (vivi_code_undefined_get_type())
+#define VIVI_IS_CODE_UNDEFINED(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_UNDEFINED))
+#define VIVI_IS_CODE_UNDEFINED_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_UNDEFINED))
+#define VIVI_CODE_UNDEFINED(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_UNDEFINED, ViviCodeUndefined))
+#define VIVI_CODE_UNDEFINED_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_UNDEFINED, ViviCodeUndefinedClass))
+#define VIVI_CODE_UNDEFINED_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_UNDEFINED, ViviCodeUndefinedClass))
+
+struct _ViviCodeUndefined
+{
+  ViviCodeConstant	constant;
+};
+
+struct _ViviCodeUndefinedClass
+{
+  ViviCodeConstantClass constant_class;
+};
+
+GType			vivi_code_undefined_get_type   	(void);
+
+ViviCodeValue *		vivi_code_undefined_new		(void);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_compiler_get_temporary.c b/vivified/code/vivi_compiler_get_temporary.c
index 2b5b515..1b7e2c7 100644
--- a/vivified/code/vivi_compiler_get_temporary.c
+++ b/vivified/code/vivi_compiler_get_temporary.c
@@ -25,8 +25,8 @@
 #include "vivi_compiler_get_temporary.h"
 
 #include "vivi_code_get.h"
-#include "vivi_code_constant.h"
 #include "vivi_code_printer.h"
+#include "vivi_code_string.h"
 
 G_DEFINE_TYPE (ViviCompilerGetTemporary, vivi_compiler_get_temporary, VIVI_TYPE_CODE_GET)
 
@@ -48,7 +48,7 @@ vivi_compiler_get_temporary_new (void)
   char *name = g_strdup_printf ("$%i", ++counter);
 
   get = g_object_new (VIVI_TYPE_COMPILER_GET_TEMPORARY, NULL);
-  VIVI_CODE_GET (get)->name = vivi_code_constant_new_string (name);
+  VIVI_CODE_GET (get)->name = vivi_code_string_new (name);
 
   g_free (name);
 
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index caf906e..f95d393 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -32,6 +32,7 @@
 #include "vivi_code_assignment.h"
 #include "vivi_code_binary_default.h"
 #include "vivi_code_block.h"
+#include "vivi_code_boolean.h"
 #include "vivi_code_break.h"
 #include "vivi_code_builtin_value_statement_default.h"
 #include "vivi_code_constant.h"
@@ -44,9 +45,13 @@
 #include "vivi_code_if.h"
 #include "vivi_code_init_object.h"
 #include "vivi_code_loop.h"
+#include "vivi_code_number.h"
+#include "vivi_code_null.h"
 #include "vivi_code_or.h"
 #include "vivi_code_return.h"
+#include "vivi_code_string.h"
 #include "vivi_code_unary.h"
+#include "vivi_code_undefined.h"
 #include "vivi_code_value_statement.h"
 #include "vivi_decompiler_block.h"
 #include "vivi_decompiler_duplicate.h"
@@ -143,31 +148,31 @@ vivi_decompile_push (ViviDecompilerBlock *block, ViviDecompilerState *state,
 	    vivi_decompiler_block_add_error (block, state, "could not read string");
 	    return FALSE;
 	  }
-	  val = vivi_code_constant_new_string (s);
+	  val = vivi_code_string_new (s);
 	  g_free (s);
 	  break;
 	}
       case 1: /* float */
-	val = vivi_code_constant_new_number (swfdec_bits_get_float (&bits));
+	val = vivi_code_number_new (swfdec_bits_get_float (&bits));
 	break;
       case 2: /* null */
-	val = vivi_code_constant_new_null ();
+	val = vivi_code_null_new ();
 	break;
       case 3: /* undefined */
-	val = vivi_code_constant_new_undefined ();
+	val = vivi_code_undefined_new ();
 	break;
       case 4: /* register */
 	val = vivi_decompiler_state_get_register (
 	      state, swfdec_bits_get_u8 (&bits));
 	break;
       case 5: /* boolean */
-	val = vivi_code_constant_new_boolean (swfdec_bits_get_u8 (&bits) ? TRUE : FALSE);
+	val = vivi_code_boolean_new (swfdec_bits_get_u8 (&bits) ? TRUE : FALSE);
 	break;
       case 6: /* double */
-	val = vivi_code_constant_new_number (swfdec_bits_get_double (&bits));
+	val = vivi_code_number_new (swfdec_bits_get_double (&bits));
 	break;
       case 7: /* 32bit int */
-	val = vivi_code_constant_new_int ((int) swfdec_bits_get_u32 (&bits));
+	val = vivi_code_number_new ((int) swfdec_bits_get_u32 (&bits));
 	break;
       case 8: /* 8bit ConstantPool address */
       case 9: /* 16bit ConstantPool address */
@@ -183,7 +188,7 @@ vivi_decompile_push (ViviDecompilerBlock *block, ViviDecompilerState *state,
 		i, swfdec_constant_pool_size (pool));
 	    return TRUE;
 	  }
-	  val = vivi_code_constant_new_string (swfdec_constant_pool_get (pool, i));
+	  val = vivi_code_string_new (swfdec_constant_pool_get (pool, i));
 	  break;
 	}
       default:
@@ -266,8 +271,7 @@ vivi_decompile_return (ViviDecompilerBlock *block, ViviDecompilerState *state,
 
   value = vivi_decompiler_state_pop (state);
   ret = vivi_code_return_new ();
-  if (!VIVI_IS_CODE_CONSTANT (value) ||
-      vivi_code_constant_get_value_type (VIVI_CODE_CONSTANT (value)) != SWFDEC_AS_TYPE_UNDEFINED)
+  if (!VIVI_IS_CODE_UNDEFINED (value))
     vivi_code_return_set_value (VIVI_CODE_RETURN (ret), value);
   g_object_unref (value);
   vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), ret);
@@ -388,7 +392,7 @@ vivi_decompile_define_local (ViviDecompilerBlock *block, ViviDecompilerState *st
   if (code == SWFDEC_AS_ACTION_DEFINE_LOCAL)
     value = vivi_decompiler_state_pop (state);
   else
-    value = vivi_code_constant_new_undefined ();
+    value = vivi_code_undefined_new ();
   name = vivi_decompiler_state_pop (state);
 
   assign = vivi_code_assignment_new (NULL, name, value);
@@ -450,9 +454,8 @@ vivi_decompile_function_call (ViviDecompilerBlock *block, ViviDecompilerState *s
   if (name)
     g_object_unref (name);
 
-  if (!VIVI_IS_CODE_CONSTANT (args) || 
-      vivi_code_constant_get_value_type (VIVI_CODE_CONSTANT (args)) != SWFDEC_AS_TYPE_NUMBER ||
-      ((count = d = vivi_code_constant_get_number (VIVI_CODE_CONSTANT (args))) != d)) {
+  if (!VIVI_IS_CODE_NUMBER (args) || 
+      ((count = d = vivi_code_number_get_value (VIVI_CODE_NUMBER (args))) != d)) {
     vivi_decompiler_block_add_error (block, state, "could not determine function argument count");
     g_object_unref (args);
     g_object_unref (call);
@@ -569,9 +572,8 @@ vivi_decompile_define_function (ViviDecompilerBlock *block, ViviDecompilerState
      * it will contain the name this function will soon be assigned to.
      */
     value = vivi_decompiler_state_peek_nth (state, 0);
-    if (VIVI_IS_CODE_CONSTANT (value) &&
-	vivi_code_constant_get_value_type (VIVI_CODE_CONSTANT (value)) == SWFDEC_AS_TYPE_STRING)
-      name = SWFDEC_AS_VALUE_GET_STRING (&VIVI_CODE_CONSTANT (value)->value);
+    if (VIVI_IS_CODE_STRING (value))
+      name = vivi_code_string_get_value (VIVI_CODE_STRING (value));
   }
   if (name == NULL)
     name = "unnamed_function";
@@ -644,9 +646,8 @@ vivi_decompile_init_object (ViviDecompilerBlock *block, ViviDecompilerState *sta
   guint i, count;
 
   args = vivi_decompiler_state_pop (state);
-  if (!VIVI_IS_CODE_CONSTANT (args) || 
-      vivi_code_constant_get_value_type (VIVI_CODE_CONSTANT (args)) != SWFDEC_AS_TYPE_NUMBER ||
-      ((count = d = vivi_code_constant_get_number (VIVI_CODE_CONSTANT (args))) != d)) {
+  if (!VIVI_IS_CODE_NUMBER (args) || 
+      ((count = d = vivi_code_number_get_value (VIVI_CODE_NUMBER (args))) != d)) {
     vivi_decompiler_block_add_error (block, state, "could not determine init object argument count");
     g_object_unref (args);
     return FALSE;
diff --git a/vivified/code/vivi_decompiler_block.c b/vivified/code/vivi_decompiler_block.c
index 14cec1c..1fc22b2 100644
--- a/vivified/code/vivi_decompiler_block.c
+++ b/vivified/code/vivi_decompiler_block.c
@@ -28,10 +28,10 @@
 #include "vivi_code_assignment.h"
 #include "vivi_code_block.h"
 #include "vivi_code_comment.h"
-#include "vivi_code_constant.h"
 #include "vivi_code_goto.h"
 #include "vivi_code_if.h"
 #include "vivi_code_label.h"
+#include "vivi_code_string.h"
 #include "vivi_decompiler_unknown.h"
 
 G_DEFINE_TYPE (ViviDecompilerBlock, vivi_decompiler_block, VIVI_TYPE_CODE_BLOCK)
@@ -330,7 +330,7 @@ vivi_decompiler_block_add_state_transition (ViviDecompilerBlock *from,
       return;
     }
     if (val_from != VIVI_CODE_VALUE (val_to)) {
-      name = vivi_code_constant_new_string (vivi_decompiler_unknown_get_name (val_to));
+      name = vivi_code_string_new (vivi_decompiler_unknown_get_name (val_to));
       vivi_code_block_add_statement (block,
 	  vivi_code_assignment_new (NULL, name, val_from));
     }
diff --git a/vivified/code/vivi_decompiler_state.c b/vivified/code/vivi_decompiler_state.c
index f821f26..5425422 100644
--- a/vivified/code/vivi_decompiler_state.c
+++ b/vivified/code/vivi_decompiler_state.c
@@ -24,7 +24,7 @@
 #include <swfdec/swfdec_script_internal.h>
 
 #include "vivi_decompiler_state.h"
-#include "vivi_code_constant.h"
+#include "vivi_code_undefined.h"
 #include "vivi_decompiler_unknown.h"
 
 struct _ViviDecompilerState {
@@ -77,7 +77,7 @@ ViviCodeValue *
 vivi_decompiler_state_pop (ViviDecompilerState *state)
 {
   if (state->stack == NULL) {
-    return VIVI_CODE_VALUE (vivi_code_constant_new_undefined ());
+    return vivi_code_undefined_new ();
   } else {
     ViviCodeValue *pop;
     pop = state->stack->data;
@@ -125,7 +125,7 @@ ViviCodeValue *
 vivi_decompiler_state_get_register (const ViviDecompilerState *state, guint reg)
 {
   if (reg >= state->n_registers || state->registers[reg] == NULL)
-    return VIVI_CODE_VALUE (vivi_code_constant_new_undefined ());
+    return vivi_code_undefined_new ();
   else
     return g_object_ref (state->registers[reg]);
 }
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index b73d7c4..35619a2 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -31,6 +31,7 @@
 #include "vivi_code_assignment.h"
 #include "vivi_code_binary_default.h"
 #include "vivi_code_block.h"
+#include "vivi_code_boolean.h"
 #include "vivi_code_break.h"
 #include "vivi_code_builtin_statement_default.h"
 #include "vivi_code_builtin_value_call_default.h"
@@ -48,11 +49,15 @@
 #include "vivi_code_init_array.h"
 #include "vivi_code_init_object.h"
 #include "vivi_code_loop.h"
+#include "vivi_code_null.h"
+#include "vivi_code_number.h"
 #include "vivi_code_or.h"
 #include "vivi_code_return.h"
+#include "vivi_code_string.h"
 #include "vivi_code_substring.h"
 #include "vivi_code_throw.h"
 #include "vivi_code_unary.h"
+#include "vivi_code_undefined.h"
 #include "vivi_code_value_statement.h"
 #include "vivi_compiler_empty_statement.h"
 #include "vivi_compiler_get_temporary.h"
@@ -584,7 +589,7 @@ parse_undefined_literal (ParseData *data, ViviCodeValue **value)
 
   parse_token (data, TOKEN_UNDEFINED);
 
-  *value = vivi_code_constant_new_undefined ();
+  *value = vivi_code_undefined_new ();
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
@@ -602,7 +607,7 @@ parse_null_literal (ParseData *data, ViviCodeValue **value)
 
   parse_token (data, TOKEN_NULL);
 
-  *value = vivi_code_constant_new_null ();
+  *value = vivi_code_null_new ();
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
@@ -620,9 +625,9 @@ parse_boolean_literal (ParseData *data, ViviCodeValue **value)
 
   if (!try_parse_token (data, TOKEN_BOOLEAN)) {
     vivi_parser_error_unexpected (data, TOKEN_BOOLEAN);
-    *value = vivi_code_constant_new_boolean (0);
+    *value = vivi_code_boolean_new (0);
   } else {
-    *value = vivi_code_constant_new_boolean (data->scanner->value.v_boolean);
+    *value = vivi_code_boolean_new (data->scanner->value.v_boolean);
   }
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
@@ -641,9 +646,9 @@ parse_numeric_literal (ParseData *data, ViviCodeValue **value)
 
   if (!try_parse_token (data, TOKEN_NUMBER)) {
     vivi_parser_error_unexpected (data, TOKEN_NUMBER);
-    *value = vivi_code_constant_new_number (0);
+    *value = vivi_code_number_new (0);
   } else {
-    *value = vivi_code_constant_new_number (data->scanner->value.v_number);
+    *value = vivi_code_number_new (data->scanner->value.v_number);
   }
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
@@ -662,9 +667,9 @@ parse_string_literal (ParseData *data, ViviCodeValue **value)
 
   if (!try_parse_token (data, TOKEN_STRING)) {
     vivi_parser_error_unexpected (data, TOKEN_STRING);
-    *value = vivi_code_constant_new_string ("undefined");
+    *value = vivi_code_string_new ("undefined");
   } else {
-    *value = vivi_code_constant_new_string (data->scanner->value.v_string);
+    *value = vivi_code_string_new (data->scanner->value.v_string);
   }
 
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
@@ -709,7 +714,7 @@ parse_literal (ParseData *data, ViviCodeValue **value)
 
   vivi_parser_error_unexpected (data, ERROR_TOKEN_LITERAL);
   vivi_parser_start_code_token (data);
-  *value = vivi_code_constant_new_undefined ();
+  *value = vivi_code_undefined_new ();
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
@@ -771,7 +776,7 @@ parse_property_name (ParseData *data, ViviCodeValue **value)
 
   vivi_parser_error_unexpected (data, ERROR_TOKEN_PROPERTY_NAME);
   vivi_parser_start_code_token (data);
-  *value = vivi_code_constant_new_undefined ();
+  *value = vivi_code_undefined_new ();
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
@@ -805,11 +810,11 @@ parse_array_literal (ParseData *data, ViviCodeValue **value,
   while (TRUE) {
     if (try_parse_token (data, TOKEN_BRACKET_RIGHT)) {
       vivi_code_init_array_add_variable (VIVI_CODE_INIT_ARRAY (*value),
-	 vivi_code_constant_new_undefined ());
+	 vivi_code_undefined_new ());
       break;
     } else if (try_parse_token (data, TOKEN_COMMA)) {
       vivi_code_init_array_add_variable (VIVI_CODE_INIT_ARRAY (*value),
-	 vivi_code_constant_new_undefined ());
+	 vivi_code_undefined_new ());
     }
     else if (peek_assignment_expression (data))
     {
@@ -899,7 +904,7 @@ parse_variable_declaration (ParseData *data, ViviCodeStatement **statement)
   } else {
     vivi_parser_start_code_token (data);
 
-    value = vivi_code_constant_new_undefined ();
+    value = vivi_code_undefined_new ();
     statement_right = NULL;
 
     vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
@@ -942,9 +947,9 @@ parse_get_url2 (ParseData *data, ViviCodeStatement **statement,
 	char *level_name;
 	parse_numeric_literal (data, &target);
 	level_name = g_strdup_printf ("_level%i",
-	    (int)vivi_code_constant_get_number (VIVI_CODE_CONSTANT (target)));
+	    (int)vivi_code_number_get_value (VIVI_CODE_NUMBER (target)));
 	g_object_unref (target);
-	target = vivi_code_constant_new_string (level_name);
+	target = vivi_code_string_new (level_name);
 	g_free (level_name);
       } else {
 	// TODO
@@ -991,7 +996,7 @@ parse_get_url2 (ParseData *data, ViviCodeStatement **statement,
       method = SWFDEC_LOADER_REQUEST_DEFAULT;
     }
   } else {
-    target = vivi_code_constant_new_undefined ();
+    target = vivi_code_undefined_new ();
     method = SWFDEC_LOADER_REQUEST_DEFAULT;
   }
 
@@ -1368,7 +1373,7 @@ parse_primary_expression (ParseData *data, ViviCodeValue **value,
   }
 
   vivi_parser_error_unexpected (data, ERROR_TOKEN_PRIMARY_EXPRESSION);
-  *value = vivi_code_constant_new_undefined ();
+  *value = vivi_code_undefined_new ();
   *statement = NULL;
   vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
@@ -1402,7 +1407,7 @@ parse_member_expression (ParseData *data, ViviCodeValue **value,
   } else {
     vivi_parser_error_unexpected_or (data, ERROR_TOKEN_PRIMARY_EXPRESSION,
 	ERROR_TOKEN_FUNCTION_EXPRESSION, TOKEN_NONE);
-    *value = vivi_code_constant_new_undefined ();
+    *value = vivi_code_undefined_new ();
     *statement = NULL;
 
     vivi_parser_duplicate_code_token (data);
@@ -1548,7 +1553,7 @@ parse_postfix_expression (ParseData *data, ViviCodeValue **value,
 	"Invalid left-hand side expression for INCREASE/DECREASE");
   }
 
-  one = vivi_code_constant_new_number (1);
+  one = vivi_code_number_new (1);
   operation = (add ? vivi_code_add_new : vivi_code_subtract_new) (*value, one);
   g_object_unref (one);
 
@@ -1616,7 +1621,7 @@ parse_unary_expression (ParseData *data, ViviCodeValue **value,
 	    "Invalid left-hand side expression for INCREASE/DECREASE");
       }
 
-      one = vivi_code_constant_new_number (1);
+      one = vivi_code_number_new (1);
       tmp = (data->scanner->next_token == TOKEN_INCREASE ? vivi_code_add_new : vivi_code_subtract_new) (*value, one);
       g_object_unref (one);
 
@@ -2269,7 +2274,7 @@ parse_iteration_statement (ParseData *data, ViviCodeStatement **statement)
 	g_object_unref (pre_value);
 
       if (try_parse_token (data, TOKEN_SEMICOLON)) {
-	condition = vivi_code_constant_new_boolean (TRUE);
+	condition = vivi_code_boolean_new (TRUE);
 	condition_statement = NULL;
       } else {
 	parse_expression (data, &condition, &condition_statement);
@@ -2295,7 +2300,7 @@ parse_iteration_statement (ParseData *data, ViviCodeStatement **statement)
 
       vivi_parser_error (data, "for (... in ...) has not been implemented yet");
 
-      condition = vivi_code_constant_new_undefined ();
+      condition = vivi_code_undefined_new ();
       condition_statement = NULL;
       post_statement = NULL;
     } else {
@@ -2306,7 +2311,7 @@ parse_iteration_statement (ParseData *data, ViviCodeStatement **statement)
 	vivi_parser_error_unexpected (data, TOKEN_SEMICOLON);
       }
 
-      condition = vivi_code_constant_new_undefined ();
+      condition = vivi_code_undefined_new ();
       condition_statement = NULL;
       post_statement = NULL;
 
@@ -2326,7 +2331,7 @@ parse_iteration_statement (ParseData *data, ViviCodeStatement **statement)
   {
     vivi_parser_error_unexpected (data, ERROR_TOKEN_ITERATION_STATEMENT);
 
-    condition = vivi_code_constant_new_undefined ();
+    condition = vivi_code_undefined_new ();
     pre_statement = NULL;
     condition_statement = NULL;
     loop_statement = vivi_compiler_empty_statement_new ();
commit 0c57cbeea50a3b7d7440220ad8e02f129ad08ebf
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Apr 17 16:32:51 2008 +0200

    add stubs for the code emitter

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index d0ae8a5..ec268b2 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -38,6 +38,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_concat.c \
 	vivi_code_constant.c \
 	vivi_code_continue.c \
+	vivi_code_emitter.c \
 	vivi_code_function.c \
 	vivi_code_function_call.c \
 	vivi_code_get.c \
@@ -95,6 +96,7 @@ noinst_HEADERS = \
 	vivi_code_constant.h \
 	vivi_code_continue.h \
 	vivi_code_defaults.h \
+	vivi_code_emitter.h \
 	vivi_code_function.h \
 	vivi_code_function_call.h \
 	vivi_code_get.h \
diff --git a/vivified/code/vivi_code_asm.h b/vivified/code/vivi_code_asm.h
index 0687471..cc7465d 100644
--- a/vivified/code/vivi_code_asm.h
+++ b/vivified/code/vivi_code_asm.h
@@ -30,11 +30,17 @@ G_BEGIN_DECLS
 #define VIVI_IS_CODE_ASM(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_ASM))
 #define VIVI_CODE_ASM_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), VIVI_TYPE_CODE_ASM, ViviCodeAsmInterface))
 
+/* forward declaration */
+typedef struct _ViviCodeEmitter ViviCodeEmitter;
+
 typedef struct _ViviCodeAsm ViviCodeAsm; /* dummy object */
 typedef struct _ViviCodeAsmInterface ViviCodeAsmInterface;
 
 struct _ViviCodeAsmInterface {
   GTypeInterface	interface;
+
+  void			(* emit)			(ViviCodeAsm *		code,
+							 ViviCodeEmitter *	emitter);
 };
 
 GType			vivi_code_asm_get_type		(void) G_GNUC_CONST;
diff --git a/vivified/code/vivi_code_asm_code_default.c b/vivified/code/vivi_code_asm_code_default.c
index 3a40fb6..3daf353 100644
--- a/vivified/code/vivi_code_asm_code_default.c
+++ b/vivified/code/vivi_code_asm_code_default.c
@@ -24,7 +24,7 @@
 #include "vivi_code_asm_code_default.h"
 #include "vivi_code_printer.h"
 
-#define DEFAULT_ASM(CapsName, underscore_name, bytecode) \
+#define DEFAULT_ASM(CapsName, underscore_name, byte_code) \
 \
 G_DEFINE_TYPE (ViviCodeAsm ## CapsName, vivi_code_asm_ ## underscore_name, VIVI_TYPE_CODE_ASM_CODE); \
 \
@@ -38,9 +38,12 @@ vivi_code_asm_ ## underscore_name ## _print (ViviCodeToken *token, ViviCodePrint
 static void \
 vivi_code_asm_ ## underscore_name ## _class_init (ViviCodeAsm ## CapsName ## Class *klass) \
 { \
+  ViviCodeAsmCodeClass *code_class = VIVI_CODE_ASM_CODE_CLASS (klass); \
   ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass); \
 \
   token_class->print = vivi_code_asm_ ## underscore_name ## _print; \
+\
+  code_class->bytecode = byte_code; \
 } \
 \
 static void \
diff --git a/vivified/code/vivi_code_asm_code_default.h b/vivified/code/vivi_code_asm_code_default.h
index d30c181..72bdfba 100644
--- a/vivified/code/vivi_code_asm_code_default.h
+++ b/vivified/code/vivi_code_asm_code_default.h
@@ -17,8 +17,8 @@
  * Boston, MA  02110-1301  USA
  */
 
-#ifndef _VIVI_CODE_BINARY_DEFAULT_H_
-#define _VIVI_CODE_BINARY_DEFAULT_H_
+#ifndef _VIVI_CODE_ASM_CODE_DEFAULT_H_
+#define _VIVI_CODE_ASM_CODE_DEFAULT_H_
 
 #include <vivified/code/vivi_code_asm_code.h>
 #include <vivified/code/vivi_code_asm.h>
diff --git a/vivified/code/vivi_code_emitter.c b/vivified/code/vivi_code_emitter.c
new file mode 100644
index 0000000..e73cd57
--- /dev/null
+++ b/vivified/code/vivi_code_emitter.c
@@ -0,0 +1,150 @@
+/* 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_emitter.h"
+
+G_DEFINE_TYPE (ViviCodeEmitter, vivi_code_emitter, G_TYPE_OBJECT)
+
+static void
+vivi_code_emitter_dispose (GObject *object)
+{
+  ViviCodeEmitter *emit = VIVI_CODE_EMITTER (object);
+
+  if (emit->bots) {
+    SwfdecBuffer *buffer = swfdec_bots_close (emit->bots);
+    swfdec_buffer_unref (buffer);
+    emit->bots = NULL;
+  }
+  g_slist_foreach (emit->later, (GFunc) g_free, NULL);
+  g_slist_free (emit->later);
+  emit->later = NULL;
+  g_hash_table_remove_all (emit->labels);
+  emit->labels = NULL;
+
+  G_OBJECT_CLASS (vivi_code_emitter_parent_class)->dispose (object);
+}
+
+static void
+vivi_code_emitter_class_init (ViviCodeEmitterClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = vivi_code_emitter_dispose;
+}
+
+static void
+vivi_code_emitter_init (ViviCodeEmitter *emit)
+{
+  emit->bots = swfdec_bots_open ();
+  emit->labels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+      g_object_unref, g_free);
+}
+
+void
+vivi_code_emitter_emit_asm (ViviCodeEmitter *emitter, ViviCodeAsm *code)
+{
+  ViviCodeAsmInterface *iface;
+
+  g_return_if_fail (VIVI_IS_CODE_EMITTER (emitter));
+  g_return_if_fail (VIVI_IS_CODE_ASM (code));
+
+  iface = VIVI_CODE_ASM_GET_INTERFACE (code);
+  iface->emit (code, emitter);
+}
+
+void
+vivi_code_emitter_add_label (ViviCodeEmitter *emitter, ViviCodeLabel *label)
+{
+  g_return_if_fail (VIVI_IS_CODE_EMITTER (emitter));
+  g_return_if_fail (VIVI_IS_CODE_LABEL (label));
+
+  g_assert (g_hash_table_lookup (emitter->labels, label) == NULL);
+  g_hash_table_insert (emitter->labels, g_object_ref (label), 
+      GSIZE_TO_POINTER (swfdec_bots_get_bytes (emitter->bots) + 1));
+}
+
+gssize
+vivi_code_emitter_get_label_offset (ViviCodeEmitter *emitter, ViviCodeLabel *label)
+{
+  gsize size;
+
+  g_return_val_if_fail (VIVI_IS_CODE_EMITTER (emitter), -1);
+  g_return_val_if_fail (VIVI_IS_CODE_LABEL (label), -1);
+
+  size = GPOINTER_TO_SIZE (g_hash_table_lookup (emitter->labels, label));
+  return (gssize) size - 1;
+}
+
+typedef struct {
+  ViviCodeEmitLater	func;
+  gpointer		data;
+} Later;
+
+void
+vivi_code_emitter_add_later (ViviCodeEmitter *emitter, ViviCodeEmitLater func, gpointer data)
+{
+  Later *later;
+
+  g_return_if_fail (VIVI_IS_CODE_EMITTER (emitter));
+  g_return_if_fail (VIVI_IS_CODE_EMITTER (emitter));
+
+  later = g_new (Later, 1);
+  later->func = func;
+  later->data = data;
+  emitter->later = g_slist_prepend (emitter->later, later);
+}
+
+SwfdecBuffer *
+vivi_code_emitter_finish (ViviCodeEmitter *emitter, GError **error)
+{
+  SwfdecBuffer *buffer;
+  GSList *walk;
+
+  g_return_val_if_fail (VIVI_IS_CODE_EMITTER (emitter), NULL);
+
+  buffer = swfdec_bots_close (emitter->bots);
+  emitter->bots = NULL;
+  for (walk = emitter->later; walk; walk = walk->next) {
+    Later *later = walk->data;
+    if (!later->func (emitter, buffer, later->data, error)) {
+      swfdec_buffer_unref (buffer);
+      buffer = NULL;
+    }
+  }
+  g_slist_foreach (emitter->later, (GFunc) g_free, NULL);
+  g_slist_free (emitter->later);
+  emitter->later = NULL;
+  g_hash_table_remove_all (emitter->labels);
+  emitter->bots = swfdec_bots_open ();
+
+  return buffer;
+}
+
+SwfdecBots *
+vivi_code_emitter_get_bots (ViviCodeEmitter *emitter)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_EMITTER (emitter), NULL);
+
+  return emitter->bots;
+}
+
diff --git a/vivified/code/vivi_code_emitter.h b/vivified/code/vivi_code_emitter.h
new file mode 100644
index 0000000..03c2fe4
--- /dev/null
+++ b/vivified/code/vivi_code_emitter.h
@@ -0,0 +1,76 @@
+/* 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_EMITTER_H_
+#define _VIVI_CODE_EMITTER_H_
+
+#include <swfdec/swfdec.h>
+#include <swfdec/swfdec_bots.h>
+#include <vivified/code/vivi_code_asm.h>
+#include <vivified/code/vivi_code_label.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeEmitterClass ViviCodeEmitterClass;
+typedef gboolean (* ViviCodeEmitLater) (ViviCodeEmitter *emitter, SwfdecBuffer *buffer, gpointer data, GError **error);
+
+#define VIVI_TYPE_CODE_EMITTER                    (vivi_code_emitter_get_type())
+#define VIVI_IS_CODE_EMITTER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_EMITTER))
+#define VIVI_IS_CODE_EMITTER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_EMITTER))
+#define VIVI_CODE_EMITTER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_EMITTER, ViviCodeEmitter))
+#define VIVI_CODE_EMITTER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_EMITTER, ViviCodeEmitterClass))
+#define VIVI_CODE_EMITTER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_EMITTER, ViviCodeEmitterClass))
+
+struct _ViviCodeEmitter
+{
+  GObject		object;
+
+  SwfdecBots *		bots;		/* output stream */
+  GHashTable *		labels;		/* ViviCodeLabel => offset + 1 */
+  GSList *		later;		/* ViviCodeEmitLater/data tuples */
+};
+
+struct _ViviCodeEmitterClass
+{
+  GObjectClass		object_class;
+};
+
+GType			vivi_code_emitter_get_type   	(void);
+
+ViviCodeEmitter *	vivi_code_emitter_new		(void);
+
+void			vivi_code_emitter_emit_asm	(ViviCodeEmitter *	emitter,
+							 ViviCodeAsm *		code);
+
+SwfdecBots *		vivi_code_emitter_get_bots	(ViviCodeEmitter *	emitter);
+void			vivi_code_emitter_add_label	(ViviCodeEmitter *	emitter,
+							 ViviCodeLabel *	label);
+gssize			vivi_code_emitter_get_label_offset 
+							(ViviCodeEmitter *	emitter,
+							 ViviCodeLabel *	label);
+void			vivi_code_emitter_add_later	(ViviCodeEmitter *	emitter,
+							 ViviCodeEmitLater	func,
+							 gpointer		data);
+SwfdecBuffer *		vivi_code_emitter_finish	(ViviCodeEmitter *	emitter,
+							 GError **		error);
+
+
+G_END_DECLS
+#endif


More information about the Swfdec-commits mailing list