Index: uspace/app/sbi/src/ancr.c
===================================================================
--- uspace/app/sbi/src/ancr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/ancr.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -72,4 +72,5 @@
 	stree_modm_t *modm;
 
+	(void) module;
 	node = list_first(&prog->module->members);
 
Index: uspace/app/sbi/src/input.c
===================================================================
--- uspace/app/sbi/src/input.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/input.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -64,6 +64,8 @@
 
 	input->buffer = malloc(INPUT_BUFFER_SIZE);
-	if (input->buffer == NULL)
-		return ENOMEM;
+	if (input->buffer == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
 
 	input->line_no = 0;
Index: uspace/app/sbi/src/lex.c
===================================================================
--- uspace/app/sbi/src/lex.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/lex.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -78,5 +78,4 @@
 	{ lc_for,	"for" },
 	{ lc_fun,	"fun" },
-	{ lc_new,	"new" },
 	{ lc_get,	"get" },
 	{ lc_if,	"if" },
@@ -85,4 +84,6 @@
 	{ lc_interface,	"interface" },
 	{ lc_is,	"is" },
+	{ lc_new,	"new" },
+	{ lc_nil,	"nil" },
 	{ lc_override,	"override" },
 	{ lc_private,	"private" },
@@ -92,4 +93,5 @@
 	{ lc_raise,	"raise" },
 	{ lc_return,	"return" },
+	{ lc_self,	"self" },
 	{ lc_set,	"set" },
 	{ lc_static,	"static" },
Index: uspace/app/sbi/src/lex_t.h
===================================================================
--- uspace/app/sbi/src/lex_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/lex_t.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -56,4 +56,5 @@
 	lc_interface,
 	lc_is,
+	lc_nil,
 	lc_override,
 	lc_private,
@@ -63,4 +64,5 @@
 	lc_raise,
 	lc_return,
+	lc_self,
 	lc_set,
 	lc_static,
Index: uspace/app/sbi/src/main.c
===================================================================
--- uspace/app/sbi/src/main.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/main.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -59,5 +59,5 @@
 	rc = input_new(&input, argv[1]);
 	if (rc != EOK) {
-		printf("Failed initializing input.\n");
+		printf("Failed opening source file '%s'.\n", argv[1]);
 		exit(1);
 	}
Index: uspace/app/sbi/src/p_expr.c
===================================================================
--- uspace/app/sbi/src/p_expr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/p_expr.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -34,4 +34,5 @@
 #include "list.h"
 #include "mytypes.h"
+#include "p_type.h"
 #include "parse.h"
 #include "stree.h"
@@ -42,4 +43,6 @@
 static stree_expr_t *parse_comparative(parse_t *parse);
 static stree_expr_t *parse_additive(parse_t *parse);
+static stree_expr_t *parse_prefix(parse_t *parse);
+static stree_expr_t *parse_prefix_new(parse_t *parse);
 static stree_expr_t *parse_postfix(parse_t *parse);
 static stree_expr_t *parse_pf_access(parse_t *parse, stree_expr_t *a);
@@ -48,5 +51,7 @@
 static stree_expr_t *parse_nameref(parse_t *parse);
 static stree_expr_t *parse_lit_int(parse_t *parse);
+static stree_expr_t *parse_lit_ref(parse_t *parse);
 static stree_expr_t *parse_lit_string(parse_t *parse);
+static stree_expr_t *parse_self_ref(parse_t *parse);
 
 /** Parse expression. */
@@ -130,8 +135,8 @@
 	stree_binop_t *binop;
 
-	a = parse_postfix(parse);
+	a = parse_prefix(parse);
 	while (lcur_lc(parse) == lc_plus) {
 		lskip(parse);
-		b = parse_postfix(parse);
+		b = parse_prefix(parse);
 
 		binop = stree_binop_new(bo_plus);
@@ -145,4 +150,44 @@
 
 	return a;
+}
+
+/** Parse prefix expression. */
+static stree_expr_t *parse_prefix(parse_t *parse)
+{
+	stree_expr_t *a;
+
+	switch (lcur_lc(parse)) {
+	case lc_plus:
+		printf("Unimplemented: Unary plus.\n");
+		exit(1);
+	case lc_new:
+		a = parse_prefix_new(parse);
+		break;
+	default:
+		a = parse_postfix(parse);
+		break;
+	}
+
+	return a;
+}
+
+/** Parse @c new operator. */
+static stree_expr_t *parse_prefix_new(parse_t *parse)
+{
+	stree_texpr_t *texpr;
+	stree_new_t *new_op;
+	stree_expr_t *expr;
+
+	lmatch(parse, lc_new);
+	texpr = parse_texpr(parse);
+	lmatch(parse, lc_lparen);
+	lmatch(parse, lc_rparen);
+
+	new_op = stree_new_new();
+	new_op->texpr = texpr;
+	expr = stree_expr_new(ec_new);
+	expr->u.new_op = new_op;
+
+	return expr;
 }
 
@@ -240,6 +285,12 @@
 		expr = parse_lit_int(parse);
 		break;
+	case lc_nil:
+		expr = parse_lit_ref(parse);
+		break;
 	case lc_lit_string:
 		expr = parse_lit_string(parse);
+		break;
+	case lc_self:
+		expr = parse_self_ref(parse);
 		break;
 	default:
@@ -284,4 +335,20 @@
 }
 
+/** Parse reference literal (@c nil). */
+static stree_expr_t *parse_lit_ref(parse_t *parse)
+{
+	stree_literal_t *literal;
+	stree_expr_t *expr;
+
+	lmatch(parse, lc_nil);
+
+	literal = stree_literal_new(ltc_ref);
+
+	expr = stree_expr_new(ec_literal);
+	expr->u.literal = literal;
+
+	return expr;
+}
+
 /** Parse string literal. */
 static stree_expr_t *parse_lit_string(parse_t *parse)
@@ -302,2 +369,18 @@
 	return expr;
 }
+
+/** Parse @c self keyword. */
+static stree_expr_t *parse_self_ref(parse_t *parse)
+{
+	stree_self_ref_t *self_ref;
+	stree_expr_t *expr;
+
+	lmatch(parse, lc_self);
+
+	self_ref = stree_self_ref_new();
+
+	expr = stree_expr_new(ec_self_ref);
+	expr->u.self_ref = self_ref;
+
+	return expr;
+}
Index: uspace/app/sbi/src/p_type.c
===================================================================
--- uspace/app/sbi/src/p_type.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/p_type.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -42,4 +42,5 @@
 static stree_texpr_t *parse_tpostfix(parse_t *parse);
 static stree_texpr_t *parse_tprimitive(parse_t *parse);
+static stree_tliteral_t *parse_tliteral(parse_t *parse);
 static stree_tnameref_t *parse_tnameref(parse_t *parse);
 
@@ -104,9 +105,43 @@
 	stree_texpr_t *texpr;
 
-	lcheck(parse, lc_ident);
-	texpr = stree_texpr_new(tc_tnameref);
-	texpr->u.tnameref = parse_tnameref(parse);
+	switch (lcur_lc(parse)) {
+	case lc_ident:
+		texpr = stree_texpr_new(tc_tnameref);
+		texpr->u.tnameref = parse_tnameref(parse);
+		break;
+	case lc_int:
+	case lc_string:
+		texpr = stree_texpr_new(tc_tliteral);
+		texpr->u.tliteral = parse_tliteral(parse);
+		break;
+	default:
+		lunexpected_error(parse);
+		exit(1);
+	}
 
 	return texpr;
+}
+
+/** Parse type literal. */
+static stree_tliteral_t *parse_tliteral(parse_t *parse)
+{
+	stree_tliteral_t *tliteral;
+
+	tliteral = stree_tliteral_new();
+
+	switch (lcur_lc(parse)) {
+	case lc_int:
+		tliteral->tlc = tlc_int;
+		break;
+	case lc_string:
+		tliteral->tlc = tlc_string;
+		break;
+	default:
+		assert(b_false);
+	}
+
+	lskip(parse);
+
+	return tliteral;
 }
 
