Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
+++ uspace/app/sbi/src/run_expr.c	(revision 71af5a4b8941d5a4dde4b226b1c8d722623f77d8)
@@ -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;
+}
