Index: uspace/app/sbi/Makefile
===================================================================
--- uspace/app/sbi/Makefile	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/Makefile	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -35,8 +35,9 @@
 SOURCES = \
 	src/builtin/bi_boxed.c \
+	src/builtin/bi_error.c \
 	src/builtin/bi_char.c \
-	src/builtin/bi_error.c \
-	src/builtin/bi_fun.c \
+	src/builtin/bi_console.c \
 	src/builtin/bi_int.c \
+	src/builtin/bi_task.c \
 	src/builtin/bi_textfile.c \
 	src/builtin/bi_string.c \
Index: uspace/app/sbi/src/builtin.c
===================================================================
--- uspace/app/sbi/src/builtin.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/builtin.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -43,6 +43,7 @@
 #include "builtin/bi_error.h"
 #include "builtin/bi_char.h"
-#include "builtin/bi_fun.h"
+#include "builtin/bi_console.h"
 #include "builtin/bi_int.h"
+#include "builtin/bi_task.h"
 #include "builtin/bi_textfile.h"
 #include "builtin/bi_string.h"
@@ -93,6 +94,7 @@
 	bi_error_declare(bi);
 	bi_char_declare(bi);
-	bi_fun_declare(bi);
+	bi_console_declare(bi);
 	bi_int_declare(bi);
+	bi_task_declare(bi);
 	bi_textfile_declare(bi);
 	bi_string_declare(bi);
@@ -111,6 +113,7 @@
 	bi_error_bind(bi);
 	bi_char_bind(bi);
-	bi_fun_bind(bi);
+	bi_console_bind(bi);
 	bi_int_bind(bi);
+	bi_task_bind(bi);
 	bi_textfile_bind(bi);
 	bi_string_bind(bi);
Index: uspace/app/sbi/src/builtin/bi_console.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_console.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
+++ uspace/app/sbi/src/builtin/bi_console.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Console builtin binding. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "../bigint.h"
+#include "../builtin.h"
+#include "../list.h"
+#include "../mytypes.h"
+#include "../run.h"
+#include "../stree.h"
+#include "../strtab.h"
+#include "../symbol.h"
+
+#include "bi_console.h"
+
+static void bi_console_write(run_t *run);
+static void bi_console_writeline(run_t *run);
+
+/** Declare Console builtin.
+ *
+ * @param bi	Builtin object
+ */
+void bi_console_declare(builtin_t *bi)
+{
+	stree_modm_t *modm;
+	stree_csi_t *csi;
+	stree_ident_t *ident;
+	stree_symbol_t *symbol;
+	stree_symbol_t *fun_sym;
+
+	/* Declare class Builtin */
+
+	ident = stree_ident_new();
+	ident->sid = strtab_get_sid("Console");
+
+	csi = stree_csi_new(csi_class);
+	csi->name = ident;
+	list_init(&csi->targ);
+	list_init(&csi->members);
+
+	modm = stree_modm_new(mc_csi);
+	modm->u.csi = csi;
+
+	symbol = stree_symbol_new(sc_csi);
+	symbol->u.csi = csi;
+	symbol->outer_csi = NULL;
+	csi->symbol = symbol;
+
+	list_append(&bi->program->module->members, modm);
+
+	/* Declare Builtin.Write(). */
+
+	fun_sym = builtin_declare_fun(csi, "Write");
+	builtin_fun_add_arg(fun_sym, "arg");
+
+	/* Declare Builtin.WriteLine(). */
+
+	fun_sym = builtin_declare_fun(csi, "WriteLine");
+	builtin_fun_add_arg(fun_sym, "arg");
+}
+
+/** Bind builtin functions.
+ *
+ * @param bi	Builtin object
+ */
+void bi_console_bind(builtin_t *bi)
+{
+	builtin_fun_bind(bi, "Console", "Write", bi_console_write);
+	builtin_fun_bind(bi, "Console", "WriteLine", bi_console_writeline);
+}
+
+/** Write to the console.
+ *
+ * @param run	Runner object
+ */
+static void bi_console_write(run_t *run)
+{
+	rdata_var_t *var;
+	int char_val;
+	int rc;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Called Console.Write()\n");
+#endif
+	var = run_local_vars_lookup(run, strtab_get_sid("arg"));
+	assert(var);
+
+	switch (var->vc) {
+	case vc_bool:
+		printf("%s", var->u.bool_v->value ? "true" : "false");
+		break;
+	case vc_char:
+		rc = bigint_get_value_int(&var->u.char_v->value, &char_val);
+		if (rc == EOK)
+			printf("%lc", char_val);
+		else
+			printf("???");
+		break;
+	case vc_int:
+		bigint_print(&var->u.int_v->value);
+		break;
+	case vc_string:
+		printf("%s", var->u.string_v->value);
+		break;
+	default:
+		printf("Unimplemented: Write() with unsupported type.\n");
+		exit(1);
+	}
+}
+
+/** Write a line of output.
+ *
+ * @param run	Runner object
+ */
+static void bi_console_writeline(run_t *run)
+{
+#ifdef DEBUG_RUN_TRACE
+	printf("Called Console.WriteLine()\n");
+#endif
+	bi_console_write(run);
+	putchar('\n');
+}
Index: uspace/app/sbi/src/builtin/bi_console.h
===================================================================
--- uspace/app/sbi/src/builtin/bi_console.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
+++ uspace/app/sbi/src/builtin/bi_console.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BI_CONSOLE_H_
+#define BI_CONSOLE_H_
+
+#include "../mytypes.h"
+
+void bi_console_declare(builtin_t *bi);
+void bi_console_bind(builtin_t *bi);
+
+#endif
Index: pace/app/sbi/src/builtin/bi_fun.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_fun.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ 	(revision )
@@ -1,219 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file Builtin functions. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include "../bigint.h"
-#include "../builtin.h"
-#include "../list.h"
-#include "../mytypes.h"
-#include "../os/os.h"
-#include "../run.h"
-#include "../stree.h"
-#include "../strtab.h"
-#include "../symbol.h"
-
-#include "bi_fun.h"
-
-static void bi_fun_builtin_write(run_t *run);
-static void bi_fun_builtin_writeline(run_t *run);
-static void bi_fun_task_exec(run_t *run);
-
-/** Declare builtin functions.
- *
- * @param bi	Builtin object
- */
-void bi_fun_declare(builtin_t *bi)
-{
-	stree_modm_t *modm;
-	stree_csi_t *csi;
-	stree_ident_t *ident;
-	stree_symbol_t *symbol;
-	stree_symbol_t *fun_sym;
-
-	/* Declare class Builtin */
-
-	ident = stree_ident_new();
-	ident->sid = strtab_get_sid("Builtin");
-
-	csi = stree_csi_new(csi_class);
-	csi->name = ident;
-	list_init(&csi->targ);
-	list_init(&csi->members);
-
-	modm = stree_modm_new(mc_csi);
-	modm->u.csi = csi;
-
-	symbol = stree_symbol_new(sc_csi);
-	symbol->u.csi = csi;
-	symbol->outer_csi = NULL;
-	csi->symbol = symbol;
-
-	list_append(&bi->program->module->members, modm);
-
-	/* Declare Builtin.Write(). */
-
-	fun_sym = builtin_declare_fun(csi, "Write");
-	builtin_fun_add_arg(fun_sym, "arg");
-
-	/* Declare Builtin.WriteLine(). */
-
-	fun_sym = builtin_declare_fun(csi, "WriteLine");
-	builtin_fun_add_arg(fun_sym, "arg");
-
-	/* Declare class Task. */
-
-	builtin_code_snippet(bi,
-		"class Task is\n"
-			"fun Exec(args : string[], packed), static, builtin;\n"
-		"end\n");
-}
-
-/** Bind builtin functions.
- *
- * @param bi	Builtin object
- */
-void bi_fun_bind(builtin_t *bi)
-{
-	builtin_fun_bind(bi, "Builtin", "Write", bi_fun_builtin_write);
-	builtin_fun_bind(bi, "Builtin", "WriteLine", bi_fun_builtin_writeline);
-	builtin_fun_bind(bi, "Task", "Exec", bi_fun_task_exec);
-}
-
-/** Write to the console.
- *
- * @param run	Runner object
- */
-static void bi_fun_builtin_write(run_t *run)
-{
-	rdata_var_t *var;
-	int char_val;
-	int rc;
-
-#ifdef DEBUG_RUN_TRACE
-	printf("Called Builtin.Write()\n");
-#endif
-	var = run_local_vars_lookup(run, strtab_get_sid("arg"));
-	assert(var);
-
-	switch (var->vc) {
-	case vc_bool:
-		printf("%s", var->u.bool_v->value ? "true" : "false");
-		break;
-	case vc_char:
-		rc = bigint_get_value_int(&var->u.char_v->value, &char_val);
-		if (rc == EOK)
-			printf("%lc", char_val);
-		else
-			printf("???");
-		break;
-	case vc_int:
-		bigint_print(&var->u.int_v->value);
-		break;
-	case vc_string:
-		printf("%s", var->u.string_v->value);
-		break;
-	default:
-		printf("Unimplemented: Write() with unsupported type.\n");
-		exit(1);
-	}
-}
-
-/** Write a line of output.
- *
- * @param run	Runner object
- */
-static void bi_fun_builtin_writeline(run_t *run)
-{
-#ifdef DEBUG_RUN_TRACE
-	printf("Called Builtin.WriteLine()\n");
-#endif
-	bi_fun_builtin_write(run);
-	putchar('\n');
-}
-
-/** Start an executable and wait for it to finish.
- *
- * @param run	Runner object
- */
-static void bi_fun_task_exec(run_t *run)
-{
-	rdata_var_t *args;
-	rdata_var_t *var;
-	rdata_array_t *array;
-	rdata_var_t *arg;
-	int idx, dim;
-	const char **cmd;
-
-#ifdef DEBUG_RUN_TRACE
-	printf("Called Task.Exec()\n");
-#endif
-	args = run_local_vars_lookup(run, strtab_get_sid("args"));
-
-	assert(args);
-	assert(args->vc == vc_ref);
-
-	var = args->u.ref_v->vref;
-	assert(var->vc == vc_array);
-
-	array = var->u.array_v;
-	assert(array->rank == 1);
-	dim = array->extent[0];
-
-	if (dim == 0) {
-		printf("Error: Builtin.Exec() expects at least one argument.\n");
-		exit(1);
-	}
-
-	cmd = calloc(dim + 1, sizeof(char *));
-	if (cmd == NULL) {
-		printf("Memory allocation failed.\n");
-		exit(1);
-	}
-
-	for (idx = 0; idx < dim; ++idx) {
-		arg = array->element[idx];
-		if (arg->vc != vc_string) {
-			printf("Error: Argument to Builtin.Exec() must be "
-			    "string (found %d).\n", arg->vc);
-			exit(1);
-		}
-
-		cmd[idx] = arg->u.string_v->value;
-	}
-
-	cmd[dim] = '\0';
-
-	if (os_exec((char * const *)cmd) != EOK) {
-		printf("Error: Exec failed.\n");
-		exit(1);
-	}
-}
Index: pace/app/sbi/src/builtin/bi_fun.h
===================================================================
--- uspace/app/sbi/src/builtin/bi_fun.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ 	(revision )
@@ -1,37 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BI_FUN_H_
-#define BI_FUN_H_
-
-#include "../mytypes.h"
-
-void bi_fun_declare(builtin_t *bi);
-void bi_fun_bind(builtin_t *bi);
-
-#endif
Index: uspace/app/sbi/src/builtin/bi_task.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_task.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
+++ uspace/app/sbi/src/builtin/bi_task.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Task builtin binding. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "../builtin.h"
+#include "../list.h"
+#include "../mytypes.h"
+#include "../os/os.h"
+#include "../run.h"
+#include "../strtab.h"
+
+#include "bi_task.h"
+
+static void bi_task_exec(run_t *run);
+
+/** Declare task builtin.
+ *
+ * @param bi	Builtin object
+ */
+void bi_task_declare(builtin_t *bi)
+{
+	builtin_code_snippet(bi,
+		"class Task is\n"
+			"fun Exec(args : string[], packed), static, builtin;\n"
+		"end\n");
+}
+
+/** Bind builtin functions.
+ *
+ * @param bi	Builtin object
+ */
+void bi_task_bind(builtin_t *bi)
+{
+	builtin_fun_bind(bi, "Task", "Exec", bi_task_exec);
+}
+
+/** Start an executable and wait for it to finish.
+ *
+ * @param run	Runner object
+ */
+static void bi_task_exec(run_t *run)
+{
+	rdata_var_t *args;
+	rdata_var_t *var;
+	rdata_array_t *array;
+	rdata_var_t *arg;
+	int idx, dim;
+	const char **cmd;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Called Task.Exec()\n");
+#endif
+	args = run_local_vars_lookup(run, strtab_get_sid("args"));
+
+	assert(args);
+	assert(args->vc == vc_ref);
+
+	var = args->u.ref_v->vref;
+	assert(var->vc == vc_array);
+
+	array = var->u.array_v;
+	assert(array->rank == 1);
+	dim = array->extent[0];
+
+	if (dim == 0) {
+		printf("Error: Builtin.Exec() expects at least one argument.\n");
+		exit(1);
+	}
+
+	cmd = calloc(dim + 1, sizeof(char *));
+	if (cmd == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	for (idx = 0; idx < dim; ++idx) {
+		arg = array->element[idx];
+		if (arg->vc != vc_string) {
+			printf("Error: Argument to Builtin.Exec() must be "
+			    "string (found %d).\n", arg->vc);
+			exit(1);
+		}
+
+		cmd[idx] = arg->u.string_v->value;
+	}
+
+	cmd[dim] = '\0';
+
+	if (os_exec((char * const *)cmd) != EOK) {
+		printf("Error: Exec failed.\n");
+		exit(1);
+	}
+}
Index: uspace/app/sbi/src/builtin/bi_task.h
===================================================================
--- uspace/app/sbi/src/builtin/bi_task.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
+++ uspace/app/sbi/src/builtin/bi_task.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BI_TASK_H_
+#define BI_TASK_H_
+
+#include "../mytypes.h"
+
+void bi_task_declare(builtin_t *bi);
+void bi_task_bind(builtin_t *bi);
+
+#endif
Index: uspace/app/sbi/src/imode.c
===================================================================
--- uspace/app/sbi/src/imode.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/imode.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -178,4 +178,17 @@
 			/* Convert expression result to value item. */
 			run_cvt_value_item(&run, rexpr, &rexpr_vi);
+			rdata_item_destroy(rexpr);
+
+			/* Check for unhandled exceptions. */
+			run_exc_check_unhandled(&run);
+		} else {
+			rexpr_vi = NULL;
+		}
+
+		/*
+		 * rexpr_vi can be NULL if either repxr was null or
+		 * if the conversion to value item raised an exception.
+		 */
+		if (rexpr_vi != NULL) {
 			assert(rexpr_vi->ic == ic_value);
 
@@ -184,6 +197,10 @@
 			rdata_value_print(rexpr_vi->u.value);
 			printf("\n");
+
+			rdata_item_destroy(rexpr_vi);
 		}
 	}