Index: uspace/app/sbi/src/parse.c
===================================================================
--- uspace/app/sbi/src/parse.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/parse.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -68,4 +68,5 @@
 static stree_for_t *parse_for(parse_t *parse);
 static stree_raise_t *parse_raise(parse_t *parse);
+static stree_return_t *parse_return(parse_t *parse);
 static stree_wef_t *parse_wef(parse_t *parse);
 static stree_exps_t *parse_exps(parse_t *parse);
@@ -342,4 +343,5 @@
 	stree_for_t *for_s;
 	stree_raise_t *raise_s;
+	stree_return_t *return_s;
 	stree_wef_t *wef_s;
 	stree_exps_t *exp_s;
@@ -370,4 +372,9 @@
 		stat = stree_stat_new(st_raise);
 		stat->u.raise_s = raise_s;
+		break;
+	case lc_return:
+		return_s = parse_return(parse);
+		stat = stree_stat_new(st_return);
+		stat->u.return_s = return_s;
 		break;
 	case lc_with:
@@ -485,4 +492,18 @@
 }
 
+/** Parse @c return statement. */
+static stree_return_t *parse_return(parse_t *parse)
+{
+	stree_return_t *return_s;
+
+	return_s = stree_return_new();
+
+	lmatch(parse, lc_return);
+	return_s->expr = parse_expr(parse);
+	lmatch(parse, lc_scolon);
+
+	return return_s;
+}
+
 /* Parse @c with-except-finally statement. */
 static stree_wef_t *parse_wef(parse_t *parse)
Index: uspace/app/sbi/src/rdata.c
===================================================================
--- uspace/app/sbi/src/rdata.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/rdata.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -100,4 +100,17 @@
 }
 