+
+	run_proc_ar_destroy(&run, proc_ar);
 
 	/* Remove block visit record from the stack, */
Index: uspace/app/sbi/src/intmap.c
===================================================================
--- uspace/app/sbi/src/intmap.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/intmap.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -50,4 +50,15 @@
 }
 
+/** Deinitialize map.
+ *
+ * The map must be already empty.
+ *
+ * @param intmap	Map to initialize.
+ */
+void intmap_fini(intmap_t *intmap)
+{
+	list_fini(&intmap->elem);
+}
+
 /** Set value corresponding to a key.
  *
@@ -56,7 +67,7 @@
  * is removed from the map.
  *
- * @param intmap	Map.
- * @param key		Key (integer).
- * @param value		Value (must be a pointer) or @c NULL.
+ * @param intmap	Map
+ * @param key		Key (integer)
+ * @param value		Value (must be a pointer) or @c NULL
  */
 void intmap_set(intmap_t *intmap, int key, void *value)
@@ -75,6 +86,5 @@
 				/* Remove map element. */
 				list_remove(&intmap->elem, node);
-				node->data = NULL;
-				free(node);
+				free(elem);
 			}
 			return;
@@ -98,6 +108,6 @@
 /** Get value corresponding to a key.
  *
- * @param intmap	Map.
- * @param key		Key for which to retrieve mapping.
+ * @param intmap	Map
+ * @param key		Key for which to retrieve mapping
  *
  * @return		Value correspoding to @a key or @c NULL if no mapping
@@ -121,2 +131,45 @@
 	return NULL;
 }
+
+/** Get first element in the map.
+ *
+ * For iterating over the map, this returns the first element (in no
+ * particular order).
+ *
+ * @param intmap	Map
+ * @return		Map element or NULL if the map is empty
+ */
+map_elem_t *intmap_first(intmap_t *intmap)
+{
+	list_node_t *node;
+
+	node = list_first(&intmap->elem);
+	if (node == NULL)
+		return NULL;
+
+	return list_node_data(node, map_elem_t *);
+}
+
+/** Get element key.
+ *
+ * Giver a map element, return the key.
+ *
+ * @param elem		Map element
+ * @return		Key
+ */
+int intmap_elem_get_key(map_elem_t *elem)
+{
+	return elem->key;
+}
+
+/** Get element value.
+ *
+ * Giver a map element, return the value.
+ *
+ * @param elem		Map element
+ * @return		Value
+ */
+void *intmap_elem_get_value(map_elem_t *elem)
+{
+	return elem->value;
+}
Index: uspace/app/sbi/src/intmap.h
===================================================================
--- uspace/app/sbi/src/intmap.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/intmap.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -33,6 +33,10 @@
 
 void intmap_init(intmap_t *intmap);
+void intmap_fini(intmap_t *intmap);
 void intmap_set(intmap_t *intmap, int key, void *data);
 void *intmap_get(intmap_t *intmap, int key);
+map_elem_t *intmap_first(intmap_t *intmap);
+int intmap_elem_get_key(map_elem_t *elem);
+void *intmap_elem_get_value(map_elem_t *elem);
 
 #endif
Index: uspace/app/sbi/src/lex.c
===================================================================
--- uspace/app/sbi/src/lex.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/lex.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -45,4 +45,9 @@
 #define TAB_WIDTH 8
 
+typedef enum {
+	cs_chr,
+	cs_str
+} chr_str_t;
+
 static void lex_touch(lex_t *lex);
 static bool_t lex_read_try(lex_t *lex);
@@ -57,4 +62,5 @@
 static void lex_number(lex_t *lex);
 static void lex_string(lex_t *lex);
+static void lex_char_string_core(lex_t *lex, chr_str_t cs);
 static int digit_value(char c);
 
@@ -117,4 +123,5 @@
 	{ lc_string,	"string" },
 	{ lc_struct,	"struct" },
+	{ lc_switch,	"switch" },
 	{ lc_then,	"then" },
 	{ lc_this,	"this" },
@@ -122,4 +129,5 @@
 	{ lc_var,	"var" },
 	{ lc_with,	"with" },
+	{ lc_when,	"when" },
 	{ lc_while,	"while" },
 	{ lc_yield,	"yield" },
@@ -535,30 +543,9 @@
 static void lex_char(lex_t *lex)
 {
-	char *bp;
-	int idx;
 	size_t len;
 	int char_val;
 
-	bp = lex->ibp + 1;
-	idx = 0;
-
-	while (bp[idx] != '\'') {
-		if (idx >= SLBUF_SIZE) {
-			printf("Error: Character literal too long.\n");
-			exit(1);
-		}
-
-		if (bp[idx] == '\0') {
-			printf("Error: Unterminated character literal.\n");
-			exit(1);
-		}
-
-		strlit_buf[idx] = bp[idx];
-		++idx;
-	}
-
-	lex->ibp = bp + idx + 1;
-
-	strlit_buf[idx] = '\0';
+	lex_char_string_core(lex, cs_chr);
+
 	len = os_str_length(strlit_buf);
 	if (len != 1) {
@@ -620,31 +607,84 @@
 static void lex_string(lex_t *lex)
 {
-	char *bp;
-	int idx;
-
-	bp = lex->ibp + 1;
-	idx = 0;
-
-	while (bp[idx] != '"') {
-		if (idx >= SLBUF_SIZE) {
-			printf("Error: String literal too long.\n");
-			exit(1);
-		}
-
-		if (bp[idx] == '\0') {
-			printf("Error: Unterminated string literal.\n");
-			exit(1);
-		}
-
-		strlit_buf[idx] = bp[idx];
-		++idx;
-	}
-
-	lex->ibp = bp + idx + 1;
-
-	strlit_buf[idx] = '\0';
+	lex_char_string_core(lex, cs_str);
 
 	lex->current.lclass = lc_lit_string;
 	lex->current.u.lit_string.value = os_str_dup(strlit_buf);
+}
+
+static void lex_char_string_core(lex_t *lex, chr_str_t cs)
+{
+	char *bp;
+	int sidx, didx;
+	char term;
+	const char *descr, *cap_descr;
+	char spchar;
+
+	/* Make compiler happy */
+	term = '\0';
+	descr = NULL;
+	cap_descr = NULL;
+
+	switch (cs) {
+	case cs_chr:
+		term = '\'';
+		descr = "character";
+		cap_descr = "Character";
+		break;
+	case cs_str:
+		term = '"';
+		descr = "string";
+		cap_descr = "String";
+		break;
+	}
+
+	bp = lex->ibp + 1;
+	sidx = didx = 0;
+
+	while (bp[sidx] != term) {
+		if (didx >= SLBUF_SIZE) {
+			printf("Error: %s literal too long.\n", cap_descr);
+			exit(1);
+		}
+
+		if (bp[sidx] == '\0') {
+			printf("Error: Unterminated %s literal.\n", descr);
+			exit(1);
+		}
+
+		if (bp[sidx] == '\\') {
+			switch (bp[sidx + 1]) {
+			case '\\':
+				spchar = '\\';
+				break;
+			case '\'':
+				spchar = '\'';
+				break;
+			case '"':
+				spchar = '"';
+				break;
+			case 'n':
+				spchar = '\n';
+				break;
+			case 't':
+				spchar = '\t';
+				break;
+			default:
+				printf("Error: Unknown character escape sequence.\n");
+				exit(1);
+			}
+
+			strlit_buf[didx] = spchar;
+			++didx;
+			sidx += 2;
+		} else {
+			strlit_buf[didx] = bp[sidx];
+			++sidx; ++didx;
+		}
+	}
+
+	lex->ibp = bp + sidx + 1;
+
+	strlit_buf[didx] = '\0';
 }
 
Index: uspace/app/sbi/src/lex_t.h
===================================================================
--- uspace/app/sbi/src/lex_t.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/lex_t.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -85,4 +85,5 @@
 	lc_string,
 	lc_struct,
+	lc_switch,
 	lc_then,
 	lc_this,
@@ -90,4 +91,5 @@
 	lc_var,
 	lc_with,
+	lc_when,
 	lc_while,
 	lc_yield,
Index: uspace/app/sbi/src/list.c
===================================================================
--- uspace/app/sbi/src/list.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/list.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -57,4 +57,16 @@
 }
 
+/** Deinitialize list.
+ *
+ * @param list	List to deinitialize.
+ */
+void list_fini(list_t *list)
+{
+	assert(list_is_empty(list));
+
+	list->head.prev = NULL;
+	list->head.next = NULL;
+}
+
 /** Append data to list.
  *
Index: uspace/app/sbi/src/list.h
===================================================================
--- uspace/app/sbi/src/list.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/list.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,4 +34,5 @@
 
 void list_init(list_t *list);
+void list_fini(list_t *list);
 void list_append(list_t *list, void *data);
 void list_prepend(list_t *list, void *data);
Index: uspace/app/sbi/src/parse.c
===================================================================
--- uspace/app/sbi/src/parse.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/parse.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -82,4 +82,5 @@
 static stree_vdecl_t *parse_vdecl(parse_t *parse);
 static stree_if_t *parse_if(parse_t *parse);
+static stree_switch_t *parse_switch(parse_t *parse);
 static stree_while_t *parse_while(parse_t *parse);
 static stree_for_t *parse_for(parse_t *parse);
@@ -667,5 +668,4 @@
 	stree_prop_t *prop;
 	stree_symbol_t *symbol;
-	bool_t body_expected;
 
 	stree_ident_t *ident;
@@ -720,6 +720,4 @@
 	/* Parse attributes. */
 	parse_symbol_attrs(parse, symbol);
-
-	body_expected = (outer_csi->cc != csi_interface);
 
 	lmatch(parse, lc_is);
@@ -1070,4 +1068,5 @@
 	stree_vdecl_t *vdecl_s;
 	stree_if_t *if_s;
+	stree_switch_t *switch_s;
 	stree_while_t *while_s;
 	stree_for_t *for_s;
@@ -1092,4 +1091,9 @@
 		stat->u.if_s = if_s;
 		break;
+	case lc_switch:
+		switch_s = parse_switch(parse);
+		stat = stree_stat_new(st_switch);
+		stat->u.switch_s = switch_s;
+		break;
 	case lc_while:
 		while_s = parse_while(parse);
@@ -1214,4 +1218,58 @@
 	lmatch(parse, lc_end);
 	return if_s;
+}
+
+/** Parse @c switch statement.
+ *
+ * @param parse		Parser object.
+ * @return		New syntax tree node.
+ */
+static stree_switch_t *parse_switch(parse_t *parse)
+{
+	stree_switch_t *switch_s;
+	stree_when_t *when_c;
+	stree_expr_t *expr;
+
+#ifdef DEBUG_PARSE_TRACE
+	printf("Parse 'switch' statement.\n");
+#endif
+	lmatch(parse, lc_switch);
+
+	switch_s = stree_switch_new();
+	list_init(&switch_s->when_clauses);
+
+	switch_s->expr = parse_expr(parse);
+	lmatch(parse, lc_is);
+
+	/* Parse @c when clauses. */
+	while (lcur_lc(parse) == lc_when) {
+		lskip(parse);
+		when_c = stree_when_new();
+		list_init(&when_c->exprs);
+		while (b_true) {
+			expr = parse_expr(parse);
+			list_append(&when_c->exprs, expr);
+			if (lcur_lc(parse) != lc_comma)
+				break;
+			lskip(parse);
+		}
+
+		lmatch(parse, lc_do);
+		when_c->block = parse_block(parse);
+
+		list_append(&switch_s->when_clauses, when_c);
+	}
+
+	/* Parse @c else clause. */
+	if (lcur_lc(parse) == lc_else) {
+		lskip(parse);
+		lmatch(parse, lc_do);
+		switch_s->else_block = parse_block(parse);
+	} else {
+		switch_s->else_block = NULL;
+	}
+
+	lmatch(parse, lc_end);
+	return switch_s;
 }
 
@@ -1654,4 +1712,5 @@
 	case lc_except:
 	case lc_finally:
+	case lc_when:
 		return b_true;
 	default:
Index: uspace/app/sbi/src/rdata.c
===================================================================
--- uspace/app/sbi/src/rdata.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/rdata.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -49,4 +49,5 @@
 #include <assert.h>
 #include "bigint.h"
+#include "list.h"
 #include "mytypes.h"
 #include "stree.h"
@@ -69,5 +70,20 @@
 static void rdata_symbol_copy(rdata_symbol_t *src, rdata_symbol_t **dest);
 
+static void rdata_var_destroy_inner(rdata_var_t *var);
+
+static void rdata_bool_destroy(rdata_bool_t *bool_v);
+static void rdata_char_destroy(rdata_char_t *char_v);
+static void rdata_int_destroy(rdata_int_t *int_v);
+static void rdata_string_destroy(rdata_string_t *string_v);
+static void rdata_ref_destroy(rdata_ref_t *ref_v);
+static void rdata_deleg_destroy(rdata_deleg_t *deleg_v);
+static void rdata_enum_destroy(rdata_enum_t *enum_v);
+static void rdata_array_destroy(rdata_array_t *array_v);
+static void rdata_object_destroy(rdata_object_t *object_v);
+static void rdata_resource_destroy(rdata_resource_t *resource_v);
+static void rdata_symbol_destroy(rdata_symbol_t *symbol_v);
+
 static int rdata_array_get_dim(rdata_array_t *array);
+static void rdata_var_copy_to(rdata_var_t *src, rdata_var_t *dest);
 
 static void rdata_address_print(rdata_address_t *address);