+rdata_ref_t *rdata_ref_new(void)
+{
+	rdata_ref_t *ref;
+
+	ref = calloc(1, sizeof(rdata_ref_t));
+	if (ref == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return ref;
+}
+
 rdata_deleg_t *rdata_deleg_new(void)
 {
@@ -111,4 +124,17 @@
 
 	return deleg;
+}
+
+rdata_object_t *rdata_object_new(void)
+{
+	rdata_object_t *object;
+
+	object = calloc(1, sizeof(rdata_object_t));
+	if (object == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return object;
 }
 
@@ -181,10 +207,11 @@
 static void rdata_ref_copy(rdata_ref_t *src, rdata_ref_t **dest)
 {
-	printf("Unimplemented: Copy reference.\n");
-	exit(1);
+	*dest = rdata_ref_new();
+	(*dest)->vref = src->vref;
 }
 
 static void rdata_deleg_copy(rdata_deleg_t *src, rdata_deleg_t **dest)
 {
+	(void) src; (void) dest;
 	printf("Unimplemented: Copy delegate.\n");
 	exit(1);
@@ -193,6 +220,142 @@
 static void rdata_object_copy(rdata_object_t *src, rdata_object_t **dest)
 {
+	(void) src; (void) dest;
 	printf("Unimplemented: Copy object.\n");
 	exit(1);
+}
+
+/** Convert item to value item.
+ *
+ * If @a item is a value, we just return a copy. If @a item is an address,
+ * we read from the address.
+ */
+void rdata_cvt_value_item(rdata_item_t *item, rdata_item_t **ritem)
+{
+	rdata_value_t *value;
+
+	/* 
+	 * This can happen when trying to use output of a function which
+	 * does not return a value.
+	 */
+	if (item == NULL) {
+		printf("Error: Sub-expression has no value.\n");
+		exit(1);
+	}
+
+	/* Address item. Perform read operation. */
+	if (item->ic == ic_address) {
+		rdata_address_read(item->u.address, ritem);
+		return;
+	}
+
+	/* It already is a value, we can share the @c var. */
+	value = rdata_value_new();
+	value->var = item->u.value->var;
+	*ritem = rdata_item_new(ic_value);
+	(*ritem)->u.value = value;
+}
+
+/** Return reference to a variable.
+ *
+ * Constructs a reference (value item) pointing to @a var.
+ */
+void rdata_reference(rdata_var_t *var, rdata_item_t **res)
+{
+	rdata_ref_t *ref;
+	rdata_var_t *ref_var;
+	rdata_value_t *ref_value;
+	rdata_item_t *ref_item;
+
+	/* Create reference to the variable. */
+	ref = rdata_ref_new();
+	ref_var = rdata_var_new(vc_ref);
+	ref->vref = var;
+	ref_var->u.ref_v = ref;
+
+	/* Construct value of the reference to return. */
+	ref_item = rdata_item_new(ic_value);
+	ref_value = rdata_value_new();
+	ref_item->u.value = ref_value;
+	ref_value->var = ref_var;
+
+	*res = ref_item;
+}
+
+/** Return address of reference target.
+ *
+ * Takes a reference (address or value) and returns the address (item) of
+ * the target of the reference.
+ */
+void rdata_dereference(rdata_item_t *ref, rdata_item_t **ritem)
+{
+	rdata_item_t *ref_val;
+	rdata_item_t *item;
+	rdata_address_t *address;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("run_dereference()\n");
+#endif
+	rdata_cvt_value_item(ref, &ref_val);
+	assert(ref_val->u.value->var->vc == vc_ref);
+
+	item = rdata_item_new(ic_address);
+	address = rdata_address_new();
+	item->u.address = address;
+	address->vref = ref_val->u.value->var->u.ref_v->vref;
+
+	if (address->vref == NULL) {
+		printf("Error: Accessing null reference.\n");
+		exit(1);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("vref set to %p\n", address->vref);
+#endif
+	*ritem = item;
+}
+
+/** Read data from an address.
+ *
+ * Return value stored in a variable at the specified address.
+ */
+void rdata_address_read(rdata_address_t *address, rdata_item_t **ritem)
+{
+	rdata_value_t *value;
+	rdata_var_t *rvar;
+
+	/* Perform a shallow copy of @c var. */
+	rdata_var_copy(address->vref, &rvar);
+
+	value = rdata_value_new();
+	value->var = rvar;
+	*ritem = rdata_item_new(ic_value);
+	(*ritem)->u.value = value;
+}
+
+/** Write data to an address.
+ *
+ * Store @a value to the variable at @a address.
+ */
+void rdata_address_write(rdata_address_t *address, rdata_value_t *value)
+{
+	rdata_var_t *nvar;
+	rdata_var_t *orig_var;
+
+	/* Perform a shallow copy of @c value->var. */
+	rdata_var_copy(value->var, &nvar);
+	orig_var = address->vref;
+
+	/* XXX do this in a prettier way. */
+
+	orig_var->vc = nvar->vc;
+	switch (nvar->vc) {
+	case vc_int: orig_var->u.int_v = nvar->u.int_v; break;
+	case vc_ref: orig_var->u.ref_v = nvar->u.ref_v; break;
+	case vc_deleg: orig_var->u.deleg_v = nvar->u.deleg_v; break;
+	case vc_object: orig_var->u.object_v = nvar->u.object_v; break;
+	default: assert(b_false);
+	}
+
+	/* XXX We should free some stuff around here. */
 }
 
@@ -232,4 +395,7 @@
 		printf("int(%d)", var->u.int_v->value);
 		break;
+	case vc_string:
+		printf("string(\"%s\")", var->u.string_v->value);
+		break;
 	case vc_ref:
 		printf("ref");
@@ -242,4 +408,5 @@
 		break;
 	default:
+		printf("print(%d)\n", var->vc);
 		assert(b_false);
 	}
Index: uspace/app/sbi/src/rdata.h
===================================================================
--- uspace/app/sbi/src/rdata.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/rdata.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -36,9 +36,18 @@
 rdata_value_t *rdata_value_new(void);
 rdata_var_t *rdata_var_new(var_class_t vc);
+rdata_ref_t *rdata_ref_new(void);
 rdata_deleg_t *rdata_deleg_new(void);
+rdata_object_t *rdata_object_new(void);
 rdata_int_t *rdata_int_new(void);
 rdata_string_t *rdata_string_new(void);
 
 void rdata_var_copy(rdata_var_t *src, rdata_var_t **dest);
+
+void rdata_cvt_value_item(rdata_item_t *item, rdata_item_t **ritem);
+void rdata_reference(rdata_var_t *var, rdata_item_t **res);
+void rdata_dereference(rdata_item_t *ref, rdata_item_t **ritem);
+void rdata_address_read(rdata_address_t *address, rdata_item_t **ritem);
+void rdata_address_write(rdata_address_t *address, rdata_value_t *value);
+
 void rdata_item_print(rdata_item_t *item);
 
Index: uspace/app/sbi/src/rdata_t.h
===================================================================
--- uspace/app/sbi/src/rdata_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/rdata_t.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -74,5 +74,5 @@
 
 	/** Map field name SID to field data */
-	intmap_t *fields; /* of (rdata_var_t *) */
+	intmap_t fields; /* of (rdata_var_t *) */
 } rdata_object_t;
 
@@ -141,5 +141,5 @@
  * assignment operator.
  */
-typedef struct {
+typedef struct rdata_item {
 	item_class_t ic;
 
Index: uspace/app/sbi/src/run.c
===================================================================
--- uspace/app/sbi/src/run.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -51,10 +51,10 @@
 static void run_if(run_t *run, stree_if_t *if_s);
 static void run_while(run_t *run, stree_while_t *while_s);
-
-static void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var);
+static void run_return(run_t *run, stree_return_t *return_s);
 
 /** Initialize runner instance. */
 void run_init(run_t *run)
 {
+	(void) run;
 }
 
@@ -62,10 +62,10 @@
 void run_program(run_t *run, stree_program_t *prog)
 {
-	stree_symbol_t *main_class_sym;
 	stree_symbol_t *main_fun_sym;
-	stree_csi_t *main_class;
 	stree_fun_t *main_fun;
 	stree_ident_t *fake_ident;
 	list_t main_args;
+	run_fun_ar_t *fun_ar;
+	rdata_item_t *res;
 
 	/* Note down link to program code. */
@@ -75,33 +75,19 @@
 	run->thread_ar = run_thread_ar_new();
 	list_init(&run->thread_ar->fun_ar);
+	run->thread_ar->bo_mode = bm_none;
 
 	/*
-	 * Resolve class @c HelloWorld
+	 * Find entry point @c Main().
 	 */
 	fake_ident = stree_ident_new();
-
-	fake_ident->sid = strtab_get_sid("HelloWorld");
-	main_class_sym = symbol_lookup_in_csi(prog, NULL, fake_ident);
-	main_class = symbol_to_csi(main_class_sym);
-	if (main_class == NULL) {
-		printf("Error: HelloWorld is not a CSI.\n");
-		exit(1);
-	}
-
-#ifdef DEBUG_RUN_TRACE
-	printf("Found class '"); symbol_print_fqn(prog, main_class_sym);
-	printf("'.\n");
-#endif
-
-	/*
-	 * Resolve function @c main within the class.
-	 */
-	fake_ident->sid = strtab_get_sid("main");
-	main_fun_sym = symbol_lookup_in_csi(prog, main_class, fake_ident);
+	fake_ident->sid = strtab_get_sid("Main");
+	main_fun_sym = symbol_find_epoint(prog, fake_ident);
+	if (main_fun_sym == NULL) {
+		printf("Error: Entry point 'Main' not found.\n");
+		exit(1);
+	}
+
 	main_fun = symbol_to_fun(main_fun_sym);
-	if (main_fun == NULL) {
-		printf("Error: HelloWorld.main is not a function.\n");
-		exit(1);
-	}
+	assert(main_fun != NULL);
 
 #ifdef DEBUG_RUN_TRACE
@@ -110,21 +96,21 @@
 #endif
 
+	/* Run function @c main. */
 	list_init(&main_args);
-	run_fun(run, main_fun, &main_args);
+	run_fun_ar_create(run, NULL, main_fun, &fun_ar);
+	run_fun_ar_set_args(run, fun_ar, &main_args);
+	run_fun(run, fun_ar, &res);
 }
 
 /** Run member function */
-void run_fun(run_t *run, stree_fun_t *fun, list_t *args)
+void run_fun(run_t *run, run_fun_ar_t *fun_ar, rdata_item_t **res)
 {
 	stree_symbol_t *fun_sym;
-	run_fun_ar_t *fun_ar;
-	run_block_ar_t *block_ar;
-	list_node_t *rarg_n, *farg_n;
+	stree_fun_t *fun;
 	list_node_t *node;
-	rdata_item_t *rarg;
-	stree_fun_arg_t *farg;
-	rdata_var_t *var;
-
-	fun_sym = fun_to_symbol(fun);
+
+	fun_sym = fun_ar->fun_sym;
+	fun = symbol_to_fun(fun_sym);
+	assert(fun != NULL);
 
 #ifdef DEBUG_RUN_TRACE
@@ -133,52 +119,6 @@
 	printf("'.\n");
 #endif
-
-	/* Create function activation record. */
-	fun_ar = run_fun_ar_new();
-	fun_ar->fun_sym = fun_sym;
-	list_init(&fun_ar->block_ar);
-
 	/* Add function AR to the stack. */
 	list_append(&run->thread_ar->fun_ar, fun_ar);
-
-	/* Create special block activation record to hold function arguments. */
-	block_ar = run_block_ar_new();
-	intmap_init(&block_ar->vars);
-	list_append(&fun_ar->block_ar, block_ar);
-
-	/* Declare local variables to hold argument values. */
-	rarg_n = list_first(args);
-	farg_n = list_first(&fun->args);
-
-	while (farg_n != NULL) {
-		if (rarg_n == NULL) {
-			printf("Error: Too few arguments to function '");
-			symbol_print_fqn(run->program, fun_sym);
-			printf("'.\n");
-			exit(1);
-		}
-
-		rarg = list_node_data(rarg_n, rdata_item_t *);
-		farg = list_node_data(farg_n, stree_fun_arg_t *);
-
-		assert(rarg->ic == ic_value);
-
-		/* Construct a variable from the argument value. */
-		run_value_item_to_var(rarg, &var);
-
-		/* Declare variable using name of formal argument. */
-		intmap_set(&block_ar->vars, farg->name->sid, var);
-
-		rarg_n = list_next(args, rarg_n);
-		farg_n = list_next(&fun->args, farg_n);
-	}
-
-	/* Check for excess real parameters. */
-	if (rarg_n != NULL) {
-		printf("Error: Too many arguments to function '");
-		symbol_print_fqn(run->program, fun_sym);
-		printf("'.\n");
-		exit(1);
-	}
 
 	/* Run main function block. */
@@ -189,4 +129,16 @@
 	}
 
+	/* Handle bailout. */
+	switch (run->thread_ar->bo_mode) {
+	case bm_stat:
+		printf("Error: Misplaced 'break' statement.\n");
+		exit(1);
+	case bm_fun:
+		run->thread_ar->bo_mode = bm_none;
+		break;
+	default:
+		break;
+	}
+
 #ifdef DEBUG_RUN_TRACE
 	printf("Done executing function '");
@@ -196,9 +148,10 @@
 	run_print_fun_bt(run);
 #endif
-
 	/* Remove function activation record from the stack. */
 	node = list_last(&run->thread_ar->fun_ar);
 	assert(list_node_data(node, run_fun_ar_t *) == fun_ar);
 	list_remove(&run->thread_ar->fun_ar, node);
+
+	*res = fun_ar->retval;
 }
 
@@ -227,4 +180,8 @@
 		stat = list_node_data(node, stree_stat_t *);
 		run_stat(run, stat);
+
+		if (run->thread_ar->bo_mode != bm_none)
+			break;
+
 		node = list_next(&block->stats, node);
 	}
@@ -260,4 +217,7 @@
 		run_while(run, stat->u.while_s);
 		break;
+	case st_return:
+		run_return(run, stat->u.return_s);
+		break;
 	case st_for:
 	case st_raise:
@@ -361,4 +321,7 @@
 		run_block(run, while_s->body);
 		run_expr(run, while_s->cond, &rcond);
+
+		if (run->thread_ar->bo_mode != bm_none)
+			break;
 	}
 
@@ -366,4 +329,24 @@
 	printf("While statement terminated.\n");
 #endif