@@ -414,5 +430,5 @@
 /** Allocate array elements.
  *
- * Allocates var nodes for elements of @a array.
+ * Allocates element array of @a array.
  *
  * @param array		Array.
@@ -420,5 +436,5 @@
 void rdata_array_alloc_element(rdata_array_t *array)
 {
-	int dim, idx;
+	int dim;
 
 	dim = rdata_array_get_dim(array);
@@ -428,12 +444,4 @@
 		printf("Memory allocation failed.\n");
 		exit(1);
-	}
-
-	for (idx = 0; idx < dim; ++idx) {
-		array->element[idx] = calloc(1, sizeof(rdata_var_t));
-		if (array->element[idx] == NULL) {
-			printf("Memory allocation failed.\n");
-			exit(1);
-		}
 	}
 }
@@ -457,4 +465,207 @@
 }
 
+/** Deallocate item.
+ *
+ * @param item	Item node
+ */
+void rdata_item_delete(rdata_item_t *item)
+{
+	assert(item != NULL);
+	free(item);
+}
+
+/** Deallocate variable address.
+ *
+ * @param addr_var	Variable address node
+ */
+void rdata_addr_var_delete(rdata_addr_var_t *addr_var)
+{
+	assert(addr_var != NULL);
+	free(addr_var);
+}
+
+/** Deallocate property address.
+ *
+ * @param addr_prop	Variable address node
+ */
+void rdata_addr_prop_delete(rdata_addr_prop_t *addr_prop)
+{
+	assert(addr_prop != NULL);
+	free(addr_prop);
+}
+
+/** Deallocate named property address.
+ *
+ * @param aprop_named	Variable address node
+ */
+void rdata_aprop_named_delete(rdata_aprop_named_t *aprop_named)
+{
+	assert(aprop_named != NULL);
+	free(aprop_named);
+}
+
+/** Deallocate indexed property address.
+ *
+ * @param aprop_indexed	Variable address node
+ */
+void rdata_aprop_indexed_delete(rdata_aprop_indexed_t *aprop_indexed)
+{
+	assert(aprop_indexed != NULL);
+	free(aprop_indexed);
+}
+
+/** Deallocate address.
+ *
+ * @param address	Address node
+ */
+void rdata_address_delete(rdata_address_t *address)
+{
+	assert(address != NULL);
+	free(address);
+}
+
+/** Deallocate value.
+ *
+ * @param value		Value node
+ */
+void rdata_value_delete(rdata_value_t *value)
+{
+	assert(value != NULL);
+	free(value);
+}
+
+/** Deallocate var node.
+ *
+ * @param var	Var node
+ */
+void rdata_var_delete(rdata_var_t *var)
+{
+	assert(var != NULL);
+	free(var);
+}
+
+/** Deallocate boolean.
+ *
+ * @param bool_v		Boolean
+ */
+void rdata_bool_delete(rdata_bool_t *bool_v)
+{
+	assert(bool_v != NULL);
+	free(bool_v);
+}
+
+/** Deallocate character.
+ *
+ * @param char_v	Character
+ */
+void rdata_char_delete(rdata_char_t *char_v)
+{
+	assert(char_v != NULL);
+	free(char_v);
+}
+
+/** Deallocate integer.
+ *
+ * @param int_v		Integer
+ */
+void rdata_int_delete(rdata_int_t *int_v)
+{
+	assert(int_v != NULL);
+	free(int_v);
+}
+
+/** Deallocate string.
+ *
+ * @param string_v	String
+ */
+void rdata_string_delete(rdata_string_t *string_v)
+{
+	assert(string_v != NULL);
+	free(string_v);
+}
+
+/** Deallocate reference.
+ *
+ * @param ref_v		Reference
+ */
+void rdata_ref_delete(rdata_ref_t *ref_v)
+{
+	assert(ref_v != NULL);
+	free(ref_v);
+}
+
+/** Deallocate delegate.
+ *
+ * @param deleg_v		Reference
+ */
+void rdata_deleg_delete(rdata_deleg_t *deleg_v)
+{
+	assert(deleg_v != NULL);
+	free(deleg_v);
+}
+
+/** Deallocate enum.
+ *
+ * @param enum_v		Reference
+ */
+void rdata_enum_delete(rdata_enum_t *enum_v)
+{
+	assert(enum_v != NULL);
+	free(enum_v);
+}
+
+/** Deallocate array.
+ *
+ * @param array_v		Array
+ */
+void rdata_array_delete(rdata_array_t *array_v)
+{
+	assert(array_v != NULL);
+	free(array_v);
+}
+
+/** Deallocate object.
+ *
+ * @param object_v		Object
+ */
+void rdata_object_delete(rdata_object_t *object_v)
+{
+	assert(object_v != NULL);
+	free(object_v);
+}
+
+/** Deallocate resource.
+ *
+ * @param resource_v		Resource
+ */
+void rdata_resource_delete(rdata_resource_t *resource_v)
+{
+	assert(resource_v != NULL);
+	free(resource_v);
+}
+
+/** Deallocate symbol.
+ *
+ * @param symbol_v		Symbol
+ */
+void rdata_symbol_delete(rdata_symbol_t *symbol_v)
+{
+	assert(symbol_v != NULL);
+	free(symbol_v);
+}
+
+/** Copy value.
+ *
+ * @param src		Input value
+ * @param dest		Place to store pointer to new value
+ */
+void rdata_value_copy(rdata_value_t *src, rdata_value_t **dest)
+{
+	assert(src != NULL);
+
+	*dest = rdata_value_new();
+	rdata_var_copy(src->var, &(*dest)->var);
+}
+
 /** Make copy of a variable.
  *
@@ -470,48 +681,64 @@
 
 	nvar = rdata_var_new(src->vc);
+	rdata_var_copy_to(src, nvar);
+
+	*dest = nvar;
+}
+
+/** Copy variable content to another variable.
+ *
+ * Writes an exact copy of an existing var node to another var node.
+ * The varclass of @a src and @a dest must match. The content of
+ * @a dest.u must be invalid.
+ *
+ * @param src		Source var node.
+ * @param dest		Destination var node.
+ */
+static void rdata_var_copy_to(rdata_var_t *src, rdata_var_t *dest)
+{
+	dest->vc = src->vc;
 
 	switch (src->vc) {
 	case vc_bool:
-		rdata_bool_copy(src->u.bool_v, &nvar->u.bool_v);
+		rdata_bool_copy(src->u.bool_v, &dest->u.bool_v);
 		break;
 	case vc_char:
-		rdata_char_copy(src->u.char_v, &nvar->u.char_v);
+		rdata_char_copy(src->u.char_v, &dest->u.char_v);
 		break;
 	case vc_int:
-		rdata_int_copy(src->u.int_v, &nvar->u.int_v);
+		rdata_int_copy(src->u.int_v, &dest->u.int_v);
 		break;
 	case vc_string:
-		rdata_string_copy(src->u.string_v, &nvar->u.string_v);
+		rdata_string_copy(src->u.string_v, &dest->u.string_v);
 		break;
 	case vc_ref:
-		rdata_ref_copy(src->u.ref_v, &nvar->u.ref_v);
+		rdata_ref_copy(src->u.ref_v, &dest->u.ref_v);
 		break;
 	case vc_deleg:
-		rdata_deleg_copy(src->u.deleg_v, &nvar->u.deleg_v);
+		rdata_deleg_copy(src->u.deleg_v, &dest->u.deleg_v);
 		break;
 	case vc_enum:
-		rdata_enum_copy(src->u.enum_v, &nvar->u.enum_v);
+		rdata_enum_copy(src->u.enum_v, &dest->u.enum_v);
 		break;
 	case vc_array:
-		rdata_array_copy(src->u.array_v, &nvar->u.array_v);
+		rdata_array_copy(src->u.array_v, &dest->u.array_v);
 		break;
 	case vc_object:
-		rdata_object_copy(src->u.object_v, &nvar->u.object_v);
+		rdata_object_copy(src->u.object_v, &dest->u.object_v);
 		break;
 	case vc_resource:
-		rdata_resource_copy(src->u.resource_v, &nvar->u.resource_v);
+		rdata_resource_copy(src->u.resource_v, &dest->u.resource_v);
 		break;
 	case vc_symbol:
-		rdata_symbol_copy(src->u.symbol_v, &nvar->u.symbol_v);
-		break;
-	}
-
-	*dest = nvar;
-}
+		rdata_symbol_copy(src->u.symbol_v, &dest->u.symbol_v);
+		break;
+	}
+}
+
 
 /** Copy boolean.
  *
- * @param src		Source boolean.
- * @param dest		Place to store pointer to new boolean.
+ * @param src		Source boolean
+ * @param dest		Place to store pointer to new boolean
  */
 static void rdata_bool_copy(rdata_bool_t *src, rdata_bool_t **dest)
@@ -523,6 +750,6 @@
 /** Copy character.
  *
- * @param src		Source character.
- * @param dest		Place to store pointer to new character.
+ * @param src		Source character
+ * @param dest		Place to store pointer to new character
  */
 static void rdata_char_copy(rdata_char_t *src, rdata_char_t **dest)
@@ -534,6 +761,6 @@
 /** Copy integer.
  *
- * @param src		Source integer.
- * @param dest		Place to store pointer to new integer.
+ * @param src		Source integer
+ * @param dest		Place to store pointer to new integer
  */
 static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest)
@@ -632,4 +859,355 @@
 	*dest = rdata_symbol_new();
 	(*dest)->sym = src->sym;
+}
+
+/** Destroy var node.
+ *
+ * @param var	Var node
+ */
+void rdata_var_destroy(rdata_var_t *var)
+{
+	/* First destroy class-specific part */
+	rdata_var_destroy_inner(var);
+
+	/* Deallocate var node */
+	rdata_var_delete(var);
+}
+
+/** Destroy inside of var node.
+ *
+ * Destroy content of var node, but do not deallocate the var node
+ * itself.
+ *
+ * @param var	Var node
+ */
+static void rdata_var_destroy_inner(rdata_var_t *var)
+{
+	/* First destroy class-specific part */
+
+	switch (var->vc) {
+	case vc_bool:
+		rdata_bool_destroy(var->u.bool_v);
+		break;
+	case vc_char:
+		rdata_char_destroy(var->u.char_v);
+		break;
+	case vc_int:
+		rdata_int_destroy(var->u.int_v);
+		break;
+	case vc_string:
+		rdata_string_destroy(var->u.string_v);
+		break;
+	case vc_ref:
+		rdata_ref_destroy(var->u.ref_v);
+		break;
+	case vc_deleg:
+		rdata_deleg_destroy(var->u.deleg_v);
+		break;
+	case vc_enum:
+		rdata_enum_destroy(var->u.enum_v);
+		break;
+	case vc_array:
+		rdata_array_destroy(var->u.array_v);
+		break;
+	case vc_object:
+		rdata_object_destroy(var->u.object_v);
+		break;
+	case vc_resource:
+		rdata_resource_destroy(var->u.resource_v);
+		break;
+	case vc_symbol:
+		rdata_symbol_destroy(var->u.symbol_v);
+		break;
+	}
+}
+
+/** Destroy item.
+ *
+ * Destroy an item including the value or address within.
+ *
+ * @param item	Item
+ */
+void rdata_item_destroy(rdata_item_t *item)
+{
+	/* First destroy class-specific part */
+
+	switch (item->ic) {
+	case ic_address:
+		rdata_address_destroy(item->u.address);
+		break;
+	case ic_value:
+		rdata_value_destroy(item->u.value);
+		break;
+	}
+
+	/* Deallocate item node */
+	rdata_item_delete(item);
+}
+
+/** Destroy address.
+ *
+ * Destroy an address node.
+ *
+ * @param address	Address
+ */
+void rdata_address_destroy(rdata_address_t *address)
+{
+	switch (address->ac) {
+	case ac_var:
+		rdata_addr_var_destroy(address->u.var_a);
+		break;
+	case ac_prop:
+		rdata_addr_prop_destroy(address->u.prop_a);
+		break;
+	}
+
+	/* Deallocate address node */
+	rdata_address_delete(address);
+}
+
+/** Destroy variable address.
+ *
+ * Destroy a variable address node.
+ *
+ * @param addr_var	Variable address
+ */
+void rdata_addr_var_destroy(rdata_addr_var_t *addr_var)
+{
+	addr_var->vref = NULL;
+
+	/* Deallocate variable address node */
+	rdata_addr_var_delete(addr_var);
+}
+
+/** Destroy property address.
+ *
+ * Destroy a property address node.
+ *
+ * @param addr_prop	Property address
+ */
+void rdata_addr_prop_destroy(rdata_addr_prop_t *addr_prop)
+{
+	switch (addr_prop->apc) {
+	case apc_named:
+		rdata_aprop_named_destroy(addr_prop->u.named);
+		break;
+	case apc_indexed:
+		rdata_aprop_indexed_destroy(addr_prop->u.indexed);
+		break;
+	}
+
+	if (addr_prop->tvalue != NULL) {
+		rdata_value_destroy(addr_prop->tvalue);
+		addr_prop->tvalue = NULL;
+	}
+
+	addr_prop->tpos = NULL;
+
+	/* Deallocate property address node */
+	rdata_addr_prop_delete(addr_prop);
+}
+
+/** Destroy named property address.
+ *
+ * Destroy a named property address node.
+ *
+ * @param aprop_named	Named property address
+ */
+void rdata_aprop_named_destroy(rdata_aprop_named_t *aprop_named)
+{
+	rdata_deleg_destroy(aprop_named->prop_d);
+
+	/* Deallocate named property address node */
+	rdata_aprop_named_delete(aprop_named);
+}
+
+/** Destroy indexed property address.
+ *
+ * Destroy a indexed property address node.
+ *
+ * @param aprop_indexed		Indexed property address
+ */
+void rdata_aprop_indexed_destroy(rdata_aprop_indexed_t *aprop_indexed)
+{
+	list_node_t *arg_node;
+	rdata_item_t *arg_i;
+
+	/* Destroy the object delegate. */
+	rdata_deleg_destroy(aprop_indexed->object_d);
+
+	/*
+	 * Walk through all argument items (indices) and destroy them,
+	 * removing them from the list as well.
+	 */
+	while (!list_is_empty(&aprop_indexed->args)) {
+		arg_node = list_first(&aprop_indexed->args);
+		arg_i = list_node_data(arg_node, rdata_item_t *);
+
+		rdata_item_destroy(arg_i);
+		list_remove(&aprop_indexed->args, arg_node);
+	}
+
+	/* Destroy the now empty list */
+	list_fini(&aprop_indexed->args);
+
+	/* Deallocate indexed property address node */
+	rdata_aprop_indexed_delete(aprop_indexed);
+}
+
+/** Destroy value.
+ *
+ * Destroy a value node.
+ *
+ * @param value		Value
+ */
+void rdata_value_destroy(rdata_value_t *value)
+{
+	/* Assumption: Var nodes in values are not shared. */
+	rdata_var_destroy(value->var);
+
+	/* Deallocate value node */
+	rdata_value_delete(value);
+}
+
+/** Destroy boolean.
+ *
+ * @param bool_v		Boolean
+ */
+static void rdata_bool_destroy(rdata_bool_t *bool_v)
+{
+	rdata_bool_delete(bool_v);
+}
+
+/** Destroy character.
+ *
+ * @param char_v	Character
+ */
+static void rdata_char_destroy(rdata_char_t *char_v)
+{
+	bigint_destroy(&char_v->value);
+	rdata_char_delete(char_v);
+}
+
+/** Destroy integer.
+ *
+ * @param int_v		Integer
+ */
+static void rdata_int_destroy(rdata_int_t *int_v)
+{
+	bigint_destroy(&int_v->value);
+	rdata_int_delete(int_v);
+}
+
+/** Destroy string.
+ *
+ * @param string_v	String
+ */
+static void rdata_string_destroy(rdata_string_t *string_v)
+{
+	/*
+	 * String values are shared so we cannot free them. Just deallocate
+	 * the node.
+	 */
+	rdata_string_delete(string_v);
+}
+
+/** Destroy reference.
+ *
+ * @param ref_v		Reference
+ */
+static void rdata_ref_destroy(rdata_ref_t *ref_v)
+{
+	ref_v->vref = NULL;
+	rdata_ref_delete(ref_v);
+}
+
+/** Destroy delegate.
+ *
+ * @param deleg_v		Reference
+ */
+static void rdata_deleg_destroy(rdata_deleg_t *deleg_v)
+{
+	deleg_v->obj = NULL;
+	deleg_v->sym = NULL;
+	rdata_deleg_delete(deleg_v);
+}
+
+/** Destroy enum.
+ *
+ * @param enum_v		Reference
+ */
+static void rdata_enum_destroy(rdata_enum_t *enum_v)
+{
+	enum_v->value = NULL;
+	rdata_enum_delete(enum_v);
+}
+
+/** Destroy array.
+ *
+ * @param array_v		Array
+ */
+static void rdata_array_destroy(rdata_array_t *array_v)
+{
+	int d;
+	size_t n_elems, p;
+
+	/*
+	 * Compute total number of elements in array.
+	 * At the same time zero out the extent array.
+	 */
+	n_elems = 1;
+	for (d = 0; d < array_v->rank; d++) {
+		n_elems = n_elems * array_v->extent[d];
+		array_v->extent[d] = 0;
+	}
+
+	/* Destroy all elements and zero out the array */
+	for (p = 0; p < n_elems; p++) {
+		rdata_var_delete(array_v->element[p]);
+		array_v->element[p] = NULL;
+	}
+
+	/* Free the arrays */
+	free(array_v->element);
+	free(array_v->extent);
+
+	array_v->rank = 0;
+
+	/* Deallocate the node */
+	rdata_array_delete(array_v);
+}
+
+/** Destroy object.
+ *
+ * @param object_v		Object
+ */
+static void rdata_object_destroy(rdata_object_t *object_v)
+{
+	/* XXX TODO */
+	rdata_object_delete(object_v);
+}
+
+/** Destroy resource.
+ *
+ * @param resource_v		Resource
+ */
+static void rdata_resource_destroy(rdata_resource_t *resource_v)
+{
+	/*
+	 * XXX Presumably this should be handled by the appropriate
+	 * built-in module, so, some call-back function would be required.
+	 */
+	resource_v->data = NULL;
+	rdata_resource_delete(resource_v);
+}
+
+/** Destroy symbol.
+ *
+ * @param symbol_v		Symbol
+ */
+static void rdata_symbol_destroy(rdata_symbol_t *symbol_v)
+{
+	symbol_v->sym = NULL;
+	rdata_symbol_delete(symbol_v);
 }
 