+}
+
+/** Run @c return statement. */
+static void run_return(run_t *run, stree_return_t *return_s)
+{
+	rdata_item_t *rexpr;
+	run_fun_ar_t *fun_ar;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Executing return statement.\n");
+#endif
+	run_expr(run, return_s->expr, &rexpr);
+
+	/* Store expression result in function AR. */
+	fun_ar = run_get_current_fun_ar(run);
+	fun_ar->retval = rexpr;
+
+	/* Force control to ascend and leave the function. */
+	if (run->thread_ar->bo_mode == bm_none)
+		run->thread_ar->bo_mode = bm_fun;
 }
 
@@ -421,8 +404,9 @@
  * (2) Initialize the variable with the provided value.
  */
-static void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var)
+void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var)
 {
 	rdata_int_t *int_v;
 	rdata_string_t *string_v;
+	rdata_ref_t *ref_v;
 	rdata_var_t *in_var;
 
@@ -445,8 +429,92 @@
 		string_v->value = item->u.value->var->u.string_v->value;
 		break;
+	case vc_ref:
+		*var = rdata_var_new(vc_ref);
+		ref_v = rdata_ref_new();
+
+		(*var)->u.ref_v = ref_v;
+		ref_v->vref = item->u.value->var->u.ref_v->vref;
+		break;
 	default:
 		printf("Error: Unimplemented argument type.\n");
 		exit(1);
 
+	}
+}
+
+/** Construct a function AR. */
+void run_fun_ar_create(run_t *run, rdata_var_t *obj, stree_fun_t *fun,
+    run_fun_ar_t **rfun_ar)
+{
+	run_fun_ar_t *fun_ar;
+
+	(void) run;
+
+	/* Create function activation record. */
+	fun_ar = run_fun_ar_new();
+	fun_ar->obj = obj;
+	fun_ar->fun_sym = fun_to_symbol(fun);
+	list_init(&fun_ar->block_ar);
+
+	fun_ar->retval = NULL;
+
+	*rfun_ar = fun_ar;
+}
+
+/** Fill arguments in a function AR. */
+void run_fun_ar_set_args(run_t *run, run_fun_ar_t *fun_ar, list_t *args)
+{
+	stree_fun_t *fun;
+	run_block_ar_t *block_ar;
+	list_node_t *rarg_n, *farg_n;
+	rdata_item_t *rarg;
+	stree_fun_arg_t *farg;
+	rdata_var_t *var;
+
+	/* AR should have been created with run_fun_ar_create(). */
+	assert(fun_ar->fun_sym != NULL);
+	assert(list_is_empty(&fun_ar->block_ar));
+
+	fun = symbol_to_fun(fun_ar->fun_sym);
+	assert(fun != NULL);
+
+	/* Create special block activation record to hold function arguments. */
+	block_ar = run_block_ar_new();
+	intmap_init(&block_ar->vars);
+	list_append(&fun_ar->block_ar, block_ar);
+
+	/* Declare local variables to hold argument values. */
+	rarg_n = list_first(args);
+	farg_n = list_first(&fun->args);
+
+	while (farg_n != NULL) {
+		if (rarg_n == NULL) {
+			printf("Error: Too few arguments to function '");
+			symbol_print_fqn(run->program, fun_ar->fun_sym);
+			printf("'.\n");
+			exit(1);
+		}
+
+		rarg = list_node_data(rarg_n, rdata_item_t *);
+		farg = list_node_data(farg_n, stree_fun_arg_t *);
+
+		assert(rarg->ic == ic_value);
+
+		/* Construct a variable from the argument value. */
+		run_value_item_to_var(rarg, &var);
+
+		/* Declare variable using name of formal argument. */
+		intmap_set(&block_ar->vars, farg->name->sid, var);
+
+		rarg_n = list_next(args, rarg_n);
+		farg_n = list_next(&fun->args, farg_n);
+	}
+
+	/* Check for excess real parameters. */
+	if (rarg_n != NULL) {
+		printf("Error: Too many arguments to function '");
+		symbol_print_fqn(run->program, fun_ar->fun_sym);
+		printf("'.\n");
+		exit(1);
 	}
 }
Index: uspace/app/sbi/src/run.h
===================================================================
--- uspace/app/sbi/src/run.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -34,5 +34,5 @@
 void run_init(run_t *run);
 void run_program(run_t *run, stree_program_t *prog);
-void run_fun(run_t *run, stree_fun_t *fun, list_t *args);
+void run_fun(run_t *run, run_fun_ar_t *fun_ar, rdata_item_t **res);
 
 void run_print_fun_bt(run_t *run);
@@ -42,4 +42,9 @@
 run_block_ar_t *run_get_current_block_ar(run_t *run);
 
+void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var);
+void run_fun_ar_set_args(run_t *run, run_fun_ar_t *fun_ar, list_t *args);
+void run_fun_ar_create(run_t *run, rdata_var_t *obj, stree_fun_t *fun,
+    run_fun_ar_t **rfun_ar);
+
 run_thread_ar_t *run_thread_ar_new(void);
 run_fun_ar_t *run_fun_ar_new(void);
Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run_expr.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -33,4 +33,5 @@
 #include <assert.h>
 #include "debug.h"
+#include "intmap.h"
 #include "list.h"
 #include "mytypes.h"
@@ -44,20 +45,38 @@
 static void run_nameref(run_t *run, stree_nameref_t *nameref,
     rdata_item_t **res);
+
 static void run_literal(run_t *run, stree_literal_t *literal,
     rdata_item_t **res);
 static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
     rdata_item_t **res);
+static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
+    rdata_item_t **res);
 static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
     rdata_item_t **res);
+
+static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
+    rdata_item_t **res);
+
 static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
+static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
+    rdata_value_t *v2, rdata_item_t **res);
+static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
+    rdata_value_t *v2, rdata_item_t **res);
+
 static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res);
+static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res);
+
 static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res);
+static void run_access_item(run_t *run, stree_access_t *access,
+    rdata_item_t *arg, rdata_item_t **res);
+static void run_access_ref(run_t *run, stree_access_t *access,
+    rdata_item_t *arg, rdata_item_t **res);
+static void run_access_deleg(run_t *run, stree_access_t *access,
+    rdata_item_t *arg, rdata_item_t **res);
+static void run_access_object(run_t *run, stree_access_t *access,
+    rdata_item_t *arg, rdata_item_t **res);
+
 static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
 static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
-
-static void run_address_read(run_t *run, rdata_address_t *address,
-    rdata_item_t **ritem);
-static void run_address_write(run_t *run, rdata_address_t *address,
-    rdata_value_t *value);
 
 /** Evaluate expression. */
@@ -75,4 +94,7 @@
 		run_literal(run, expr->u.literal, res);
 		break;
+	case ec_self_ref:
+		run_self_ref(run, expr->u.self_ref, res);
+		break;
 	case ec_binop:
 		run_binop(run, expr->u.binop, res);
@@ -80,4 +102,7 @@
 	case ec_unop:
 		run_unop(run, expr->u.unop, res);
+		break;
+	case ec_new:
+		run_new(run, expr->u.new_op, res);
 		break;
 	case ec_access:
@@ -106,7 +131,13 @@
 	rdata_item_t *item;
 	rdata_address_t *address;
-	rdata_value_t *val;
+	rdata_value_t *value;
 	rdata_var_t *var;
 	rdata_deleg_t *deleg_v;
+
+	run_fun_ar_t *fun_ar;
+	stree_symbol_t *csi_sym;
+	stree_csi_t *csi;
+	rdata_object_t *obj;
+	rdata_var_t *member_var;
 
 #ifdef DEBUG_RUN_TRACE
@@ -137,6 +168,18 @@
 	 */
 
-	/* XXX Start lookup in currently active CSI. */
-	sym = symbol_lookup_in_csi(run->program, NULL, nameref->name);
+	/* Determine currently active object or CSI. */
+	fun_ar = run_get_current_fun_ar(run);
+	if (fun_ar->obj != NULL) {
+		assert(fun_ar->obj->vc == vc_object);
+		obj = fun_ar->obj->u.object_v;
+		csi_sym = obj->class_sym;
+		csi = symbol_to_csi(csi_sym);
+		assert(csi != NULL);
+	} else {
+		csi = fun_ar->fun_sym->outer_csi;
+		obj = NULL;
+	}
+
+	sym = symbol_lookup_in_csi(run->program, csi, nameref->name);
 
 	switch (sym->sc) {
@@ -146,10 +189,10 @@
 #endif
 		item = rdata_item_new(ic_value);
-		val = rdata_value_new();
+		value = rdata_value_new();
 		var = rdata_var_new(vc_deleg);
 		deleg_v = rdata_deleg_new();
 
-		item->u.value = val;
-		val->var = var;
+		item->u.value = value;
+		value->var = var;
 		var->u.deleg_v = deleg_v;
 
@@ -158,4 +201,68 @@
 		*res = item;
 		break;
+	case sc_fun:
+		/* There should be no global functions. */
+		assert(csi != NULL);
+
+		if (sym->outer_csi != csi) {
+			/* Function is not in the current object. */
+			printf("Error: Cannot access non-static member "
+			    "function '");
+			symbol_print_fqn(run->program, sym);
+			printf("' from nested CSI '");
+			symbol_print_fqn(run->program, csi_sym);
+			printf("'.\n");
+			exit(1);
+		}
+
+		/* Construct delegate. */
+		item = rdata_item_new(ic_value);
+		value = rdata_value_new();
+		item->u.value = value;
+
+		var = rdata_var_new(vc_deleg);
+		deleg_v = rdata_deleg_new();
+		value->var = var;
+		var->u.deleg_v = deleg_v;
+
+		deleg_v->obj = fun_ar->obj;
+		deleg_v->sym = sym;
+
+		*res = item;
+		break;
+	case sc_var:
+#ifdef DEBUG_RUN_TRACE
+		printf("Referencing member variable.\n");
+#endif
+		/* There should be no global variables. */
+		assert(csi != NULL);
+
+		/* XXX Assume variable is not static for now. */
+		assert(obj != NULL);
+
+		if (sym->outer_csi != csi) {
+			/* Variable is not in the current object. */
+			printf("Error: Cannot access non-static member "
+			    "variable '");
+			symbol_print_fqn(run->program, sym);
+			printf("' from nested CSI '");
+			symbol_print_fqn(run->program, csi_sym);
+			printf("'.\n");
+			exit(1);
+		}
+
+		/* Find member variable in object. */
+		member_var = intmap_get(&obj->fields, nameref->name->sid);
+		assert(member_var != NULL);
+
+		/* Return address of the variable. */
+		item = rdata_item_new(ic_address);
+		address = rdata_address_new();
+
+		item->u.address = address;
+		address->vref = member_var;
+
+		*res = item;
+		break;
 	default:
 		printf("Referencing symbol class %d unimplemented.\n", sym->sc);
@@ -176,4 +283,7 @@
 	case ltc_int:
 		run_lit_int(run, &literal->u.lit_int, res);
+		break;
+	case ltc_ref:
+		run_lit_ref(run, &literal->u.lit_ref, res);
 		break;
 	case ltc_string:
@@ -197,4 +307,5 @@
 	printf("Run integer literal.\n");
 #endif
+	(void) run;
 
 	item = rdata_item_new(ic_value);
@@ -211,4 +322,32 @@
 }
 
+/** Evaluate reference literal (@c nil). */
+static void run_lit_ref(run_t *run, stree_lit_ref_t *lit_ref,
+    rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_ref_t *ref_v;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run reference literal (nil).\n");
+#endif
+	(void) run;
+	(void) lit_ref;
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_ref);
+	ref_v = rdata_ref_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.ref_v = ref_v;
+	ref_v->vref = NULL;
+
+	*res = item;
+}
+
 /** Evaluate string literal. */
 static void run_lit_string(run_t *run, stree_lit_string_t *lit_string,
@@ -223,4 +362,6 @@
 	printf("Run integer literal.\n");
 #endif
+	(void) run;
+
 	item = rdata_item_new(ic_value);
 	value = rdata_value_new();
@@ -236,4 +377,19 @@
 }
 
+/** Evaluate @c self reference. */
+static void run_self_ref(run_t *run, stree_self_ref_t *self_ref,
+    rdata_item_t **res)
+{
+	run_fun_ar_t *fun_ar;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run self reference.\n");
+#endif
+	(void) self_ref;
+	fun_ar = run_get_current_fun_ar(run);
+
+	/* Return reference to the currently active object. */
+	rdata_reference(fun_ar->obj, res);
+}
 
 /** Evaluate binary operation. */
@@ -243,10 +399,4 @@
 	rdata_item_t *rarg1_vi, *rarg2_vi;
 	rdata_value_t *v1, *v2;
-	int i1, i2;
-
-	rdata_item_t *item;
-	rdata_value_t *value;
-	rdata_var_t *var;
-	rdata_int_t *int_v;
 
 #ifdef DEBUG_RUN_TRACE
@@ -276,15 +426,42 @@
 #endif
 
-	run_cvt_value_item(run, rarg1_i, &rarg1_vi);
-	run_cvt_value_item(run, rarg2_i, &rarg2_vi);
+	rdata_cvt_value_item(rarg1_i, &rarg1_vi);
+	rdata_cvt_value_item(rarg2_i, &rarg2_vi);
 
 	v1 = rarg1_vi->u.value;
 	v2 = rarg2_vi->u.value;
 
-	if (v1->var->vc != vc_int || v2->var->vc != vc_int) {
-		printf("Unimplemented: Binary operation arguments are not "
-		    "integer values.\n");
-		exit(1);
-	}
+	if (v1->var->vc != v2->var->vc) {
+		printf("Unimplemented: Binary operation arguments have "
+		    "different type.\n");
+		exit(1);
+	}
+
+	switch (v1->var->vc) {
+	case vc_int:
+		run_binop_int(run, binop, v1, v2, res);
+		break;
+	case vc_ref:
+		run_binop_ref(run, binop, v1, v2, res);
+		break;
+	default:
+		printf("Unimplemented: Binary operation arguments of "
+		    "type %d.\n", v1->var->vc);
+		exit(1);
+	}
+}
+
+/** Evaluate binary operation on int arguments. */
+static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
+    rdata_value_t *v2, rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_int_t *int_v;
+
+	int i1, i2;
+
+	(void) run;
 
 	item = rdata_item_new(ic_value);
@@ -331,4 +508,47 @@
 }
 
+/** Evaluate binary operation on ref arguments. */
+static void run_binop_ref(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
+    rdata_value_t *v2, rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_int_t *int_v;
+
+	rdata_var_t *ref1, *ref2;
+
+	(void) run;
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_int);
+	int_v = rdata_int_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.int_v = int_v;
+
+	ref1 = v1->var->u.ref_v->vref;
+	ref2 = v2->var->u.ref_v->vref;
+
+	switch (binop->bc) {
+	/* XXX We should have a real boolean type. */
+	case bo_equal:
+		int_v->value = (ref1 == ref2) ? 1 : 0;
+		break;
+	case bo_notequal:
+		int_v->value = (ref1 != ref2) ? 1 : 0;
+		break;
+	default:
+		printf("Error: Invalid binary operation on reference "
+		    "arguments (%d).\n", binop->bc);
+		assert(b_false);
+	}
+
+	*res = item;
+}
+
+
 /** Evaluate unary operation. */
 static void run_unop(run_t *run, stree_unop_t *unop, rdata_item_t **res)
@@ -343,48 +563,248 @@
 }
 