@@ -671,27 +1249,9 @@
 void rdata_var_write(rdata_var_t *var, rdata_value_t *value)
 {
-	rdata_var_t *nvar;
+	/* Free old content of var->u */
+	rdata_var_destroy_inner(var);
 
 	/* Perform a shallow copy of @c value->var. */
-	rdata_var_copy(value->var, &nvar);
-
-	/* XXX do this in a prettier way. */
-
-	var->vc = nvar->vc;
-	switch (nvar->vc) {
-	case vc_bool: var->u.bool_v = nvar->u.bool_v; break;
-	case vc_char: var->u.char_v = nvar->u.char_v; break;
-	case vc_int: var->u.int_v = nvar->u.int_v; break;
-	case vc_string: var->u.string_v = nvar->u.string_v; break;
-	case vc_ref: var->u.ref_v = nvar->u.ref_v; break;
-	case vc_deleg: var->u.deleg_v = nvar->u.deleg_v; break;
-	case vc_enum: var->u.enum_v = nvar->u.enum_v; break;
-	case vc_array: var->u.array_v = nvar->u.array_v; break;
-	case vc_object: var->u.object_v = nvar->u.object_v; break;
-	case vc_resource: var->u.resource_v = nvar->u.resource_v; break;
-	case vc_symbol: var->u.symbol_v = nvar->u.symbol_v; break;
-	}
-
-	/* XXX We should free some stuff around here. */
+	rdata_var_copy_to(value->var, var);
 }
 
Index: uspace/app/sbi/src/rdata.h
===================================================================
--- uspace/app/sbi/src/rdata.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/rdata.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -41,4 +41,5 @@
 
 rdata_var_t *rdata_var_new(var_class_t vc);
+void rdata_var_delete(rdata_var_t *var);
 rdata_ref_t *rdata_ref_new(void);
 rdata_deleg_t *rdata_deleg_new(void);
@@ -53,6 +54,37 @@
 rdata_symbol_t *rdata_symbol_new(void);
 
+void rdata_address_delete(rdata_address_t *address);
+void rdata_value_delete(rdata_value_t *value);
+void rdata_var_delete(rdata_var_t *var);
+void rdata_item_delete(rdata_item_t *item);
+void rdata_addr_var_delete(rdata_addr_var_t *addr_var);
+void rdata_addr_prop_delete(rdata_addr_prop_t *addr_prop);
+void rdata_aprop_named_delete(rdata_aprop_named_t *aprop_named);
+void rdata_aprop_indexed_delete(rdata_aprop_indexed_t *aprop_indexed);
+
+void rdata_bool_delete(rdata_bool_t *bool_v);
+void rdata_char_delete(rdata_char_t *char_v);
+void rdata_int_delete(rdata_int_t *int_v);
+void rdata_string_delete(rdata_string_t *string_v);
+void rdata_ref_delete(rdata_ref_t *ref_v);
+void rdata_deleg_delete(rdata_deleg_t *deleg_v);
+void rdata_enum_delete(rdata_enum_t *enum_v);
+void rdata_array_delete(rdata_array_t *array_v);
+void rdata_object_delete(rdata_object_t *object_v);
+void rdata_resource_delete(rdata_resource_t *resource_v);
+void rdata_symbol_delete(rdata_symbol_t *symbol_v);
+
 void rdata_array_alloc_element(rdata_array_t *array);
+void rdata_value_copy(rdata_value_t *val, rdata_value_t **rval);
 void rdata_var_copy(rdata_var_t *src, rdata_var_t **dest);
+
+void rdata_address_destroy(rdata_address_t *address);
+void rdata_addr_var_destroy(rdata_addr_var_t *addr_var);
+void rdata_addr_prop_destroy(rdata_addr_prop_t *addr_prop);
+void rdata_aprop_named_destroy(rdata_aprop_named_t *aprop_named);
+void rdata_aprop_indexed_destroy(rdata_aprop_indexed_t *aprop_indexed);
+void rdata_value_destroy(rdata_value_t *value);
+void rdata_var_destroy(rdata_var_t *var);
+void rdata_item_destroy(rdata_item_t *item);
 
 void rdata_var_read(rdata_var_t *var, rdata_item_t **ritem);
Index: uspace/app/sbi/src/rdata_t.h
===================================================================
--- uspace/app/sbi/src/rdata_t.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/rdata_t.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -272,6 +272,9 @@
 typedef struct rdata_value {
 	/**
-	 * Read-only Variable holding a copy of the data. The same @c var
-	 * can be shared between different instances of @c rdata_value_t.
+	 * Read-only Variable holding a copy of the data. Currently we don't
+	 * allow sharing the same @c var node between different value nodes
+	 * so that when destroying the value we can destroy the var.
+	 *
+	 * We could share this, but would need to reference-count it.
 	 */
 	rdata_var_t *var;
Index: uspace/app/sbi/src/run.c
===================================================================
--- uspace/app/sbi/src/run.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/run.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -53,4 +53,5 @@
 static void run_vdecl(run_t *run, stree_vdecl_t *vdecl);
 static void run_if(run_t *run, stree_if_t *if_s);
+static void run_switch(run_t *run, stree_switch_t *switch_s);
 static void run_while(run_t *run, stree_while_t *while_s);
 static void run_raise(run_t *run, stree_raise_t *raise_s);
@@ -142,4 +143,5 @@
 	run_proc_ar_set_args(run, proc_ar, &main_args);
 	run_proc(run, proc_ar, &res);
+	run_proc_ar_destroy(run, proc_ar);
 
 	run_exc_check_unhandled(run);
@@ -272,4 +274,7 @@
 	assert(list_node_data(node, run_block_ar_t *) == block_ar);
 	list_remove(&proc_ar->block_ar, node);
+
+	/* Deallocate block activation record. */
+	run_block_ar_destroy(run, block_ar);
 }
 
@@ -303,4 +308,7 @@
 		run_if(run, stat->u.if_s);
 		break;
+	case st_switch:
+		run_switch(run, stat->u.switch_s);
+		break;
 	case st_while:
 		run_while(run, stat->u.while_s);
@@ -342,4 +350,9 @@
 	run_expr(run, exps->expr, &rexpr);
 
+	/*
+	 * If the expression has a value, the caller should have asked for it.
+	 */
+	assert(res != NULL || rexpr == NULL);
+
 	if (res != NULL)
 		*res = rexpr;
@@ -355,15 +368,10 @@
 	run_block_ar_t *block_ar;
 	rdata_var_t *var, *old_var;
-	tdata_item_t *var_ti;
 
 #ifdef DEBUG_RUN_TRACE
 	printf("Executing variable declaration statement.\n");
 #endif
-	/* Compute variable type. XXX Memoize. */
-	run_texpr(run->program, run_get_current_csi(run), vdecl->type,
-	    &var_ti);
-
 	/* Create variable and initialize with default value. */
-	run_var_new(run, var_ti, &var);
+	run_var_new(run, vdecl->titem, &var);
 
 	block_ar = run_get_current_block_ar(run);
@@ -393,5 +401,5 @@
 	list_node_t *ifc_node;
 	stree_if_clause_t *ifc;
-	bool_t clause_fired;
+	bool_t rcond_b, clause_fired;
 
 #ifdef DEBUG_RUN_TRACE
@@ -411,5 +419,8 @@
 			return;
 
-		if (run_item_boolean_value(run, rcond) == b_true) {
+		rcond_b = run_item_boolean_value(run, rcond);
+		rdata_item_destroy(rcond);
+
+		if (rcond_b == b_true) {
 #ifdef DEBUG_RUN_TRACE
 			printf("Taking non-default path.\n");
@@ -436,4 +447,106 @@
 }
 
+/** Run @c switch statement.
+ *
+ * @param run		Runner object
+ * @param switch_s	Switch statement to run
+ */
+static void run_switch(run_t *run, stree_switch_t *switch_s)
+{
+	rdata_item_t *rsexpr, *rsexpr_vi;
+	rdata_item_t *rwexpr, *rwexpr_vi;
+	list_node_t *whenc_node;
+	stree_when_t *whenc;
+	list_node_t *expr_node;
+	stree_expr_t *expr;
+	bool_t clause_fired;
+	bool_t equal;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing switch statement.\n");
+#endif
+	rsexpr_vi = NULL;
+
+	/* Evaluate switch expression */
+	run_expr(run, switch_s->expr, &rsexpr);
+	if (run_is_bo(run))
+		goto cleanup;
+
+	/* Convert to value item */
+	run_cvt_value_item(run, rsexpr, &rsexpr_vi);
+	rdata_item_destroy(rsexpr);
+	if (run_is_bo(run))
+		goto cleanup;
+
+	clause_fired = b_false;
+	whenc_node = list_first(&switch_s->when_clauses);
+
+	/* Walk through all when clauses and see if they fire. */
+
+	while (whenc_node != NULL) {
+		/* Get when clause */
+		whenc = list_node_data(whenc_node, stree_when_t *);
+
+		expr_node = list_first(&whenc->exprs);
+
+		/* Walk through all expressions in the when clause */
+		while (expr_node != NULL) {
+			/* Get expression */
+			expr = list_node_data(expr_node, stree_expr_t *);
+
+			/* Evaluate expression */
+			run_expr(run, expr, &rwexpr);
+			if (run_is_bo(run))
+				goto cleanup;
+
+			/* Convert to value item */
+			run_cvt_value_item(run, rwexpr, &rwexpr_vi);
+			rdata_item_destroy(rwexpr);
+			if (run_is_bo(run)) {
+				rdata_item_destroy(rwexpr_vi);
+				goto cleanup;
+			}
+
+			/* Check if values are equal ('==') */
+			run_equal(run, rsexpr_vi->u.value,
+			    rwexpr_vi->u.value, &equal);
+			rdata_item_destroy(rwexpr_vi);
+			if (run_is_bo(run))
+				goto cleanup;
+
+			if (equal) {
+#ifdef DEBUG_RUN_TRACE
+				printf("Taking non-default path.\n");
+#endif
+				run_block(run, whenc->block);
+				clause_fired = b_true;
+				break;
+			}
+
+			expr_node = list_next(&whenc->exprs, expr_node);
+		}
+
+		if (clause_fired)
+			break;
+
+		whenc_node = list_next(&switch_s->when_clauses, whenc_node);
+	}
+
+	/* If no when clause fired, invoke the else clause. */
+	if (clause_fired == b_false && switch_s->else_block != NULL) {
+#ifdef DEBUG_RUN_TRACE
+		printf("Taking default path.\n");
+#endif
+		run_block(run, switch_s->else_block);
+	}
+cleanup:
+	if (rsexpr_vi != NULL)
+		rdata_item_destroy(rsexpr_vi);
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Switch statement terminated.\n");
+#endif
+}
+
 /** Run @c while statement.
  *
@@ -453,4 +566,5 @@
 
 	while (run_item_boolean_value(run, rcond) == b_true) {
+		rdata_item_destroy(rcond);
 		run_block(run, while_s->body);
 		run_expr(run, while_s->cond, &rcond);
@@ -459,4 +573,7 @@
 	}
 
+	if (rcond != NULL)
+		rdata_item_destroy(rcond);
+
 	if (run->thread_ar->bo_mode == bm_stat) {
 		/* Bailout due to break statement */
@@ -487,4 +604,7 @@
 
 	run_cvt_value_item(run, rexpr, &rexpr_vi);
+	rdata_item_destroy(rexpr);
+	if (run_is_bo(run))
+		return;
 
 	/* Store expression cspan in thread AR. */
@@ -492,4 +612,5 @@
 
 	/* Store expression result in thread AR. */
+	/* XXX rexpr_vi is leaked here, we only return ->u.value */
 	run->thread_ar->exc_payload = rexpr_vi->u.value;
 
@@ -541,4 +662,7 @@
 
 		run_cvt_value_item(run, rexpr, &rexpr_vi);
+		rdata_item_destroy(rexpr);
+		if (run_is_bo(run))
+			return;
 
 		/* Store expression result in procedure AR. */
@@ -632,16 +756,11 @@
 {
 	stree_csi_t *exc_csi;
-	tdata_item_t *etype;
 
 	/* Get CSI of active exception. */
 	exc_csi = run_exc_payload_get_csi(run);
 
-	/* Evaluate type expression in except clause. */
-	run_texpr(run->program, run_get_current_csi(run), except_c->etype,
-	    &etype);
-
 	/* Determine if active exc. is derived from type in exc. clause. */
 	/* XXX This is wrong, it does not work with generics. */
-	return tdata_is_csi_derived_from_ti(exc_csi, etype);
+	return tdata_is_csi_derived_from_ti(exc_csi, except_c->titem);
 }
 
@@ -1009,5 +1128,5 @@
 	(void) run;
 
-	/* Create function activation record. */
+	/* Create procedure activation record. */
 	proc_ar = run_proc_ar_new();
 	proc_ar->obj = obj;
@@ -1024,4 +1143,31 @@
 	*rproc_ar = proc_ar;
 }
+
+/** Destroy a procedure AR.
+ *
+ * @param run		Runner object
+ * @param proc_ar	Pointer to procedure activation record
+ */
+void run_proc_ar_destroy(run_t *run, run_proc_ar_t *proc_ar)
+{
+	list_node_t *ar_node;
+	run_block_ar_t *block_ar;
+
+	(void) run;
+
+	/* Destroy special block activation record. */
+	ar_node = list_first(&proc_ar->block_ar);
+	block_ar = list_node_data(ar_node, run_block_ar_t *);
+	list_remove(&proc_ar->block_ar, ar_node);
+	run_block_ar_destroy(run, block_ar);
+
+	/* Destroy procedure activation record. */
+	proc_ar->obj = NULL;
+	proc_ar->proc = NULL;
+	list_fini(&proc_ar->block_ar);
+	proc_ar->retval = NULL;
+	run_proc_ar_delete(proc_ar);
+}
+
 
 /** Fill arguments in a procedure AR.
@@ -1055,4 +1201,5 @@
 	rdata_ref_t *ref;
 	rdata_array_t *array;
+	rdata_var_t *elem_var;
 	int n_vargs, idx;
 
@@ -1147,5 +1294,6 @@
 			assert(rarg->ic == ic_value);
 
-			rdata_var_write(array->element[idx], rarg->u.value);
+			run_value_item_to_var(rarg, &elem_var);
+			array->element[idx] = elem_var;
 
 			rarg_n = list_next(arg_vals, rarg_n);
@@ -1241,4 +1389,34 @@
 }
 
+/** Destroy a block AR.
+ *
+ * @param run		Runner object
+ * @param proc_ar	Pointer to block activation record
+ */
+void run_block_ar_destroy(run_t *run, run_block_ar_t *block_ar)
+{
+	map_elem_t *elem;
+	rdata_var_t *var;
+	int key;
+
+	(void) run;
+
+	elem = intmap_first(&block_ar->vars);
+	while (elem != NULL) {
+		/* Destroy the variable */
+		var = intmap_elem_get_value(elem);
+		rdata_var_destroy(var);
+
+		/* Remove the map element */
+		key = intmap_elem_get_key(elem);
+		intmap_set(&block_ar->vars, key, NULL);
+
+		elem = intmap_first(&block_ar->vars);
+	}
+
+	intmap_fini(&block_ar->vars);
+	run_block_ar_delete(block_ar);
+}
+
 /** Convert item to value item.
  *
@@ -1269,7 +1447,7 @@
 	}
 
-	/* It already is a value, we can share the @c var. */
+	/* Make a copy of the var node within. */
 	value = rdata_value_new();
-	value->var = item->u.value->var;
+	rdata_var_copy(item->u.value->var, &value->var);
 	*ritem = rdata_item_new(ic_value);
 	(*ritem)->u.value = value;
@@ -1358,4 +1536,5 @@
 {
 	(void) run;
+	assert(ritem != NULL);
 
 	switch (address->ac) {
@@ -1368,5 +1547,5 @@
 	}
 
-	assert((*ritem)->ic == ic_value);
+	assert(*ritem == NULL || (*ritem)->ic == ic_value);
 }
 
@@ -1457,4 +1636,7 @@
 	run_proc(run, proc_ar, ritem);
 
+	/* Destroy procedure activation record. */
+	run_proc_ar_destroy(run, proc_ar);
+
 #ifdef DEBUG_RUN_TRACE
 	printf("Getter returns ");
@@ -1529,4 +1711,7 @@
 	/* Setter should not return a value. */
 	assert(ritem == NULL);
+
+	/* Destroy procedure activation record. */
+	run_proc_ar_destroy(run, proc_ar);
 
 #ifdef DEBUG_RUN_TRACE
@@ -1590,4 +1775,9 @@
 #endif
 	run_cvt_value_item(run, ref, &ref_val);
+	if (run_is_bo(run)) {
+		*ritem = run_recovery_item(run);
+		return;
+	}
+
 	assert(ref_val->u.value->var->vc == vc_ref);
 
@@ -1598,4 +1788,6 @@
 	address->u.var_a = addr_var;
 	addr_var->vref = ref_val->u.value->var->u.ref_v->vref;
+
+	rdata_item_destroy(ref_val);
 
 	if (addr_var->vref == NULL) {
@@ -1840,7 +2032,6 @@
 }
 
-/** Construct a new procedure activation record.
- *
- * @param run	Runner object
+/** Allocate a new procedure activation record.
+ *
  * @return	New procedure AR.
  */
@@ -1858,5 +2049,15 @@
 }
 
-/** Construct a new block activation record.
+/** Deallocate a procedure activation record.
+ *
+ * @return	New procedure AR.
+ */
+void run_proc_ar_delete(run_proc_ar_t *proc_ar)
+{
+	assert(proc_ar != NULL);
+	free(proc_ar);
+}
+
+/** Allocate a new block activation record.
  *
  * @param run	Runner object
@@ -1875,2 +2076,13 @@
 	return block_ar;
 }
+
+/** Deallocate a new block activation record.
+ *
+ * @param run	Runner object
+ * @return	New block AR.
+ */
+void run_block_ar_delete(run_block_ar_t *block_ar)
+{
+	assert(block_ar != NULL);
+	free(block_ar);
+}
Index: uspace/app/sbi/src/run.h
===================================================================
--- uspace/app/sbi/src/run.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/run.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -61,4 +61,5 @@
 void run_proc_ar_create(run_t *run, rdata_var_t *obj, stree_proc_t *proc,
     run_proc_ar_t **rproc_ar);
+void run_proc_ar_destroy(run_t *run, run_proc_ar_t *proc_ar);
 
 var_class_t run_item_get_vc(run_t *run, rdata_item_t *item);
@@ -79,5 +80,10 @@
 run_thread_ar_t *run_thread_ar_new(void);
 run_proc_ar_t *run_proc_ar_new(void);
+void run_proc_ar_delete(run_proc_ar_t *proc_ar);
 run_block_ar_t *run_block_ar_new(void);
+void run_block_ar_delete(run_block_ar_t *block_ar);
+void run_proc_ar_delete(run_proc_ar_t *proc_ar);
+void run_block_ar_destroy(run_t *run, run_block_ar_t *block_ar);
+
 
 #endif
Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/run_expr.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -113,4 +113,5 @@
 static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
 static void run_call_args(run_t *run, list_t *args, list_t *arg_vals);
+static void run_destroy_arg_vals(list_t *arg_vals);
 
 static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res);
@@ -200,4 +201,7 @@
 	rdata_address_t *address;
 	rdata_addr_var_t *addr_var;
+	rdata_addr_prop_t *addr_prop;
+	rdata_aprop_named_t *aprop_named;
+	rdata_deleg_t *deleg_p;
 	rdata_value_t *value;
 	rdata_var_t *var;
@@ -334,13 +338,17 @@
 		break;
 	case sc_var:
-#ifdef DEBUG_RUN_TRACE
-		printf("Referencing member variable.\n");
-#endif
-		/* There should be no global variables. */
+	case sc_prop:
+#ifdef DEBUG_RUN_TRACE
+		if (sym->sc == sc_var)
+			printf("Referencing member variable.\n");
+		else
+			printf("Referencing unqualified property.\n");
+#endif
+		/* There should be no global variables or properties. */
 		assert(csi != NULL);
 
 		if (symbol_search_csi(run->program, csi, nameref->name)
 		    == NULL && !stree_symbol_is_static(sym)) {
-			/* Variable is not in the current object. */
+			/* Symbol is not in the current object. */
 			printf("Error: Cannot access non-static member "
 			    "variable '");
@@ -352,6 +360,10 @@
 		}
 
+		/*
+		 * Determine object in which the symbol resides
+		 */
 		if (stree_symbol_is_static(sym)) {
 			/*
+			 * Class object
 			 * XXX This is too slow!
 			 *
@@ -365,26 +377,46 @@
 			aobj = sobj->u.object_v;
 		} else {
-			aobj = obj;
+			/*
+			 * Instance object. Currently we don't support
+			 * true inner classes, thus we know the symbol is
+			 * in the active object (there is no dynamic parent).
+			 */
+			sobj = proc_ar->obj;
+			aobj = sobj->u.object_v;;
 		}
 
-		/* Find member variable in object. */
-		member_var = intmap_get(&aobj->fields, nameref->name->sid);
-		assert(member_var != NULL);
-
-		/* Return address of the variable. */
-		item = rdata_item_new(ic_address);
-		address = rdata_address_new(ac_var);
-		addr_var = rdata_addr_var_new();
-
-		item->u.address = address;
-		address->u.var_a = addr_var;
-		addr_var->vref = member_var;
-
-		*res = item;
-		break;
-	case sc_prop:
-		/* XXX TODO */
-		printf("Unimplemented: Property name reference.\n");
-		abort();
+		if (sym->sc == sc_var) {
+			/* Find member variable in object. */
+			member_var = intmap_get(&aobj->fields,
+			    nameref->name->sid);
+			assert(member_var != NULL);
+
+			/* Return address of the variable. */
+			item = rdata_item_new(ic_address);
+			address = rdata_address_new(ac_var);
+			addr_var = rdata_addr_var_new();
+
+			item->u.address = address;
+			address->u.var_a = addr_var;
+			addr_var->vref = member_var;
+
+			*res = item;
+		} else {
+			/* Construct named property address. */
+			item = rdata_item_new(ic_address);
+			address = rdata_address_new(ac_prop);
+			addr_prop = rdata_addr_prop_new(apc_named);
+			aprop_named = rdata_aprop_named_new();
+			item->u.address = address;
+			address->u.prop_a = addr_prop;
+			addr_prop->u.named = aprop_named;
+
+			deleg_p = rdata_deleg_new();
+			deleg_p->obj = sobj;
+			deleg_p->sym = sym;
+			addr_prop->u.named->prop_d = deleg_p;
+
+			*res = item;
+		}
 		break;
 	}
@@ -611,4 +643,9 @@
 	rdata_value_t *v1, *v2;
 
+	rarg1_i = NULL;
+	rarg2_i = NULL;
+	rarg1_vi = NULL;
+	rarg2_vi = NULL;
+
 #ifdef DEBUG_RUN_TRACE
 	printf("Run binary operation.\n");
@@ -616,20 +653,31 @@
 	run_expr(run, binop->arg1, &rarg1_i);
 	if (run_is_bo(run)) {
-		*res = NULL;
-		return;
+		*res = run_recovery_item(run);
+		goto cleanup;
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Check binop argument result.\n");
+#endif
+	run_cvt_value_item(run, rarg1_i, &rarg1_vi);
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		goto cleanup;
 	}
 
 	run_expr(run, binop->arg2, &rarg2_i);
 	if (run_is_bo(run)) {
-		*res = NULL;
-		return;
-	}
-
-#ifdef DEBUG_RUN_TRACE
-	printf("Check binop argument results.\n");
-#endif
-
-	run_cvt_value_item(run, rarg1_i, &rarg1_vi);
+		*res = run_recovery_item(run);
+		goto cleanup;
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Check binop argument result.\n");
+#endif
 	run_cvt_value_item(run, rarg2_i, &rarg2_vi);
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		goto cleanup;
+	}
 
 	v1 = rarg1_vi->u.value;
@@ -668,4 +716,14 @@
 		assert(b_false);
 	}
+
+cleanup:
+	if (rarg1_i != NULL)
+		rdata_item_destroy(rarg1_i);
+	if (rarg2_i != NULL)
+		rdata_item_destroy(rarg2_i);
+	if (rarg1_vi != NULL)
+		rdata_item_destroy(rarg1_vi);
+	if (rarg2_vi != NULL)
+		rdata_item_destroy(rarg2_vi);
 }
 
@@ -1054,5 +1112,5 @@
 	rdata_bool_t *bool_v;
 
-	rdata_var_t *ref1, *ref2;
+	stree_embr_t *e1, *e2;
 
 	(void) run;
@@ -1067,13 +1125,13 @@
 	var->u.bool_v = bool_v;
 
-	ref1 = v1->var->u.ref_v->vref;
-	ref2 = v2->var->u.ref_v->vref;
+	e1 = v1->var->u.enum_v->value;
+	e2 = v2->var->u.enum_v->value;
 
 	switch (binop->bc) {
 	case bo_equal:
-		bool_v->value = (ref1 == ref2);
+		bool_v->value = (e1 == e2);
 		break;
 	case bo_notequal:
-		bool_v->value = (ref1 != ref2);
+		bool_v->value = (e1 != e2);
 		break;
 	default:
@@ -1100,8 +1158,11 @@
 	printf("Run unary operation.\n");
 #endif
+	rarg_i = NULL;
+	rarg_vi = NULL;
+
 	run_expr(run, unop->arg, &rarg_i);
 	if (run_is_bo(run)) {
-		*res = NULL;
-		return;
+		*res = run_recovery_item(run);
+		goto cleanup;
 	}
 
@@ -1110,4 +1171,8 @@
 #endif
 	run_cvt_value_item(run, rarg_i, &rarg_vi);
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		goto cleanup;
+	}
 
 	val = rarg_vi->u.value;
@@ -1124,7 +1189,12 @@
 		    "type %d.\n", val->var->vc);
 		run_raise_error(run);
-		*res = NULL;
-		break;
-	}
+		*res = run_recovery_item(run);
+		break;
+	}
+cleanup:
+	if (rarg_i != NULL)
+		rdata_item_destroy(rarg_i);
+	if (rarg_vi != NULL)
+		rdata_item_destroy(rarg_vi);
 }
 
@@ -1208,4 +1278,77 @@
 	*res = item;
 }
+
+/** Run equality comparison of two values
+ *
+ * This should be equivalent to equality ('==') binary operation.
+ * XXX Duplicating code of run_binop_xxx().
+ *
+ * @param run		Runner object
+ * @param v1		Value of first argument
+ * @param v2		Value of second argument
+ * @param res		Place to store result (plain boolean value)
+ */
+void run_equal(run_t *run, rdata_value_t *v1, rdata_value_t *v2, bool_t *res)
+{
+	bool_t b1, b2;
+	bigint_t *c1, *c2;
+	bigint_t *i1, *i2;
+	bigint_t diff;
+	const char *s1, *s2;
+	rdata_var_t *ref1, *ref2;
+	stree_embr_t *e1, *e2;
+
+	(void) run;
+	assert(v1->var->vc == v2->var->vc);
+
+	switch (v1->var->vc) {
+	case vc_bool:
+		b1 = v1->var->u.bool_v->value;
+		b2 = v2->var->u.bool_v->value;
+
+		*res = (b1 == b2);
+		break;
+	case vc_char:
+		c1 = &v1->var->u.char_v->value;
+		c2 = &v2->var->u.char_v->value;
+
+    		bigint_sub(c1, c2, &diff);
+		*res = bigint_is_zero(&diff);
+		break;
+	case vc_int:
+		i1 = &v1->var->u.int_v->value;
+		i2 = &v2->var->u.int_v->value;
+
+		bigint_sub(i1, i2, &diff);
+		*res = bigint_is_zero(&diff);
+		break;
+	case vc_string:
+		s1 = v1->var->u.string_v->value;
+		s2 = v2->var->u.string_v->value;
+
+		*res = os_str_cmp(s1, s2) == 0;
+		break;
+	case vc_ref:
+		ref1 = v1->var->u.ref_v->vref;
+		ref2 = v2->var->u.ref_v->vref;
+
+		*res = (ref1 == ref2);
+		break;
+	case vc_enum:
+		e1 = v1->var->u.enum_v->value;
+		e2 = v2->var->u.enum_v->value;
+
+		*res = (e1 == e2);
+		break;
+
+	case vc_deleg:
+	case vc_array:
+	case vc_object:
+	case vc_resource:
+	case vc_symbol:
+		assert(b_false);
+	}
+}
+
 
 /** Evaluate @c new operation.
@@ -1297,9 +1440,14 @@
 		run_expr(run, expr, &rexpr);
 		if (run_is_bo(run)) {
-			*res = NULL;
+			*res = run_recovery_item(run);
 			return;
 		}
 
 		run_cvt_value_item(run, rexpr, &rexpr_vi);
+		if (run_is_bo(run)) {
+			*res = run_recovery_item(run);
+			return;
+		}
+
 		assert(rexpr_vi->ic == ic_value);
 		rexpr_var = rexpr_vi->u.value->var;
@@ -1375,5 +1523,5 @@
 	run_call_args(run, &new_op->ctor_args, &arg_vals);
 	if (run_is_bo(run)) {
-		*res = NULL;
+		*res = run_recovery_item(run);
 		return;
 	}
@@ -1387,4 +1535,8 @@
 	assert(obj_i->u.address->ac == ac_var);
 	run_object_ctor(run, obj_i->u.address->u.var_a->vref, &arg_vals);
+	rdata_item_destroy(obj_i);
+
+	/* Destroy argument values */
+	run_destroy_arg_vals(&arg_vals);
 }
 