+/** Evaluate @c new operation. */
+static void run_new(run_t *run, stree_new_t *new_op, rdata_item_t **res)
+{
+	rdata_object_t *obj;
+	rdata_var_t *obj_var;
+
+	stree_symbol_t *csi_sym;
+	stree_csi_t *csi;
+	stree_csimbr_t *csimbr;
+
+	rdata_var_t *mbr_var;
+
+	list_node_t *node;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run 'new' operation.\n");
+#endif
+	/* Lookup object CSI. */
+	/* XXX Should start in the current CSI. */
+	csi_sym = symbol_xlookup_in_csi(run->program, NULL, new_op->texpr);
+	csi = symbol_to_csi(csi_sym);
+	if (csi == NULL) {
+		printf("Error: Symbol '");
+		symbol_print_fqn(run->program, csi_sym);
+		printf("' is not a CSI. CSI required for 'new' operator.\n");
+		exit(1);
+	}
+
+	/* Create the object. */
+	obj = rdata_object_new();
+	obj->class_sym = csi_sym;
+	intmap_init(&obj->fields);
+
+	obj_var = rdata_var_new(vc_object);
+	obj_var->u.object_v = obj;
+
+	/* Create object fields. */
+	node = list_first(&csi->members);
+	while (node != NULL) {
+		csimbr = list_node_data(node, stree_csimbr_t *);
+		if (csimbr->cc == csimbr_var) {
+			/* XXX Depends on member variable type. */
+			mbr_var = rdata_var_new(vc_int);
+			mbr_var->u.int_v = rdata_int_new();
+			mbr_var->u.int_v->value = 0;
+
+			intmap_set(&obj->fields, csimbr->u.var->name->sid,
+			    mbr_var);
+		}
+
+		node = list_next(&csi->members, node);
+	}
+
+	/* Create reference to the new object. */
+	rdata_reference(obj_var, res);
+}
+
 /** Evaluate member acccess. */
 static void run_access(run_t *run, stree_access_t *access, rdata_item_t **res)
 {
 	rdata_item_t *rarg;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run access operation.\n");
+#endif
+	run_expr(run, access->arg, &rarg);
+	if (rarg == NULL) {
+		printf("Error: Sub-expression has no value.\n");
+		exit(1);
+	}
+
+	run_access_item(run, access, rarg, res);
+}
+
+/** Evaluate member acccess (with base already evaluated). */
+static void run_access_item(run_t *run, stree_access_t *access,
+    rdata_item_t *arg, rdata_item_t **res)
+{
+	var_class_t vc;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run access operation on pre-evaluated base.\n");
+#endif
+	switch (arg->ic) {
+	case ic_value:
+		vc = arg->u.value->var->vc;
+		break;
+	case ic_address:
+		vc = arg->u.address->vref->vc;
+		break;
+	default:
+		/* Silence warning. */
+		abort();
+	}
+
+	switch (vc) {
+	case vc_ref:
+		run_access_ref(run, access, arg, res);
+		break;
+	case vc_deleg:
+		run_access_deleg(run, access, arg, res);
+		break;
+	case vc_object:
+		run_access_object(run, access, arg, res);
+		break;
+	default:
+		printf("Unimplemented: Using access operator ('.') "
+		    "with unsupported data type (value/%d).\n", vc);
+		exit(1);
+	}
+}
+
+/** Evaluate reference acccess. */
+static void run_access_ref(run_t *run, stree_access_t *access,
+    rdata_item_t *arg, rdata_item_t **res)
+{
+	rdata_item_t *darg;
+
+	/* Implicitly dereference. */
+	rdata_dereference(arg, &darg);
+
+	/* Try again. */
+	run_access_item(run, access, darg, res);
+}
+
+/** Evaluate delegate-member acccess. */
+static void run_access_deleg(run_t *run, stree_access_t *access,
+    rdata_item_t *arg, rdata_item_t **res)
+{
+	rdata_item_t *arg_vi;
+	rdata_value_t *arg_val;
 	rdata_deleg_t *deleg_v;
 	stree_symbol_t *member;
 
 #ifdef DEBUG_RUN_TRACE
-	printf("Run access operation.\n");
-#endif
-	run_expr(run, access->arg, &rarg);
-
-	if (rarg->ic == ic_value && rarg->u.value->var->vc == vc_deleg) {
-#ifdef DEBUG_RUN_TRACE
-		printf("Accessing delegate.\n");
-#endif
-		deleg_v = rarg->u.value->var->u.deleg_v;
-		if (deleg_v->obj != NULL || deleg_v->sym->sc != sc_csi) {
-			printf("Error: Using '.' with symbol of wrong "
-			    "type (%d).\n", deleg_v->sym->sc);
-			exit(1);
-		}
-
-		member = symbol_search_csi(run->program, deleg_v->sym->u.csi,
-		    access->member_name);
-
-		if (member == NULL) {
-			printf("Error: No such member.\n");
-			exit(1);
-		}
-
-#ifdef DEBUG_RUN_TRACE
-		printf("Found member '%s'.\n",
+	printf("Run delegate access operation.\n");
+#endif
+	rdata_cvt_value_item(arg, &arg_vi);
+	arg_val = arg_vi->u.value;
+	assert(arg_val->var->vc == vc_deleg);
+
+	deleg_v = arg_val->var->u.deleg_v;
+	if (deleg_v->obj != NULL || deleg_v->sym->sc != sc_csi) {
+		printf("Error: Using '.' with delegate to different object "
+		    "than a CSI (%d).\n", deleg_v->sym->sc);
+		exit(1);
+	}
+
+	member = symbol_search_csi(run->program, deleg_v->sym->u.csi,
+	    access->member_name);
+
+	if (member == NULL) {
+		printf("Error: CSI '");
+		symbol_print_fqn(run->program, deleg_v->sym);
+		printf("' has no member named '%s'.\n",
 		    strtab_get_str(access->member_name->sid));
-#endif
-
-		/* Reuse existing item, value, var, deleg. */
+		exit(1);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Found member '%s'.\n",
+	    strtab_get_str(access->member_name->sid));
+#endif
+
+	/*
+	 * Reuse existing item, value, var, deleg.
+	 * XXX This is maybe not a good idea because it complicates memory
+	 * management as there is not a single owner 
+	 */
+	deleg_v->sym = member;
+	*res = arg;
+}
+
+/** Evaluate object member acccess. */
+static void run_access_object(run_t *run, stree_access_t *access,
+    rdata_item_t *arg, rdata_item_t **res)
+{
+	stree_symbol_t *member;
+	rdata_object_t *object;
+	rdata_item_t *ritem;
+	rdata_address_t *address;
+
+	rdata_value_t *value;
+	rdata_deleg_t *deleg_v;
+	rdata_var_t *var;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run object access operation.\n");
+#endif
+	assert(arg->ic == ic_address);
+	assert(arg->u.value->var->vc == vc_object);
+
+	object = arg->u.value->var->u.object_v;
+
+	member = symbol_search_csi(run->program, object->class_sym->u.csi,
+	    access->member_name);
+
+	if (member == NULL) {
+		printf("Error: Object of class '");
+		symbol_print_fqn(run->program, object->class_sym);
+		printf("' has no member named '%s'.\n",
+		    strtab_get_str(access->member_name->sid));
+		exit(1);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Found member '%s'.\n",
+	    strtab_get_str(access->member_name->sid));
+#endif
+
+	switch (member->sc) {
+	case sc_csi:
+		printf("Error: Accessing object member which is nested CSI.\n");
+		exit(1);
+	case sc_fun:
+		/* Construct delegate. */
+		ritem = rdata_item_new(ic_value);
+		value = rdata_value_new();
+		ritem->u.value = value;
+
+		var = rdata_var_new(vc_deleg);
+		value->var = var;
+		deleg_v = rdata_deleg_new();
+		var->u.deleg_v = deleg_v;
+
+		deleg_v->obj = arg->u.value->var;
 		deleg_v->sym = member;
-
-		*res = rarg;
-		return;
-	}
-
-	*res = NULL;
+		break;
+	case sc_var:
+		/* Construct variable address item. */
+		ritem = rdata_item_new(ic_address);
+		address = rdata_address_new();
+		ritem->u.address = address;
+
+		address->vref = intmap_get(&object->fields,
+		    access->member_name->sid);
+		assert(address->vref != NULL);
+		break;
+	case sc_prop:
+		printf("Unimplemented: Accessing object property.\n");
+		exit(1);
+	}
+
+	*res = ritem;
 }
 
@@ -399,4 +819,7 @@
 	rdata_item_t *rarg_i, *rarg_vi;
 
+	stree_fun_t *fun;
+	run_fun_ar_t *fun_ar;
+
 #ifdef DEBUG_RUN_TRACE
 	printf("Run call operation.\n");
@@ -422,5 +845,4 @@
 	printf("'\n");
 #endif
-
 	/* Evaluate function arguments. */
 	list_init(&arg_vals);
@@ -430,5 +852,5 @@
 		arg = list_node_data(node, stree_expr_t *);
 		run_expr(run, arg, &rarg_i);
-		run_cvt_value_item(run, rarg_i, &rarg_vi);
+		rdata_cvt_value_item(rarg_i, &rarg_vi);
 
 		list_append(&arg_vals, rarg_vi);
@@ -436,10 +858,19 @@
 	}
 