@@ -1404,8 +1556,10 @@
 	printf("Run access operation.\n");
 #endif
+	rarg = NULL;
+
 	run_expr(run, access->arg, &rarg);
 	if (run_is_bo(run)) {
-		*res = NULL;
-		return;
+		*res = run_recovery_item(run);
+		goto cleanup;
     	}
 
@@ -1416,4 +1570,7 @@
 
 	run_access_item(run, access, rarg, res);
+cleanup:
+	if (rarg != NULL)
+		rdata_item_destroy(rarg);
 }
 
@@ -1484,4 +1641,7 @@
 	/* Try again. */
 	run_access_item(run, access, darg, res);
+
+	/* Destroy temporary */
+	rdata_item_destroy(darg);
 }
 
@@ -1790,4 +1950,9 @@
 #endif
 	run_cvt_value_item(run, arg, &arg_vi);
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		return;
+	}
+
 	arg_val = arg_vi->u.value;
 	assert(arg_val->var->vc == vc_symbol);
@@ -1800,4 +1965,6 @@
 	embr = stree_enum_find_mbr(symbol_v->sym->u.enum_d,
 	    access->member_name);
+
+	rdata_item_destroy(arg_vi);
 
 	/* Member existence should be ensured by static type checking. */
@@ -1841,16 +2008,19 @@
 	printf("Run call operation.\n");
 #endif
+	rdeleg = NULL;
+	rdeleg_vi = NULL;
+
 	run_expr(run, call->fun, &rdeleg);
 	if (run_is_bo(run)) {
-		*res = NULL;
-		return;
-	}
-
-	if (run->thread_ar->bo_mode != bm_none) {
 		*res = run_recovery_item(run);
-		return;
+		goto cleanup;
 	}
 
 	run_cvt_value_item(run, rdeleg, &rdeleg_vi);
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		goto cleanup;
+	}
+
 	assert(rdeleg_vi->ic == ic_value);
 
@@ -1877,6 +2047,6 @@
 	run_call_args(run, &call->args, &arg_vals);
 	if (run_is_bo(run)) {
-		*res = NULL;
-		return;
+		*res = run_recovery_item(run);
+		goto cleanup;
 	}
 
@@ -1889,4 +2059,7 @@
 	/* Fill in argument values. */
 	run_proc_ar_set_args(run, proc_ar, &arg_vals);
+
+	/* Destroy arg_vals, they are no longer needed. */
+	run_destroy_arg_vals(&arg_vals);
 
 	/* Run the function. */
@@ -1900,4 +2073,13 @@
 	}
 
+	/* Destroy procedure activation record. */
+	run_proc_ar_destroy(run, proc_ar);
+
+cleanup:
+	if (rdeleg != NULL)
+		rdata_item_destroy(rdeleg);
+	if (rdeleg_vi != NULL)
+		rdata_item_destroy(rdeleg_vi);
+
 #ifdef DEBUG_RUN_TRACE
 	printf("Returned from function call.\n");
@@ -1928,11 +2110,51 @@
 		run_expr(run, arg, &rarg_i);
 		if (run_is_bo(run))
-			return;
+			goto error;
 
 		run_cvt_value_item(run, rarg_i, &rarg_vi);
+		rdata_item_destroy(rarg_i);
+		if (run_is_bo(run))
+			goto error;
 
 		list_append(arg_vals, rarg_vi);
 		arg_n = list_next(args, arg_n);
 	}
+	return;
+
+error:
+	/*
+	 * An exception or error occured while evaluating one of the
+	 * arguments. Destroy already obtained argument values and
+	 * dismantle the list.
+	 */
+	run_destroy_arg_vals(arg_vals);
+}
+
+/** Destroy list of evaluated arguments.
+ *
+ * Provided a list of evaluated arguments, destroy them, removing them
+ * from the list and fini the list itself.
+ *
+ * @param arg_vals	List of evaluated arguments (value items,
+ *			rdata_item_t).
+ */
+static void run_destroy_arg_vals(list_t *arg_vals)
+{
+	list_node_t *val_n;
+	rdata_item_t *val_i;
+
+	/*
+	 * An exception or error occured while evaluating one of the
+	 * arguments. Destroy already obtained argument values and
+	 * dismantle the list.
+	 */
+	while (!list_is_empty(arg_vals)) {
+		val_n = list_first(arg_vals);
+		val_i = list_node_data(val_n, rdata_item_t *);
+
+		rdata_item_destroy(val_i);
+		list_remove(arg_vals, val_n);
+	}
+	list_fini(arg_vals);
 }
 
@@ -1954,4 +2176,6 @@
 	var_class_t vc;
 	list_t arg_vals;
+	list_node_t *val_n;
+	rdata_item_t *val_i;
 
 #ifdef DEBUG_RUN_TRACE
@@ -1960,5 +2184,5 @@
 	run_expr(run, index->base, &rbase);
 	if (run_is_bo(run)) {
-		*res = NULL;
+		*res = run_recovery_item(run);
 		return;
 	}
@@ -1969,6 +2193,7 @@
 	if (vc == vc_ref) {
 		run_dereference(run, rbase, index->base->cspan, &base_i);
+		rdata_item_destroy(rbase);
 		if (run_is_bo(run)) {
-			*res = NULL;
+			*res = run_recovery_item(run);
 			return;
 		}
@@ -1987,9 +2212,14 @@
 		run_expr(run, arg, &rarg_i);
 		if (run_is_bo(run)) {
-			*res = NULL;
-			return;
+			*res = run_recovery_item(run);
+			goto cleanup;
 		}
 
 		run_cvt_value_item(run, rarg_i, &rarg_vi);
+		rdata_item_destroy(rarg_i);
+		if (run_is_bo(run)) {
+			*res = run_recovery_item(run);
+			goto cleanup;
+		}
 
 		list_append(&arg_vals, rarg_vi);
@@ -2012,4 +2242,22 @@
 		exit(1);
 	}
+
+	/* Destroy the indexing base temporary */
+	rdata_item_destroy(base_i);
+cleanup:
+	/*
+	 * An exception or error occured while evaluating one of the
+	 * arguments. Destroy already obtained argument values and
+	 * dismantle the list.
+	 */
+	while (!list_is_empty(&arg_vals)) {
+		val_n = list_first(&arg_vals);
+		val_i = list_node_data(val_n, rdata_item_t *);
+
+		rdata_item_destroy(val_i);
+		list_remove(&arg_vals, val_n);
+	}
+
+	list_fini(&arg_vals);
 }
 
@@ -2136,5 +2384,5 @@
 
 	list_node_t *node;
-	rdata_item_t *arg;
+	rdata_item_t *arg, *arg_copy;
 
 #ifdef DEBUG_RUN_TRACE
@@ -2186,5 +2434,14 @@
 	while (node != NULL) {
 		arg = list_node_data(node, rdata_item_t *);
-		list_append(&aprop_indexed->args, arg);
+
+		/*
+		 * Clone argument so that original can
+		 * be freed.
+		 */
+		assert(arg->ic == ic_value);
+		arg_copy = rdata_item_new(ic_value);
+		rdata_value_copy(arg->u.value, &arg_copy->u.value);
+
+		list_append(&aprop_indexed->args, arg_copy);
 		node = list_next(args, node);
 	}
@@ -2225,4 +2482,9 @@
 
 	run_cvt_value_item(run, base, &base_vi);
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		return;
+	}
+
 	assert(base_vi->u.value->var->vc == vc_string);
 	string = base_vi->u.value->var->u.string_v;
@@ -2277,5 +2539,5 @@
 		    index->expr->cspan);
 		*res = run_recovery_item(run);
-		return;
+		goto cleanup;
 	}
 
@@ -2291,4 +2553,6 @@
 
 	*res = ritem;
+cleanup:
+	rdata_item_destroy(base_vi);
 }
 
@@ -2310,17 +2574,26 @@
 	printf("Run assign operation.\n");
 #endif
+	rdest_i = NULL;
+	rsrc_i = NULL;
+	rsrc_vi = NULL;
+
 	run_expr(run, assign->dest, &rdest_i);
 	if (run_is_bo(run)) {
-		*res = NULL;
-		return;
+		*res = run_recovery_item(run);
+		goto cleanup;
 	}
 
 	run_expr(run, assign->src, &rsrc_i);
 	if (run_is_bo(run)) {
-		*res = NULL;
-		return;
+		*res = run_recovery_item(run);
+		goto cleanup;
 	}
 
 	run_cvt_value_item(run, rsrc_i, &rsrc_vi);
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		goto cleanup;
+	}
+
 	assert(rsrc_vi->ic == ic_value);
 
@@ -2334,4 +2607,11 @@
 
 	*res = NULL;
+cleanup:
+	if (rdest_i != NULL)
+		rdata_item_destroy(rdest_i);
+	if (rsrc_i != NULL)
+		rdata_item_destroy(rsrc_i);
+	if (rsrc_vi != NULL)
+		rdata_item_destroy(rsrc_vi);
 }
 
@@ -2359,5 +2639,5 @@
 	run_expr(run, as_op->arg, &rarg_i);
 	if (run_is_bo(run)) {
-		*res = NULL;
+		*res = run_recovery_item(run);
 		return;
 	}
@@ -2369,4 +2649,11 @@
 	assert(run_item_get_vc(run, rarg_i) == vc_ref);
 	run_cvt_value_item(run, rarg_i, &rarg_vi);
+	rdata_item_destroy(rarg_i);
+
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		return;
+	}
+
 	assert(rarg_vi->ic == ic_value);
 
@@ -2405,4 +2692,7 @@
 	}
 
+	/* The dereferenced item is not used anymore. */
+	rdata_item_destroy(rarg_di);
+
 	*res = rarg_vi;
 }
@@ -2435,9 +2725,15 @@
 	run_expr(run, box->arg, &rarg_i);
 	if (run_is_bo(run)) {
-		*res = NULL;
+		*res = run_recovery_item(run);
 		return;
 	}
 
 	run_cvt_value_item(run, rarg_i, &rarg_vi);
+	rdata_item_destroy(rarg_i);
+	if (run_is_bo(run)) {
+		*res = run_recovery_item(run);
+		return;
+	}
+
 	assert(rarg_vi->ic == ic_value);
 
@@ -2482,4 +2778,5 @@
 
 	rdata_var_write(mbr_var, rarg_vi->u.value);
+	rdata_item_destroy(rarg_vi);
 }
 
@@ -2657,4 +2954,7 @@
 	assert(res == NULL);
 
+	/* Destroy procedure activation record. */
+	run_proc_ar_destroy(run, proc_ar);
+
 #ifdef DEBUG_RUN_TRACE
 	printf("Returned from constructor..\n");
@@ -2675,7 +2975,10 @@
 	rdata_item_t *vitem;
 	rdata_var_t *var;
+	bool_t res;
 
 	(void) run;
 	run_cvt_value_item(run, item, &vitem);
+	if (run_is_bo(run))
+		return b_true;
 
 	assert(vitem->ic == ic_value);
@@ -2683,4 +2986,8 @@
 
 	assert(var->vc == vc_bool);
-	return var->u.bool_v->value;
-}
+	res = var->u.bool_v->value;
+
+	/* Free value item */
+	rdata_item_destroy(vitem);
+	return res;
+}
Index: uspace/app/sbi/src/run_expr.h
===================================================================
--- uspace/app/sbi/src/run_expr.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/run_expr.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -39,4 +39,5 @@
     rdata_var_t **res);
 
+void run_equal(run_t *run, rdata_value_t *v1, rdata_value_t *v2, bool_t *res);
 bool_t run_item_boolean_value(run_t *run, rdata_item_t *item);
 
Index: uspace/app/sbi/src/stree.c
===================================================================
--- uspace/app/sbi/src/stree.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/stree.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -397,4 +397,21 @@
 }
 
+/** Allocate new @c switch statement.
+ *
+ * @return	New @c if statement
+ */
+stree_switch_t *stree_switch_new(void)
+{
+	stree_switch_t *switch_s;
+
+	switch_s = calloc(1, sizeof(stree_switch_t));
+	if (switch_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return switch_s;
+}
+
 /** Allocate new @c while statement.
  *
@@ -548,4 +565,21 @@
 
 	return if_clause;
+}
+
+/** Allocate new @c when clause.
+ *
+ * @return	New @c when clause
+ */
+stree_when_t *stree_when_new(void)
+{
+	stree_when_t *when_c;
+
+	when_c = calloc(1, sizeof(stree_when_t));
+	if (when_c == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return when_c;
 }
 
Index: uspace/app/sbi/src/stree.h
===================================================================
--- uspace/app/sbi/src/stree.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/stree.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -55,4 +55,5 @@
 stree_vdecl_t *stree_vdecl_new(void);
 stree_if_t *stree_if_new(void);
+stree_switch_t *stree_switch_new(void);
 stree_while_t *stree_while_new(void);
 stree_for_t *stree_for_new(void);
@@ -65,4 +66,5 @@
 stree_except_t *stree_except_new(void);
 stree_if_clause_t *stree_if_clause_new(void);
+stree_when_t *stree_when_new(void);
 stree_block_t *stree_block_new(void);
 
Index: uspace/app/sbi/src/stree_t.h
===================================================================
--- uspace/app/sbi/src/stree_t.h	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/stree_t.h	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -364,5 +364,5 @@
 } texpr_class_t;
 
-/** Arithmetic expression */
+/** Type expression */
 typedef struct stree_texpr {
 	texpr_class_t tc;
@@ -394,4 +394,7 @@
 	stree_ident_t *name;
 	stree_texpr_t *type;
+
+	/** Type of this variable or @c NULL if not typed yet */
+	struct tdata_item *titem;
 } stree_vdecl_t;
 
@@ -401,4 +404,7 @@
 	stree_texpr_t *etype;
 	stree_block_t *block;
+
+	/** Evaluated etype or @c NULL if not typed yet */
+	struct tdata_item *titem;
 } stree_except_t;
 
@@ -418,4 +424,23 @@
 } stree_if_t;
 
+/** @c when clause */
+typedef struct {
+	/** List of expressions -- cases -- for this clause */
+	list_t exprs; /* of stree_expr_t */
+	stree_block_t *block;
+} stree_when_t;
+
+/** Switch statement */
+typedef struct {
+	/** Switch expression */
+	stree_expr_t *expr;
+
+	/** When clauses */
+	list_t when_clauses; /* of stree_when_t */
+
+	/** Else block */
+	stree_block_t *else_block;
+} stree_switch_t;
+
 /** While statement */
 typedef struct {
@@ -448,5 +473,5 @@
 } stree_exps_t;
 
-/** With-try-except-finally statement (WEF) */
+/** With-try-except-finally (WEF) statement */
 typedef struct {
 	stree_block_t *with_block;
@@ -459,4 +484,5 @@
 	st_vdecl,
 	st_if,
+	st_switch,
 	st_while,
 	st_for,
@@ -475,4 +501,5 @@
 		stree_vdecl_t *vdecl_s;
 		stree_if_t *if_s;
+		stree_switch_t *switch_s;
 		stree_while_t *while_s;
 		stree_for_t *for_s;
@@ -510,5 +537,5 @@
 /** Function signature.
  *
- * Foormal parameters and return type. This is common to function and delegate
+ * Formal parameters and return type. This is common to function and delegate
  * delcarations.
  */
@@ -788,11 +815,8 @@
 	} u;
 
-	/** Containing CSI (for all symbols) */
+	/** Containing CSI */
 	stree_csi_t *outer_csi;
 
-	/** Containing block (for block-level symbols) */
-	stree_block_t *outer_block;
-
-	/** Symbol attributes. */
+	/** Symbol attributes */
 	list_t attr; /* of stree_symbol_attr_t */
 } stree_symbol_t;
Index: uspace/app/sbi/src/stype.c
===================================================================
--- uspace/app/sbi/src/stype.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/stype.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -76,4 +76,5 @@
 static void stype_vdecl(stype_t *stype, stree_vdecl_t *vdecl_s);
 static void stype_if(stype_t *stype, stree_if_t *if_s);
+static void stype_switch(stype_t *stype, stree_switch_t *switch_s);
 static void stype_while(stype_t *stype, stree_while_t *while_s);
 static void stype_for(stype_t *stype, stree_for_t *for_s);
@@ -889,4 +890,5 @@
 	case st_vdecl: stype_vdecl(stype, stat->u.vdecl_s); break;
 	case st_if: stype_if(stype, stat->u.if_s); break;
+	case st_switch: stype_switch(stype, stat->u.switch_s); break;
 	case st_while: stype_while(stype, stat->u.while_s); break;
 	case st_for: stype_for(stype, stat->u.for_s); break;
@@ -931,4 +933,7 @@
 	}
 
+	/* Annotate with variable type */
+	vdecl_s->titem = titem;
+
 	intmap_set(&block_vr->vdecls, vdecl_s->name->sid, vdecl_s);
 }
@@ -973,4 +978,71 @@
 	if (if_s->else_block != NULL)
 		stype_block(stype, if_s->else_block);
+}
+
+/** Type @c switch statement.
+ *
+ * @param stype		Static typing object
+ * @param switch_s	@c switch statement
+ */
+static void stype_switch(stype_t *stype, stree_switch_t *switch_s)
+{
+	stree_expr_t *expr, *cexpr;
+	list_node_t *whenc_node;
+	stree_when_t *whenc;
+	list_node_t *expr_node;
+	tdata_item_t *titem1, *titem2;
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Type 'switch' statement.\n");
+#endif
+	stype_expr(stype, switch_s->expr);
+
+	titem1 = switch_s->expr->titem;
+	if (titem1 == NULL) {
+		cspan_print(switch_s->expr->cspan);
+		printf(" Error: Switch expression has no value.\n");
+		stype_note_error(stype);
+		return;
+	}
+
+	/* Walk through all when clauses. */
+	whenc_node = list_first(&switch_s->when_clauses);
+
+	while (whenc_node != NULL) {
+		/* Get when clause */
+		whenc = list_node_data(whenc_node, stree_when_t *);
+
+		/* Walk through all expressions of the when clause */
+		expr_node = list_first(&whenc->exprs);
+		while (expr_node != NULL) {
+			expr = list_node_data(expr_node, stree_expr_t *);
+
+			stype_expr(stype, expr);
+			titem2 = expr->titem;
+			if (titem2 == NULL) {
+				cspan_print(expr->cspan);
+				printf(" Error: When expression has no value.\n");
+				stype_note_error(stype);
+				return;
+			}
+
+			/* Convert expression to same type as switch expr. */
+			cexpr = stype_convert(stype, expr, titem1);
+
+			/* Patch code with augmented expression. */
+			list_node_setdata(expr_node, cexpr);
+
+			expr_node = list_next(&whenc->exprs, expr_node);
+		}
+
+		/* Type the @c when block */
+		stype_block(stype, whenc->block);
+
+		whenc_node = list_next(&switch_s->when_clauses, whenc_node);
+	}
+
+	/* Type the @c else block */
+	if (switch_s->else_block != NULL)
+		stype_block(stype, switch_s->else_block);
 }
 