-	run_fun(run, deleg_v->sym->u.fun, &arg_vals);
+	fun = symbol_to_fun(deleg_v->sym);
+	assert(fun != NULL);
+
+	/* Create function activation record. */
+	run_fun_ar_create(run, deleg_v->obj, fun, &fun_ar);
+
+	/* Fill in argument values. */
+	run_fun_ar_set_args(run, fun_ar, &arg_vals);
+
+	/* Run the function. */
+	run_fun(run, fun_ar, res);
 
 #ifdef DEBUG_RUN_TRACE
 	printf("Returned from function call.\n");
 #endif
-	*res = NULL;
 }
 
@@ -457,5 +888,5 @@
 	run_expr(run, assign->src, &rsrc_i);
 
-	run_cvt_value_item(run, rsrc_i, &rsrc_vi);
+	rdata_cvt_value_item(rsrc_i, &rsrc_vi);
 	src_val = rsrc_vi->u.value;
 
@@ -466,5 +897,5 @@
 	}
 
-	run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
+	rdata_address_write(rdest_i->u.address, rsrc_vi->u.value);
 
 	*res = NULL;
@@ -483,5 +914,6 @@
 	rdata_var_t *var;
 
-	run_cvt_value_item(run, item, &vitem);
+	(void) run;
+	rdata_cvt_value_item(item, &vitem);
 
 	assert(vitem->ic == ic_value);
@@ -495,73 +927,2 @@
 	return (var->u.int_v->value != 0);
 }
-
-/** Convert item to value item.
- *
- * If @a item is a value, we just return a copy. If @a item is an address,
- * we read from the address.
- */
-void run_cvt_value_item(run_t *run, rdata_item_t *item,
-    rdata_item_t **ritem)
-{
-	rdata_value_t *value;
-
-	/* Address item. Perform read operation. */
-	if (item->ic == ic_address) {
-		run_address_read(run, item->u.address, ritem);
-		return;
-	}
-
-	/* It already is a value, we can share the @c var. */
-	value = rdata_value_new();
-	value->var = item->u.value->var;
-	*ritem = rdata_item_new(ic_value);
-	(*ritem)->u.value = value;
-}
-
-/** Read data from an address.
- *
- * Return value stored in a variable at the specified address.
- */
-static void run_address_read(run_t *run, rdata_address_t *address,
-    rdata_item_t **ritem)
-{
-	rdata_value_t *value;
-	rdata_var_t *rvar;
-	(void) run;
-
-	/* Perform a shallow copy of @c var. */
-	rdata_var_copy(address->vref, &rvar);
-
-	value = rdata_value_new();
-	value->var = rvar;
-	*ritem = rdata_item_new(ic_value);
-	(*ritem)->u.value = value;
-}
-
-/** Write data to an address.
- *
- * Store @a value to the variable at @a address.
- */
-static void run_address_write(run_t *run, rdata_address_t *address,
-    rdata_value_t *value)
-{
-	rdata_var_t *nvar;
-	rdata_var_t *orig_var;
-
-	/* Perform a shallow copy of @c value->var. */
-	rdata_var_copy(value->var, &nvar);
-	orig_var = address->vref;
-
-	/* XXX do this in a prettier way. */
-
-	orig_var->vc = nvar->vc;
-	switch (nvar->vc) {
-	case vc_int: orig_var->u.int_v = nvar->u.int_v; break;
-	case vc_ref: orig_var->u.ref_v = nvar->u.ref_v; break;
-	case vc_deleg: orig_var->u.deleg_v = nvar->u.deleg_v; break;
-	case vc_object: orig_var->u.object_v = nvar->u.object_v; break;
-	default: assert(b_false);
-	}
-
-	/* XXX We should free some stuff around here. */
-}
Index: uspace/app/sbi/src/run_expr.h
===================================================================
--- uspace/app/sbi/src/run_expr.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run_expr.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -34,6 +34,4 @@
 void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res);
 
-void run_cvt_value_item(run_t *run, rdata_item_t *item,
-    rdata_item_t **ritem);
 bool_t run_item_boolean_value(run_t *run, rdata_item_t *item);
 
Index: uspace/app/sbi/src/run_t.h
===================================================================
--- uspace/app/sbi/src/run_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/run_t.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -43,4 +43,5 @@
 } run_block_ar_t;
 
+
 /** Function activation record
  *
@@ -48,4 +49,7 @@
  */
 typedef struct run_fun_ar {
+	/** Object on which the member function is being invoked or @c NULL. */
+	struct rdata_var *obj;
+
 	/** Definition of function being invoked */
 	struct stree_symbol *fun_sym;
@@ -53,5 +57,23 @@
 	/** Block activation records */
 	list_t block_ar; /* of run_block_ar_t */
+
+	/** Function return value or @c NULL if not set. */
+	struct rdata_item *retval;
 } run_fun_ar_t;
+
+/** Bailout mode
+ *
+ * Determines whether control is bailing out of a statement, function, etc.
+ */
+typedef enum {
+	/** Normal execution */
+	bm_none,
+
+	/** Break from statement */
+	bm_stat,
+
+	/** Return from function */
+	bm_fun
+} run_bailout_mode;
 
 /** Thread activation record
@@ -60,6 +82,9 @@
  */
 typedef struct run_thread_ar {
-	/** Function activation records. */
+	/** Function activation records */
 	list_t fun_ar; /* of run_fun_ar_t */
+
+	/** Bailout mode */
+	run_bailout_mode bo_mode;
 } run_thread_ar_t;
 
Index: uspace/app/sbi/src/stree.c
===================================================================
--- uspace/app/sbi/src/stree.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/stree.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -228,4 +228,17 @@
 }
 
+stree_return_t *stree_return_new(void)
+{
+	stree_return_t *return_s;
+
+	return_s = calloc(1, sizeof(stree_return_t));
+	if (return_s == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return return_s;
+}
+
 stree_wef_t *stree_wef_new(void)
 {
@@ -309,4 +322,17 @@
 }
 
+stree_new_t *stree_new_new(void)
+{
+	stree_new_t *new_op;
+
+	new_op = calloc(1, sizeof(stree_new_t));
+	if (new_op == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return new_op;
+}
+
 stree_access_t *stree_access_new(void)
 {
@@ -375,4 +401,17 @@
 }
 
+stree_self_ref_t *stree_self_ref_new(void)
+{
+	stree_self_ref_t *self_ref;
+
+	self_ref = calloc(1, sizeof(stree_self_ref_t));
+	if (self_ref == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return self_ref;
+}
+
 stree_texpr_t *stree_texpr_new(texpr_class_t tc)
 {
@@ -415,4 +454,17 @@
 }
 
+stree_tliteral_t *stree_tliteral_new(void)
+{
+	stree_tliteral_t *tliteral;
+
+	tliteral = calloc(1, sizeof(stree_tliteral_t));
+	if (tliteral == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return tliteral;
+}
+
 stree_tnameref_t *stree_tnameref_new(void)
 {
Index: uspace/app/sbi/src/stree.h
===================================================================
--- uspace/app/sbi/src/stree.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/stree.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -48,4 +48,5 @@
 stree_for_t *stree_for_new(void);
 stree_raise_t *stree_raise_new(void);
+stree_return_t *stree_return_new(void);
 stree_wef_t *stree_wef_new(void);
 stree_exps_t *stree_exps_new(void);
@@ -55,4 +56,5 @@
 stree_assign_t *stree_assign_new(assign_class_t ac);
 stree_binop_t *stree_binop_new(binop_class_t bc);
+stree_new_t *stree_new_new(void);
 stree_access_t *stree_access_new(void);
 stree_call_t *stree_call_new(void);
@@ -61,8 +63,10 @@
 stree_ident_t *stree_ident_new(void);
 stree_literal_t *stree_literal_new(literal_class_t ltc);
+stree_self_ref_t *stree_self_ref_new(void);
 
 stree_texpr_t *stree_texpr_new(texpr_class_t tc);
 stree_tapply_t *stree_tapply_new(void);
 stree_taccess_t *stree_taccess_new(void);
+stree_tliteral_t *stree_tliteral_new(void);
 stree_tnameref_t *stree_tnameref_new(void);
 
Index: uspace/app/sbi/src/stree_t.h
===================================================================
--- uspace/app/sbi/src/stree_t.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/stree_t.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -48,8 +48,16 @@
 } stree_nameref_t;
 
+/** Reference to currently active object. */
+typedef struct {
+} stree_self_ref_t;
+
 typedef struct {
 	int value;
 } stree_lit_int_t;
 
+/** Reference literal (there is only one: @c nil). */
+typedef struct {
+} stree_lit_ref_t;
+
 typedef struct {
 	char *value;
@@ -58,4 +66,5 @@
 typedef enum {
 	ltc_int,
+	ltc_ref,
 	ltc_string
 } literal_class_t;
@@ -66,4 +75,5 @@
 	union {
 		stree_lit_int_t lit_int;
+		stree_lit_ref_t lit_ref;
 		stree_lit_string_t lit_string;
 	} u;
@@ -107,4 +117,10 @@
 } stree_unop_t;
 
+/** New operation */
+typedef struct {
+	/** Type of object to construct. */
+	struct stree_texpr *texpr;
+} stree_new_t;
+
 /** Member access operation */
 typedef struct {
@@ -139,6 +155,8 @@
 	ec_nameref,
 	ec_literal,
+	ec_self_ref,
 	ec_binop,
 	ec_unop,
+	ec_new,
 	ec_access,
 	ec_call,
@@ -153,6 +171,8 @@
 		stree_nameref_t *nameref;
 		stree_literal_t *literal;
+		stree_self_ref_t *self_ref;
 		stree_binop_t *binop;
 		stree_unop_t *unop;
+		stree_new_t *new_op;
 		stree_access_t *access;
 		stree_call_t *call;
@@ -166,4 +186,15 @@
 
 struct stree_texpr;
+
+/** Type literal class */
+typedef enum {
+	tlc_int,
+	tlc_string
+} tliteral_class_t;
+
+/** Type literal */
+typedef struct {
+	tliteral_class_t tlc;
+} stree_tliteral_t;
 
 /** Type name reference */
@@ -188,4 +219,5 @@
 /** Type expression class */
 typedef enum {
+	tc_tliteral,
 	tc_tnameref,
 	tc_taccess,
@@ -198,4 +230,5 @@
 
 	union {
+		stree_tliteral_t *tliteral;
 		stree_tnameref_t *tnameref;
 		stree_taccess_t *taccess;
@@ -241,4 +274,9 @@
 typedef struct {
 } stree_raise_t;
+
+/** Return statement */
+typedef struct {
+	stree_expr_t *expr;
+} stree_return_t;
 
 /** Expression statement */
@@ -261,4 +299,5 @@
 	st_for,
 	st_raise,
+	st_return,
 	st_exps,
 	st_wef
@@ -275,4 +314,5 @@
 		stree_for_t *for_s;
 		stree_raise_t *raise_s;
+		stree_return_t *return_s;
 		stree_exps_t *exp_s;
 		stree_wef_t *wef_s;
Index: uspace/app/sbi/src/symbol.c
===================================================================
--- uspace/app/sbi/src/symbol.c	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/symbol.c	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -40,4 +40,6 @@
 static stree_symbol_t *symbol_search_global(stree_program_t *prog,
     stree_ident_t *name);
+static stree_symbol_t *symbol_find_epoint_rec(stree_program_t *prog,
+    stree_ident_t *name, stree_csi_t *csi);
 static stree_ident_t *symbol_get_ident(stree_symbol_t *symbol);
 
@@ -92,5 +94,5 @@
 
 	if (symbol == NULL) {
-		printf("Error: Symbol '%s' not found\n", strtab_get_str(name->sid));
+		printf("Error: Symbol '%s' not found.\n", strtab_get_str(name->sid));
 		exit(1);
 	}
@@ -111,4 +113,10 @@
 	stree_symbol_t *symbol;
 	stree_ident_t *mbr_name;
+	stree_symbol_t *base_csi_sym;
+	stree_csi_t *base_csi;
+
+	(void) prog;
+
+	/* Look in new members in this class. */
 
 	node = list_first(&scope->members);
@@ -146,4 +154,15 @@
 	}
 
+	/* Try inherited members. */
+	if (scope->base_csi_ref != NULL) {
+		base_csi_sym = symbol_xlookup_in_csi(prog,
+		    csi_to_symbol(scope)->outer_csi, scope->base_csi_ref);
+		base_csi = symbol_to_csi(base_csi_sym);
+		assert(base_csi != NULL);
+
+		return symbol_search_csi(prog, base_csi, name);
+	}
+
+	/* No match */
 	return NULL;
 }
@@ -176,4 +195,74 @@
 }
 
+/** Find entry point. */
+stree_symbol_t *symbol_find_epoint(stree_program_t *prog, stree_ident_t *name)
+{
+	list_node_t *node;
+	stree_modm_t *modm;
+	stree_symbol_t *entry, *etmp;
+
+	entry = NULL;
+
+	node = list_first(&prog->module->members);
+	while (node != NULL) {
+		modm = list_node_data(node, stree_modm_t *);
+		if (modm->mc == mc_csi) {
+			etmp = symbol_find_epoint_rec(prog, name, modm->u.csi);
+			if (etmp != NULL) {
+				if (entry != NULL) {
+					printf("Error: Duplicate entry point.\n");
+					exit(1);
+				}
+				entry = etmp;
+			}
+		}
+	    	node = list_next(&prog->module->members, node);
+	}
+
+	return entry;
+}
+
+static stree_symbol_t *symbol_find_epoint_rec(stree_program_t *prog,
+    stree_ident_t *name, stree_csi_t *csi)
+{
+	list_node_t *node;
+	stree_csimbr_t *csimbr;
+	stree_symbol_t *entry, *etmp;
+
+	entry = NULL;
+
+	node = list_first(&csi->members);
+	while (node != NULL) {
+		csimbr = list_node_data(node, stree_csimbr_t *);
+
+		switch (csimbr->cc) {
+		case csimbr_csi:
+			etmp = symbol_find_epoint_rec(prog, name, csimbr->u.csi);
+			if (etmp != NULL) {
+				if (entry != NULL) {
+					printf("Error: Duplicate entry point.\n");
+					exit(1);
+				}
+				entry = etmp;
+			}
+			break;
+		case csimbr_fun:
+			if (csimbr->u.fun->name->sid == name->sid) {
+				if (entry != NULL) {
+					printf("Error: Duplicate entry point.\n");
+					exit(1);
+				}
+				entry = fun_to_symbol(csimbr->u.fun);
+			}
+		default:
+			break;
+		}
+
+	    	node = list_next(&csi->members, node);
+	}
+
+	return entry;
+}
+
 stree_csi_t *symbol_to_csi(stree_symbol_t *symbol)
 {
Index: uspace/app/sbi/src/symbol.h
===================================================================
--- uspace/app/sbi/src/symbol.h	(revision 09ababb72064b384cf70e51c6b186a578020991e)
+++ uspace/app/sbi/src/symbol.h	(revision fa36f294e6a3f5cc4a846e9b33621971e0cc3d07)
@@ -38,5 +38,5 @@
 stree_symbol_t *symbol_search_csi(stree_program_t *prog, stree_csi_t *scope,
     stree_ident_t *name);
-
+stree_symbol_t *symbol_find_epoint(stree_program_t *prog, stree_ident_t *name);
 
 stree_csi_t *symbol_to_csi(stree_symbol_t *symbol);