@@ -1168,4 +1240,6 @@
 	while (ec_n != NULL) {
 		ec = list_node_data(ec_n, stree_except_t *);
+		run_texpr(stype->program, stype->current_csi, ec->etype,
+		    &ec->titem);
 		stype_block(stype, ec->block);
 
Index: uspace/app/sbi/src/stype_expr.c
===================================================================
--- uspace/app/sbi/src/stype_expr.c	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/app/sbi/src/stype_expr.c	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -894,4 +894,11 @@
 
 	titem = unop->arg->titem;
+	if (titem == NULL) {
+		cspan_print(unop->arg->cspan);
+		printf(" Error: Argument of unary operation has no value.\n");
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
 
 	if (titem->tic == tic_ignore) {
Index: uspace/dist/src/sysel/demos/arith.sy
===================================================================
--- uspace/dist/src/sysel/demos/arith.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/arith.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -30,57 +30,57 @@
 	fun Main(), static is
 		-- Test addition, multiplication and precedence.
-		Builtin.Write("2*2 + 2*2 = ");
-		Builtin.Write(2*2 + 2*2);
-		Builtin.WriteLine(" (expected: 8)");
+		Console.Write("2*2 + 2*2 = ");
+		Console.Write(2*2 + 2*2);
+		Console.WriteLine(" (expected: 8)");
 
 		-- Test subtraction, multiplication and precedence.
-		Builtin.Write("1111 - 1 - 10 - 10*10 - 10*10*10 = ");
-		Builtin.Write(1111 - 1 - 10 - 10*10 - 10*10*10);
-		Builtin.WriteLine(" (expected: 0)");
+		Console.Write("1111 - 1 - 10 - 10*10 - 10*10*10 = ");
+		Console.Write(1111 - 1 - 10 - 10*10 - 10*10*10);
+		Console.WriteLine(" (expected: 0)");
 
 		-- Test parenthesized sub-expressions.
-		Builtin.Write("10 * (1 - 1) = ");
-		Builtin.Write(10 * (1 - 1));
-		Builtin.WriteLine(" (expected: 0)");
+		Console.Write("10 * (1 - 1) = ");
+		Console.Write(10 * (1 - 1));
+		Console.WriteLine(" (expected: 0)");
 
 		-- Test unary plus and minus.
-		Builtin.Write("(+1) - (-1) - (+(+1)) + (+(-1)) = ");
-		Builtin.Write((+1) - (-1) - (+(+1)) + (+(-1)));
-		Builtin.WriteLine(" (expected: 0)");
+		Console.Write("(+1) - (-1) - (+(+1)) + (+(-1)) = ");
+		Console.Write((+1) - (-1) - (+(+1)) + (+(-1)));
+		Console.WriteLine(" (expected: 0)");
 
 		-- Test signed multiplication.
-		Builtin.Write("+1 * +1 = ");
-		Builtin.Write(+1 * +1);
-		Builtin.WriteLine(" (expected: 1)");
+		Console.Write("+1 * +1 = ");
+		Console.Write(+1 * +1);
+		Console.WriteLine(" (expected: 1)");
 
-		Builtin.Write("-1 * -1 = ");
-		Builtin.Write(-1 * -1);
-		Builtin.WriteLine(" (expected: 1)");
+		Console.Write("-1 * -1 = ");
+		Console.Write(-1 * -1);
+		Console.WriteLine(" (expected: 1)");
 
-		Builtin.Write("+1 * -1 = ");
-		Builtin.Write(+1 * -1);
-		Builtin.WriteLine(" (expected: -1)");
+		Console.Write("+1 * -1 = ");
+		Console.Write(+1 * -1);
+		Console.WriteLine(" (expected: -1)");
 
-		Builtin.Write("-1 * +1 = ");
-		Builtin.Write(-1 * +1);
-		Builtin.WriteLine(" (expected: -1)");
+		Console.Write("-1 * +1 = ");
+		Console.Write(-1 * +1);
+		Console.WriteLine(" (expected: -1)");
 
 		-- Test multiplication with large result.
-		Builtin.Write("1000000 * 1000000 * 1000000 * 1000000 = ");
-		Builtin.Write(1000000 * 1000000 * 1000000 * 1000000);
-		Builtin.WriteLine(" (expected: 1000000000000000000000000)");
+		Console.Write("1000000 * 1000000 * 1000000 * 1000000 = ");
+		Console.Write(1000000 * 1000000 * 1000000 * 1000000);
+		Console.WriteLine(" (expected: 1000000000000000000000000)");
 
 		-- Test large literals.
-		Builtin.Write("1000000000000000000000000 = ");
-		Builtin.Write(1000000000000000000000000);
-		Builtin.WriteLine(" (expected: 1000000000000000000000000)");
+		Console.Write("1000000000000000000000000 = ");
+		Console.Write(1000000000000000000000000);
+		Console.WriteLine(" (expected: 1000000000000000000000000)");
 
 		-- Test large factorials.
 		var n : int;
 
-		Builtin.WriteLine("Factorials:");
+		Console.WriteLine("Factorials:");
 		n = 1;
 		while n <= 40 do
-			Builtin.WriteLine(Factorial(n));
+			Console.WriteLine(Factorial(n));
 			n = n + 1;
 		end
Index: uspace/dist/src/sysel/demos/array.sy
===================================================================
--- uspace/dist/src/sysel/demos/array.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/array.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -40,5 +40,5 @@
 		i = 0;
 		while i < 3 do
-			Builtin.WriteLine(a[i, 0]);
+			Console.WriteLine(a[i, 0]);
 			i = i + 1;
 		end
Index: uspace/dist/src/sysel/demos/autobox.sy
===================================================================
--- uspace/dist/src/sysel/demos/autobox.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/autobox.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -39,11 +39,11 @@
 		--
 		b = true;
-		Builtin.WriteLine(b.Value);
+		Console.WriteLine(b.Value);
 		c = 'a';
-		Builtin.WriteLine(c.Value);
+		Console.WriteLine(c.Value);
 		i = 1;
-		Builtin.WriteLine(i.Value);
+		Console.WriteLine(i.Value);
 		s = "Hello";
-		Builtin.WriteLine(s.Value);
+		Console.WriteLine(s.Value);
 
 		-- Anything can be converted to Object.
Index: uspace/dist/src/sysel/demos/count.sy
===================================================================
--- uspace/dist/src/sysel/demos/count.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/count.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -33,5 +33,5 @@
 		i = a;
 		while i < b do
-			Builtin.WriteLine(i);
+			Console.WriteLine(i);
 			i = i + 1;
 		end
Index: uspace/dist/src/sysel/demos/ctor.sy
===================================================================
--- uspace/dist/src/sysel/demos/ctor.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/ctor.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -32,6 +32,6 @@
 
 		a = new A(1);
-		Builtin.Write("a.v = ");
-		Builtin.WriteLine(a.v);
+		Console.Write("a.v = ");
+		Console.WriteLine(a.v);
 	end
 end
@@ -41,5 +41,5 @@
 
 	new(i : int) is
-		Builtin.WriteLine("A.new()");
+		Console.WriteLine("A.new()");
 		v = i;
 	end
Index: uspace/dist/src/sysel/demos/deleg.sy
===================================================================
--- uspace/dist/src/sysel/demos/deleg.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/deleg.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -55,6 +55,6 @@
 	-- Function having delegate as the first parameger
 	fun Operate(op : BinaryOp; opName : string) is
-		Builtin.Write(opName + "(1, 2): ");
-		Builtin.WriteLine(op(1, 2));
+		Console.Write(opName + "(1, 2): ");
+		Console.WriteLine(op(1, 2));
 	end
 
Index: uspace/dist/src/sysel/demos/enum.sy
===================================================================
--- uspace/dist/src/sysel/demos/enum.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/enum.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -31,40 +31,40 @@
 		var color : ChessColor;
 
-		Builtin.WriteLine("Set color to ChessColor.Black.");
+		Console.WriteLine("Set color to ChessColor.Black.");
 		color = ChessColor.Black;
 
-		Builtin.Write("Test color == ChessColor.Black.. ");
+		Console.Write("Test color == ChessColor.Black.. ");
 		if color == ChessColor.Black then
-			Builtin.WriteLine("True - OK");
+			Console.WriteLine("True - OK");
 		else
-			Builtin.WriteLine("False - Fail!");
+			Console.WriteLine("False - Fail!");
 			raise new Error.Base();
 		end
 
-		Builtin.Write("Test color != ChessColor.Black.. ");
+		Console.Write("Test color != ChessColor.Black.. ");
 		if color != ChessColor.Black then
-			Builtin.WriteLine("True - Fail!");
+			Console.WriteLine("True - Fail!");
 			raise new Error.Base();
 		else
-			Builtin.WriteLine("False - OK");
+			Console.WriteLine("False - OK");
 		end
 
-		Builtin.Write("Test color == ChessColor.White.. ");
+		Console.Write("Test color == ChessColor.White.. ");
 		if color == ChessColor.White then
-			Builtin.WriteLine("True - Fail!");
+			Console.WriteLine("True - Fail!");
 			raise new Error.Base();
 		else
-			Builtin.WriteLine("False - OK");
+			Console.WriteLine("False - OK");
 		end
 
-		Builtin.Write("Test color != ChessColor.White.. ");
+		Console.Write("Test color != ChessColor.White.. ");
 		if color != ChessColor.White then
-			Builtin.WriteLine("True - OK");
+			Console.WriteLine("True - OK");
 		else
-			Builtin.WriteLine("False - Fail!");
+			Console.WriteLine("False - Fail!");
 			raise new Error.Base();
 		end
 
-		Builtin.WriteLine("Success");
+		Console.WriteLine("Success");
 
 		-- Test enum declared in non-CSI scope
Index: uspace/dist/src/sysel/demos/except.sy
===================================================================
--- uspace/dist/src/sysel/demos/except.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/except.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -29,5 +29,5 @@
 class ExceptionDemo is
 	fun foo(), static is
-	        Builtin.WriteLine("Entered foo().");
+	        Console.WriteLine("Entered foo().");
 		raise new BaseException();
 	end
@@ -38,9 +38,9 @@
 			foo();
 		except e : DerivedException do
-			Builtin.WriteLine("Caught derived exception.");
+			Console.WriteLine("Caught derived exception.");
 		except e : BaseException do
-			Builtin.WriteLine("Caught base exception.");
+			Console.WriteLine("Caught base exception.");
 		finally do
-			Builtin.WriteLine("Finally.");
+			Console.WriteLine("Finally.");
 		end
 	end
Index: uspace/dist/src/sysel/demos/gen.sy
===================================================================
--- uspace/dist/src/sysel/demos/gen.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/gen.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -31,5 +31,5 @@
 class GenericsDemo is
 	fun Main(), static is
-		Builtin.WriteLine("Let's try some generics.");
+		Console.WriteLine("Let's try some generics.");
 
 		var f : B/int/string;
Index: uspace/dist/src/sysel/demos/hello.sy
===================================================================
--- uspace/dist/src/sysel/demos/hello.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/hello.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -29,5 +29,5 @@
 class HelloWorld is
 	fun Main(), static is
-		Builtin.WriteLine("Hello world!");
+		Console.WriteLine("Hello world!");
 	end
 end
Index: uspace/dist/src/sysel/demos/htxtfile.sy
===================================================================
--- uspace/dist/src/sysel/demos/htxtfile.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/htxtfile.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -45,5 +45,5 @@
 		while not in_file.EOF do
 			line = in_file.ReadLine();
-			Builtin.WriteLine(name + ": " + line);
+			Console.WriteLine(name + ": " + line);
 			out_file.WriteLine(name + ": " + line);
 		end
Index: uspace/dist/src/sysel/demos/iface.sy
===================================================================
--- uspace/dist/src/sysel/demos/iface.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/iface.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -43,5 +43,5 @@
 		f = g as Foo;
 
-		Builtin.WriteLine(g.a());
+		Console.WriteLine(g.a());
 	end
 end
Index: uspace/dist/src/sysel/demos/inherit.sy
===================================================================
--- uspace/dist/src/sysel/demos/inherit.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/inherit.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -29,5 +29,5 @@
 class A is
 	fun Foo() is
-		Builtin.WriteLine("A.Foo()");
+		Console.WriteLine("A.Foo()");
 	end
 end
@@ -35,5 +35,5 @@
 class B : A is
 	fun Foo() is
-		Builtin.WriteLine("B.Foo()");
+		Console.WriteLine("B.Foo()");
 	end
 end
Index: uspace/dist/src/sysel/demos/list.sy
===================================================================
--- uspace/dist/src/sysel/demos/list.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/list.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -43,5 +43,5 @@
 		e = list.GetEnumerator();
 		while e.MoveNext() do
-			Builtin.WriteLine(e.Data);
+			Console.WriteLine(e.Data);
 		end
 	end
Index: uspace/dist/src/sysel/demos/map.sy
===================================================================
--- uspace/dist/src/sysel/demos/map.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/map.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -43,7 +43,7 @@
 		e = map.GetEnumerator();
 		while e.MoveNext() do
-			Builtin.Write(e.Data);
-			Builtin.Write(" -> ");
-			Builtin.WriteLine(map[e.Data]);
+			Console.Write(e.Data);
+			Console.Write(" -> ");
+			Console.WriteLine(map[e.Data]);
 		end
 	end
Index: uspace/dist/src/sysel/demos/property.sy
===================================================================
--- uspace/dist/src/sysel/demos/property.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/property.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -33,14 +33,25 @@
 	prop X : int is
 		get is
-			Builtin.Write("Getting value of X which is ");
-			Builtin.WriteLine(x);
+			Console.Write("Getting value of X which is ");
+			Console.WriteLine(x);
 			return x;
 		end
 
 		set value is
-			Builtin.Write("Setting value of X to ");
-			Builtin.WriteLine(value);
+			Console.Write("Setting value of X to ");
+			Console.WriteLine(value);
 			x = value;
 		end
+	end
+
+	-- Test accessing property via an unqualified name
+	fun TestUnqualPropAcc() is
+		var i : int;
+
+		X = 1;
+		i = X;
+
+		Console.Write("TestUnqualPropAcc(): Got ");
+		Console.WriteLine(i);
 	end
 
@@ -51,8 +62,8 @@
 	prop self[index : int] : int is
 		get is
-			Builtin.Write("Getting property with index ");
-			Builtin.Write(index);
-			Builtin.Write(" which is ");
-			Builtin.WriteLine(iprops[index]);
+			Console.Write("Getting property with index ");
+			Console.Write(index);
+			Console.Write(" which is ");
+			Console.WriteLine(iprops[index]);
 
 			return iprops[index];
@@ -60,8 +71,8 @@
 
 		set value is
-			Builtin.Write("Setting property with index ");
-			Builtin.Write(index);
-			Builtin.Write(" to ");
-			Builtin.WriteLine(value);
+			Console.Write("Setting property with index ");
+			Console.Write(index);
+			Console.Write(" to ");
+			Console.WriteLine(value);
 
 			iprops[index] = value;
@@ -82,9 +93,9 @@
 	prop B : Bar is
 		get is
-			Builtin.WriteLine("Getting B");
+			Console.WriteLine("Getting B");
 			return bprop;
 		end
 		set value is
-			Builtin.WriteLine("Setting B");
+			Console.WriteLine("Setting B");
 			bprop = value;
 		end
@@ -110,6 +121,8 @@
 		i = a.X;
 
-		Builtin.Write("Main(): Got ");
-		Builtin.WriteLine(i);
+		Console.Write("Main(): Got ");
+		Console.WriteLine(i);
+
+		a.TestUnqualPropAcc();
 
 		a.iprops = new int[5];
@@ -121,6 +134,6 @@
 		i = a[1];
 
-		Builtin.Write("Main(): Got ");
-		Builtin.WriteLine(i);
+		Console.Write("Main(): Got ");
+		Console.WriteLine(i);
 
 		-- Property field access
@@ -132,7 +145,7 @@
 		a.bprop = b;
 
-		Builtin.WriteLine(a.bprop.i);
+		Console.WriteLine(a.bprop.i);
 		a.bprop.i = 2;
-		Builtin.WriteLine(a.bprop.i);
+		Console.WriteLine(a.bprop.i);
 	end
 end
Index: uspace/dist/src/sysel/demos/string.sy
===================================================================
--- uspace/dist/src/sysel/demos/string.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/string.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -30,5 +30,5 @@
 	fun Main(), static is
 		-- Concatenate some strings.
-		Builtin.WriteLine("One-" + "two-" + "three!");
+		Console.WriteLine("One-" + "two-" + "three!");
 
 		-- Extract characters from a string.
@@ -36,9 +36,9 @@
 		i = 0;
 		while i < 5 do
-			Builtin.WriteLine("ABCDE"[i]);
+			Console.WriteLine("ABCDE"[i]);
 			i = i + 1;
 		end
 
-		Builtin.WriteLine("Abracadabra".Slice(2, 4));
+		Console.WriteLine("Abracadabra".Slice(2, 4));
 	end
 end
Index: uspace/dist/src/sysel/demos/svar.sy
===================================================================
--- uspace/dist/src/sysel/demos/svar.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/svar.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -31,13 +31,13 @@
 		-- Test static member variable
 		A.B.a = 1;
-		Builtin.WriteLine(A.B.a);
+		Console.WriteLine(A.B.a);
 		A.B.a = 2;
-		Builtin.WriteLine(A.B.a);
+		Console.WriteLine(A.B.a);
 
 		-- Test static property
 		A.B.P = 1;
-		Builtin.WriteLine(A.B.P);
+		Console.WriteLine(A.B.P);
 		A.B.P = 2;
-		Builtin.WriteLine(A.B.P);
+		Console.WriteLine(A.B.P);
 	end
 end
Index: uspace/dist/src/sysel/demos/switch.sy
===================================================================
--- uspace/dist/src/sysel/demos/switch.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
+++ uspace/dist/src/sysel/demos/switch.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -0,0 +1,199 @@
+--
+-- Copyright (c) 2011 Jiri Svoboda
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- o Redistributions of source code must retain the above copyright
+--   notice, this list of conditions and the following disclaimer.
+-- o Redistributions in binary form must reproduce the above copyright
+--   notice, this list of conditions and the following disclaimer in the
+--   documentation and/or other materials provided with the distribution.
+-- o The name of the author may not be used to endorse or promote products
+--   derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+-- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+-- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+-- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--
+
+--- Switch statement demo.
+--
+-- This demonstrates the switch statement. The switch statement looks like:
+--
+-- switch <s_expr> is
+-- when <e1> [, <e2> ...] do
+--	<statements1>
+-- when <f1> [, <f2> ...] do
+--	<statements2>
+-- [...]
+-- [else do
+--	<statements3>]
+-- end
+--
+-- It is mostly equivalent to the pseudocode:
+--
+-- var v : <type of s_expr>;
+-- if v == <e1> [or v == <e2> ...] then
+--	<statements1>
+-- elif v == <f1> [ or v == <f2> ...] then
+--	<statements2>
+-- [...]
+-- [else
+--	<statements3>]
+-- end
+--
+-- This means there is no artificial limitation as to what you can switch
+-- on. The expressions don't have to be constant and they can be of any type
+-- as long as the switch expression (<s_expr>) can be compared with each
+-- of the when expressions (<e1>, <e2>, <f1>, <f2>, ...).
+--
+-- Note however, the 'or' here denotes short-circuit evaluation. (Currently
+-- the 'or' operation does not use short-circuit evaluation, but that's
+-- more of a bug than a feature.
+--
+class SwitchDemo is
+	class A is
+	end
+
+	var a1 : A, static;
+	var a2 : A, static;
+	var a3 : A, static;
+	var a4 : A, static;
+
+	enum MyEnum is
+		red;
+		green;
+		blue;
+		black;
+		cyan;
+	end
+
+	-- Switch on boolean value
+	fun SwitchBool(v : bool) : string, static is
+		switch v is
+		when false do
+			return "false";
+		when true do
+			return "true";
+		end
+	end
+
+	-- Switch on char value
+	fun SwitchChar(v : char) : string, static is
+		switch v is
+		when 'a', 'b' do
+			return "a/b";
+		when 'c', 'd' do
+			return "c/d";
+		else do
+			return "<other>";
+		end
+	end
+
+	-- Switch on integer value
+	fun SwitchInt(v : int) : string, static is
+		switch v is
+		when 0, 1 do
+			return "0/1";
+		when 2, 3 do
+			return "2/3";
+		else do
+			return "<other>";
+		end
+	end
+
+	-- Switch on string value
+	fun SwitchString(v : string) : string, static is
+		switch v is
+		when "foo", "bar"  do
+			return "foo/bar";
+		when "hello", "world" do
+			return "hello/world";
+		else do
+			return "<other>";
+		end
+	end
+
+	-- Switch on object reference
+	fun SwitchObj(v : A) : string, static is
+		switch v is
+		when a1, a2 do
+			return "a1/a2";
+		when a3, a4 do
+			return "a3/a4";
+		else do
+			return "<other>";
+		end
+	end
+
+	-- Switch on object reference
+	fun SwitchEnum(v : MyEnum) : string, static is
+		switch v is
+		when MyEnum.red, MyEnum.green do
+			return "red/green";
+		when MyEnum.blue, MyEnum.black do
+			return "blue/black";
+		else do
+			return "<other>";
+		end
+	end
+
+	fun Test(res : string; test_expr : string; expected : string), static is
+		Console.WriteLine(test_expr + " = '" + res + "' (expected '" +
+		    expected + "')");
+		if res != expected then
+			Console.WriteLine("Error: Got unexpected result.");
+			raise new Error.Base();
+		end
+	end
+
+	fun Main(), static is
+		a1 = new A();
+		a2 = new A();
+		a3 = new A();
+		a4 = new A();
+
+		Test(SwitchBool(false), "SwitchBool(false)", "false");
+		Test(SwitchBool(true), "SwitchBool(true)", "true");
+
+		Test(SwitchChar('a'), "SwitchChar('a')", "a/b");
+		Test(SwitchChar('b'), "SwitchChar('b')", "a/b");
+		Test(SwitchChar('c'), "SwitchChar('c')", "c/d");
+		Test(SwitchChar('d'), "SwitchChar('d')", "c/d");
+		Test(SwitchChar('e'), "SwitchChar('e')", "<other>");
+
+		Test(SwitchInt(0), "SwitchInt(0)", "0/1");
+		Test(SwitchInt(1), "SwitchInt(1)", "0/1");
+		Test(SwitchInt(2), "SwitchInt(2)", "2/3");
+		Test(SwitchInt(3), "SwitchInt(3)", "2/3");
+		Test(SwitchInt(4), "SwitchInt(4)", "<other>");
+
+		Test(SwitchString("foo"), "SwitchString('foo')", "foo/bar");
+		Test(SwitchString("bar"), "SwitchString('bar')", "foo/bar");
+		Test(SwitchString("hello"), "SwitchString('hello')", "hello/world");
+		Test(SwitchString("world"), "SwitchString('world')", "hello/world");
+		Test(SwitchString("boom"), "SwitchString('boom')", "<other>");
+
+		Test(SwitchObj(a1), "SwitchObj(a1)", "a1/a2");
+		Test(SwitchObj(a2), "SwitchObj(a2)", "a1/a2");
+		Test(SwitchObj(a3), "SwitchObj(a3)", "a3/a4");
+		Test(SwitchObj(a4), "SwitchObj(a4)", "a3/a4");
+		Test(SwitchObj(nil), "SwitchObj(nil)", "<other>");
+
+		Test(SwitchEnum(MyEnum.red), "SwitchEnum(MyEnum.red)", "red/green");
+		Test(SwitchEnum(MyEnum.green), "SwitchEnum(MyEnum.green)", "red/green");
+		Test(SwitchEnum(MyEnum.blue), "SwitchEnum(MyEnum.blue)", "blue/black");
+		Test(SwitchEnum(MyEnum.black), "SwitchEnum(MyEnum.black)", "blue/black");
+		Test(SwitchEnum(MyEnum.cyan), "SwitchEnum(MyEnum.cyan)", "<other>");
+	end
+end
Index: uspace/dist/src/sysel/demos/varargs.sy
===================================================================
--- uspace/dist/src/sysel/demos/varargs.sy	(revision 406d5145faf1500950e7b901c8f5588480931860)
+++ uspace/dist/src/sysel/demos/varargs.sy	(revision 051b3db868923b7f34bea045ba0529d963856b5a)
@@ -44,5 +44,5 @@
 			-- implemented...
 			do
-				Builtin.WriteLine(args[i]);
+				Console.WriteLine(args[i]);
 			except e : Error.OutOfBounds do
 				error = true;
