Index: uspace/app/sbi/src/builtin.c
===================================================================
--- uspace/app/sbi/src/builtin.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/builtin.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -27,5 +27,5 @@
  */
 
-/** @file Builtin functions. */
+/** @file Builtin procedures. */
 
 #include <stdio.h>
@@ -42,7 +42,7 @@
 #include "builtin.h"
 
-static stree_symbol_t *builtin_declare_fun(stree_csi_t *csi, char *name);
-static void builtin_fun_add_arg(stree_symbol_t *fun_sym, char *name);
-static void builtin_fun_add_vararg(stree_symbol_t *fun_sym, char *name);
+static stree_symbol_t *builtin_declare_fun(stree_csi_t *csi, const char *name);
+static void builtin_fun_add_arg(stree_symbol_t *fun_sym, const char *name);
+static void builtin_fun_add_vararg(stree_symbol_t *fun_sym, const char *name);
 
 static void builtin_write_line(run_t *run);
@@ -54,5 +54,5 @@
 /** Declare builtin symbols in the program.
  *
- * Declares symbols that will be hooked to builtin interpreter functions.
+ * Declares symbols that will be hooked to builtin interpreter procedures.
  */
 void builtin_declare(stree_program_t *program)
@@ -80,5 +80,5 @@
 	list_append(&program->module->members, modm);
 
-	/* Declare builtin functions. */
+	/* Declare builtin procedures. */
 
 	bi_write_line = builtin_declare_fun(csi, "WriteLine");
@@ -89,12 +89,12 @@
 }
 
-void builtin_run_fun(run_t *run, stree_symbol_t *fun_sym)
+void builtin_run_proc(run_t *run, stree_symbol_t *proc_sym)
 {
 #ifdef DEBUG_RUN_TRACE
-	printf("Run builtin function.\n");
+	printf("Run builtin procedure.\n");
 #endif
-	if (fun_sym == bi_write_line) {
+	if (proc_sym == bi_write_line) {
 		builtin_write_line(run);
-	} else if (fun_sym == bi_exec) {
+	} else if (proc_sym == bi_exec) {
 		builtin_exec(run);
 	} else {
@@ -104,5 +104,5 @@
 
 /** Declare a builtin function in @a csi. */
-static stree_symbol_t *builtin_declare_fun(stree_csi_t *csi, char *name)
+static stree_symbol_t *builtin_declare_fun(stree_csi_t *csi, const char *name)
 {
 	stree_ident_t *ident;
@@ -133,7 +133,7 @@
 
 /** Add one formal parameter to function. */
-static void builtin_fun_add_arg(stree_symbol_t *fun_sym, char *name)
-{
-	stree_fun_arg_t *fun_arg;
+static void builtin_fun_add_arg(stree_symbol_t *fun_sym, const char *name)
+{
+	stree_proc_arg_t *proc_arg;
 	stree_fun_t *fun;
 
@@ -141,16 +141,16 @@
 	assert(fun != NULL);
 
-	fun_arg = stree_fun_arg_new();
-	fun_arg->name = stree_ident_new();
-	fun_arg->name->sid = strtab_get_sid(name);
-	fun_arg->type = NULL; /* XXX */
-
-	list_append(&fun->args, fun_arg);
+	proc_arg = stree_proc_arg_new();
+	proc_arg->name = stree_ident_new();
+	proc_arg->name->sid = strtab_get_sid(name);
+	proc_arg->type = NULL; /* XXX */
+
+	list_append(&fun->args, proc_arg);
 }
 
 /** Add variadic formal parameter to function. */
-static void builtin_fun_add_vararg(stree_symbol_t *fun_sym, char *name)
-{
-	stree_fun_arg_t *fun_arg;
+static void builtin_fun_add_vararg(stree_symbol_t *fun_sym, const char *name)
+{
+	stree_proc_arg_t *proc_arg;
 	stree_fun_t *fun;
 
@@ -158,10 +158,10 @@
 	assert(fun != NULL);
 
-	fun_arg = stree_fun_arg_new();
-	fun_arg->name = stree_ident_new();
-	fun_arg->name->sid = strtab_get_sid(name);
-	fun_arg->type = NULL; /* XXX */
-
-	fun->varg = fun_arg;
+	proc_arg = stree_proc_arg_new();
+	proc_arg->name = stree_ident_new();
+	proc_arg->name->sid = strtab_get_sid(name);
+	proc_arg->type = NULL; /* XXX */
+
+	fun->varg = proc_arg;
 }
 
Index: uspace/app/sbi/src/builtin.h
===================================================================
--- uspace/app/sbi/src/builtin.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/builtin.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -33,5 +33,5 @@
 
 void builtin_declare(stree_program_t *program);
-void builtin_run_fun(run_t *run, stree_symbol_t *fun_sym);
+void builtin_run_proc(run_t *run, stree_symbol_t *proc_sym);
 
 #endif
Index: uspace/app/sbi/src/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/os/helenos.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -75,4 +75,27 @@
 }
 
+/** Get character from string at the given index. */
+int os_str_get_char(const char *str, int index, int *out_char)
+{
+	size_t offset;
+	int i;
+	wchar_t c;
+
+	if (index < 0)
+		return EINVAL;
+
+	offset = 0;
+	for (i = 0; i <= index; ++i) {
+		c = str_decode(str, &offset, STR_NO_LIMIT);
+		if (c == '\0')
+			return EINVAL;
+		if (c == U_SPECIAL)
+			return EIO;
+	}
+
+	*out_char = (int) c;
+	return EOK;
+}
+
 /** Simple command execution. */
 int os_exec(char *const cmd[])
Index: uspace/app/sbi/src/os/os.h
===================================================================
--- uspace/app/sbi/src/os/os.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/os/os.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -33,4 +33,5 @@
 int os_str_cmp(const char *a, const char *b);
 char *os_str_dup(const char *str);
+int os_str_get_char(const char *str, int index, int *out_char);
 int os_exec(char *const cmd[]);
 
Index: uspace/app/sbi/src/os/posix.c
===================================================================
--- uspace/app/sbi/src/os/posix.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/os/posix.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -79,4 +79,17 @@
 }
 
+/** Get character from string at the given index. */
+int os_str_get_char(const char *str, int index, int *out_char)
+{
+	size_t len;
+
+	len = strlen(str);
+	if (index < 0 || (size_t) index >= len)
+		return EINVAL;
+
+	*out_char = str[index];
+	return EOK;
+}
+
 /** Simple command execution. */
 int os_exec(char *const cmd[])
Index: uspace/app/sbi/src/parse.c
===================================================================
--- uspace/app/sbi/src/parse.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/parse.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -55,5 +55,5 @@
 static stree_prop_t *parse_prop(parse_t *parse);
 
-static stree_fun_arg_t *parse_fun_arg(parse_t *parse);
+static stree_proc_arg_t *parse_proc_arg(parse_t *parse);
 static stree_arg_attr_t *parse_arg_attr(parse_t *parse);
 
@@ -227,5 +227,5 @@
 {
 	stree_fun_t *fun;
-	stree_fun_arg_t *arg;
+	stree_proc_arg_t *arg;
 
 	fun = stree_fun_new();
@@ -241,5 +241,5 @@
 		/* Parse formal parameters. */
 		while (b_true) {
-			arg = parse_fun_arg(parse);
+			arg = parse_proc_arg(parse);
 			if (stree_arg_has_attr(arg, aac_packed)) {
 				fun->varg = arg;
@@ -292,12 +292,77 @@
 {
 	stree_prop_t *prop;
+	stree_ident_t *ident;
+	stree_proc_arg_t *arg;
 
 	prop = stree_prop_new();
+	list_init(&prop->args);
 
 	lmatch(parse, lc_prop);
-	prop->name = parse_ident(parse);
+
+	if (lcur_lc(parse) == lc_self) {
+		/* Indexed property set */
+
+		/* Use some name that is impossible as identifier. */
+		ident = stree_ident_new();
+		ident->sid = strtab_get_sid(INDEXER_IDENT);
+		prop->name = ident;
+
+		lskip(parse);
+		lmatch(parse, lc_lsbr);
+
+		/* Parse formal parameters. */
+		while (b_true) {
+			arg = parse_proc_arg(parse);
+			if (stree_arg_has_attr(arg, aac_packed)) {
+				prop->varg = arg;
+				break;
+			} else {
+				list_append(&prop->args, arg);
+			}
+
+			if (lcur_lc(parse) == lc_rsbr)
+				break;
+
+			lmatch(parse, lc_scolon);
+		}
+
+		lmatch(parse, lc_rsbr);
+	} else {
+		/* Named property */
+		prop->name = parse_ident(parse);
+	}
+
 	lmatch(parse, lc_colon);
 	prop->type = parse_texpr(parse);
 	lmatch(parse, lc_is);
+
+	while (lcur_lc(parse) != lc_end) {
+		switch (lcur_lc(parse)) {
+		case lc_get:
+			lskip(parse);
+			lmatch(parse, lc_is);
+			if (prop->getter_body != NULL) {
+				printf("Error: Duplicate getter.\n");
+				exit(1);
+			}
+			prop->getter_body = parse_block(parse);
+			lmatch(parse, lc_end);
+			break;
+		case lc_set:
+			lskip(parse);
+			prop->setter_arg_name = parse_ident(parse);
+			lmatch(parse, lc_is);
+			if (prop->setter_body != NULL) {
+				printf("Error: Duplicate setter.\n");
+				exit(1);
+			}
+			prop->setter_body = parse_block(parse);
+			lmatch(parse, lc_end);
+			break;
+		default:
+			lunexpected_error(parse);
+		}
+	}
+
 	lmatch(parse, lc_end);
 
@@ -306,10 +371,10 @@
 
 /** Parse formal function argument. */
-static stree_fun_arg_t *parse_fun_arg(parse_t *parse)
-{
-	stree_fun_arg_t *arg;
+static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
+{
+	stree_proc_arg_t *arg;
 	stree_arg_attr_t *attr;
 
-	arg = stree_fun_arg_new();
+	arg = stree_proc_arg_new();
 	arg->name = parse_ident(parse);
 	lmatch(parse, lc_colon);
Index: uspace/app/sbi/src/rdata.c
===================================================================
--- uspace/app/sbi/src/rdata.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/rdata.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -64,5 +64,58 @@
 }
 
-rdata_address_t *rdata_address_new(void)
+rdata_addr_var_t *rdata_addr_var_new(void)
+{
+	rdata_addr_var_t *addr_var;
+
+	addr_var = calloc(1, sizeof(rdata_addr_var_t));
+	if (addr_var == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return addr_var;
+}
+
+rdata_aprop_named_t *rdata_aprop_named_new(void)
+{
+	rdata_aprop_named_t *aprop_named;
+
+	aprop_named = calloc(1, sizeof(rdata_aprop_named_t));
+	if (aprop_named == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return aprop_named;
+}
+
+rdata_aprop_indexed_t *rdata_aprop_indexed_new(void)
+{
+	rdata_aprop_indexed_t *aprop_indexed;
+
+	aprop_indexed = calloc(1, sizeof(rdata_aprop_indexed_t));
+	if (aprop_indexed == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return aprop_indexed;
+}
+
+rdata_addr_prop_t *rdata_addr_prop_new(aprop_class_t apc)
+{
+	rdata_addr_prop_t *addr_prop;
+
+	addr_prop = calloc(1, sizeof(rdata_addr_prop_t));
+	if (addr_prop == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	addr_prop->apc = apc;
+	return addr_prop;
+}
+
+rdata_address_t *rdata_address_new(address_class_t ac)
 {
 	rdata_address_t *address;
@@ -74,4 +127,5 @@
 	}
 
+	address->ac = ac;
 	return address;
 }
@@ -349,105 +403,15 @@
 }
 
-/** 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.
+/** Read data from a variable.
+ *
+ * Return value stored in variable @a var.
  */
-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)
+void rdata_var_read(rdata_var_t *var, 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);
+	/* Perform a shallow copy of @a var. */
+	rdata_var_copy(var, &rvar);
 
 	value = rdata_value_new();
@@ -455,13 +419,4 @@
 	*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_write(address->vref, value);
 }
 
@@ -492,4 +447,37 @@
 }
 
+/** Get item var-class.
+ *
+ * Get var-class of @a item, regardless whether it is a value or address.
+ * (I.e. the var class of the value or variable at the given address).
+ */
+var_class_t rdata_item_get_vc(rdata_item_t *item)
+{
+	var_class_t vc;
+
+	switch (item->ic) {
+	case ic_value:
+		vc = item->u.value->var->vc;
+		break;
+	case ic_address:
+		switch (item->u.address->ac) {
+		case ac_var:
+			vc = item->u.address->u.var_a->vref->vc;
+			break;
+		case ac_prop:
+			printf("Unimplemented: Get property address "
+			    "varclass.\n");
+			exit(1);
+		default:
+			assert(b_false);
+		}
+		break;
+	default:
+		assert(b_false);
+	}
+
+	return vc;
+}
+
 /** Determine if CSI @a a is derived from CSI described by type item @a tb. */
 bool_t rdata_is_csi_derived_from_ti(stree_csi_t *a, rdata_titem_t *tb)
@@ -530,5 +518,12 @@
 static void rdata_address_print(rdata_address_t *address)
 {
-	rdata_var_print(address->vref);
+	switch (address->ac) {
+	case ac_var:
+		rdata_var_print(address->u.var_a->vref);
+		break;
+	case ac_prop:
+		printf("Warning: Unimplemented: Print property address.\n");
+		break;
+	}
 }
 
Index: uspace/app/sbi/src/rdata.h
===================================================================
--- uspace/app/sbi/src/rdata.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/rdata.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -33,6 +33,11 @@
 
 rdata_item_t *rdata_item_new(item_class_t ic);
-rdata_address_t *rdata_address_new(void);
+rdata_addr_var_t *rdata_addr_var_new(void);
+rdata_aprop_named_t *rdata_aprop_named_new(void);
+rdata_aprop_indexed_t *rdata_aprop_indexed_new(void);
+rdata_addr_prop_t *rdata_addr_prop_new(aprop_class_t apc);
+rdata_address_t *rdata_address_new(address_class_t ac);
 rdata_value_t *rdata_value_new(void);
+
 rdata_var_t *rdata_var_new(var_class_t vc);
 rdata_ref_t *rdata_ref_new(void);
@@ -51,11 +56,8 @@
 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_var_read(rdata_var_t *var, rdata_item_t **ritem);
 void rdata_var_write(rdata_var_t *var, rdata_value_t *value);
 
+var_class_t rdata_item_get_vc(rdata_item_t *item);
 bool_t rdata_is_csi_derived_from_ti(stree_csi_t *a, rdata_titem_t *tb);
 
Index: uspace/app/sbi/src/rdata_t.h
===================================================================
--- uspace/app/sbi/src/rdata_t.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/rdata_t.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -131,8 +131,75 @@
 } rdata_var_t;
 
-/** Address item. */
-typedef struct rdata_address {
+/** Address class */
+typedef enum {
+	/** Variable address */
+	ac_var,
+
+	/** Property address */
+	ac_prop
+} address_class_t;
+
+/** Variable address */
+typedef struct {
 	/** Targeted variable */
 	rdata_var_t *vref;
+} rdata_addr_var_t;
+
+/** Named property address */
+typedef struct {
+	/** Delegate to the property */
+	rdata_deleg_t *prop_d;
+} rdata_aprop_named_t;
+
+/** Indexed property address */
+typedef struct {
+	/** Delegate to the object (or CSI) which is being indexed. */
+	rdata_deleg_t *object_d;
+
+	/** Arguments (indices) */
+	list_t args; /* of rdata_item_t */
+} rdata_aprop_indexed_t;
+
+typedef enum {
+	/* Named property address */
+	apc_named,
+
+	/* Indexed property address */
+	apc_indexed
+} aprop_class_t;
+
+/** Property address.
+ *
+ * When accessing part of a property that is non-scalar and mutable,
+ * a read-modify-write (or get-modify-set) operation is necessary.
+ * To accomodate this, the address item must hold a temporary copy of the
+ * property value.
+ */
+typedef struct {
+	aprop_class_t apc;
+
+	/** Temporary copy of property value or @c NULL when not used. */
+	struct rdata_value *tvalue;
+
+	/**
+	 * Points to the specific var node within @c tvalue that is addressed
+	 * or @c NULL when @c tvalue is not used.
+	 */
+	rdata_var_t *tpos;
+
+	union {
+		rdata_aprop_named_t *named;
+		rdata_aprop_indexed_t *indexed;
+	} u;
+} rdata_addr_prop_t;
+
+/** Address item */
+typedef struct rdata_address {
+	address_class_t ac;
+
+	union {
+		rdata_addr_var_t *var_a;
+		rdata_addr_prop_t *prop_a;
+	} u;
 } rdata_address_t;
 
Index: uspace/app/sbi/src/run.c
===================================================================
--- uspace/app/sbi/src/run.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/run.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -58,4 +58,9 @@
 static bool_t run_exc_match(run_t *run, stree_except_t *except_c);
 
+static void run_aprop_read(run_t *run, rdata_addr_prop_t *addr_prop,
+    rdata_item_t **ritem);
+static void run_aprop_write(run_t *run, rdata_addr_prop_t *addr_prop,
+    rdata_value_t *value);
+
 /** Initialize runner instance. */
 void run_init(run_t *run)
@@ -71,5 +76,5 @@
 	stree_ident_t *fake_ident;
 	list_t main_args;
-	run_fun_ar_t *fun_ar;
+	run_proc_ar_t *proc_ar;
 	rdata_item_t *res;
 
@@ -79,5 +84,5 @@
 	/* Initialize thread activation record. */
 	run->thread_ar = run_thread_ar_new();
-	list_init(&run->thread_ar->fun_ar);
+	list_init(&run->thread_ar->proc_ar);
 	run->thread_ar->bo_mode = bm_none;
 
@@ -103,7 +108,7 @@
 	/* Run function @c main. */
 	list_init(&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_proc_ar_create(run, NULL, main_fun_sym, main_fun->body, &proc_ar);
+	run_proc_ar_set_args(run, proc_ar, &main_args);
+	run_proc(run, proc_ar, &res);
 
 	/* Check for unhandled exceptions. */
@@ -115,28 +120,25 @@
 }
 
-/** Run member function */
-void run_fun(run_t *run, run_fun_ar_t *fun_ar, rdata_item_t **res)
-{
-	stree_symbol_t *fun_sym;
-	stree_fun_t *fun;
+/** Run procedure. */
+void run_proc(run_t *run, run_proc_ar_t *proc_ar, rdata_item_t **res)
+{
+	stree_symbol_t *proc_sym;
 	list_node_t *node;
 
-	fun_sym = fun_ar->fun_sym;
-	fun = symbol_to_fun(fun_sym);
-	assert(fun != NULL);
+	proc_sym = proc_ar->proc_sym;
 
 #ifdef DEBUG_RUN_TRACE
 	printf("Start executing function '");
-	symbol_print_fqn(run->program, fun_sym);
+	symbol_print_fqn(run->program, proc_sym);
 	printf("'.\n");
 #endif
-	/* Add function AR to the stack. */
-	list_append(&run->thread_ar->fun_ar, fun_ar);
-
-	/* Run main function block. */
-	if (fun->body != NULL) {
-		run_block(run, fun->body);
+	/* Add procedure AR to the stack. */
+	list_append(&run->thread_ar->proc_ar, proc_ar);
+
+	/* Run main procedure block. */
+	if (proc_ar->proc_block != NULL) {
+		run_block(run, proc_ar->proc_block);
 	} else {
-		builtin_run_fun(run, fun_sym);
+		builtin_run_proc(run, proc_sym);
 	}
 
@@ -146,5 +148,5 @@
 		printf("Error: Misplaced 'break' statement.\n");
 		exit(1);
-	case bm_fun:
+	case bm_proc:
 		run->thread_ar->bo_mode = bm_none;
 		break;
@@ -154,16 +156,18 @@
 
 #ifdef DEBUG_RUN_TRACE
-	printf("Done executing function '");
-	symbol_print_fqn(run->program, fun_sym);
+	printf("Done executing procedure '");
+	symbol_print_fqn(run->program, proc_sym);
 	printf("'.\n");
 
 	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;
+	/* Remove procedure activation record from the stack. */
+	node = list_last(&run->thread_ar->proc_ar);
+	assert(list_node_data(node, run_proc_ar_t *) == proc_ar);
+	list_remove(&run->thread_ar->proc_ar, node);
+
+	/* Procedure should not return an address. */
+	assert(proc_ar->retval == NULL || proc_ar->retval->ic == ic_value);
+	*res = proc_ar->retval;
 }
 
@@ -171,5 +175,5 @@
 static void run_block(run_t *run, stree_block_t *block)
 {
-	run_fun_ar_t *fun_ar;
+	run_proc_ar_t *proc_ar;
 	run_block_ar_t *block_ar;
 	list_node_t *node;
@@ -185,6 +189,6 @@
 
 	/* Add block activation record to the stack. */
-	fun_ar = run_get_current_fun_ar(run);
-	list_append(&fun_ar->block_ar, block_ar);
+	proc_ar = run_get_current_proc_ar(run);
+	list_append(&proc_ar->block_ar, block_ar);
 
 	node = list_first(&block->stats);
@@ -204,7 +208,7 @@
 
 	/* Remove block activation record from the stack. */
-	node = list_last(&fun_ar->block_ar);
+	node = list_last(&proc_ar->block_ar);
 	assert(list_node_data(node, run_block_ar_t *) == block_ar);
-	list_remove(&fun_ar->block_ar, node);
+	list_remove(&proc_ar->block_ar, node);
 }
 
@@ -357,5 +361,5 @@
 #endif
 	run_expr(run, raise_s->expr, &rexpr);
-	rdata_cvt_value_item(rexpr, &rexpr_vi);
+	run_cvt_value_item(run, rexpr, &rexpr_vi);
 
 	/* Store expression result in thread AR. */
@@ -370,5 +374,6 @@
 {
 	rdata_item_t *rexpr;
-	run_fun_ar_t *fun_ar;
+	rdata_item_t *rexpr_vi;
+	run_proc_ar_t *proc_ar;
 
 #ifdef DEBUG_RUN_TRACE
@@ -376,12 +381,13 @@
 #endif
 	run_expr(run, return_s->expr, &rexpr);
+	run_cvt_value_item(run, rexpr, &rexpr_vi);
 
 	/* 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. */
+	proc_ar = run_get_current_proc_ar(run);
+	proc_ar->retval = rexpr_vi;
+
+	/* Force control to ascend and leave the procedure. */
 	if (run->thread_ar->bo_mode == bm_none)
-		run->thread_ar->bo_mode = bm_fun;
+		run->thread_ar->bo_mode = bm_proc;
 }
 
@@ -501,11 +507,11 @@
 rdata_var_t *run_local_vars_lookup(run_t *run, sid_t name)
 {
-	run_fun_ar_t *fun_ar;
+	run_proc_ar_t *proc_ar;
 	run_block_ar_t *block_ar;
 	rdata_var_t *var;
 	list_node_t *node;
 
-	fun_ar = run_get_current_fun_ar(run);
-	node = list_last(&fun_ar->block_ar);
+	proc_ar = run_get_current_proc_ar(run);
+	node = list_last(&proc_ar->block_ar);
 
 	/* Walk through all block activation records. */
@@ -516,5 +522,5 @@
 			return var;
 
-		node = list_prev(&fun_ar->block_ar, node);
+		node = list_prev(&proc_ar->block_ar, node);
 	}
 
@@ -524,10 +530,10 @@
 
 /** Get current function activation record. */
-run_fun_ar_t *run_get_current_fun_ar(run_t *run)
+run_proc_ar_t *run_get_current_proc_ar(run_t *run)
 {
 	list_node_t *node;
 
-	node = list_last(&run->thread_ar->fun_ar);
-	return list_node_data(node, run_fun_ar_t *);
+	node = list_last(&run->thread_ar->proc_ar);
+	return list_node_data(node, run_proc_ar_t *);
 }
 
@@ -535,10 +541,10 @@
 run_block_ar_t *run_get_current_block_ar(run_t *run)
 {
-	run_fun_ar_t *fun_ar;
+	run_proc_ar_t *proc_ar;
 	list_node_t *node;
 
-	fun_ar = run_get_current_fun_ar(run);
-
-	node = list_last(&fun_ar->block_ar);
+	proc_ar = run_get_current_proc_ar(run);
+
+	node = list_last(&proc_ar->block_ar);
 	return list_node_data(node, run_block_ar_t *);
 }
@@ -547,8 +553,8 @@
 stree_csi_t *run_get_current_csi(run_t *run)
 {
-	run_fun_ar_t *fun_ar;
-
-	fun_ar = run_get_current_fun_ar(run);
-	return fun_ar->fun_sym->outer_csi;
+	run_proc_ar_t *proc_ar;
+
+	proc_ar = run_get_current_proc_ar(run);
+	return proc_ar->proc_sym->outer_csi;
 }
 
@@ -600,31 +606,47 @@
 
 /** 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_proc_ar_create(run_t *run, rdata_var_t *obj, stree_symbol_t *proc_sym,
+    stree_block_t *proc_block, run_proc_ar_t **rproc_ar)
+{
+	run_proc_ar_t *proc_ar;
+	run_block_ar_t *block_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)
+	proc_ar = run_proc_ar_new();
+	proc_ar->obj = obj;
+	proc_ar->proc_sym = proc_sym;
+	proc_ar->proc_block = proc_block;
+	list_init(&proc_ar->block_ar);
+
+	proc_ar->retval = NULL;
+
+	/* Create special block activation record to hold function arguments. */
+	block_ar = run_block_ar_new();
+	intmap_init(&block_ar->vars);
+	list_append(&proc_ar->block_ar, block_ar);
+
+	*rproc_ar = proc_ar;
+}
+
+/** Fill arguments in a procedure AR.
+ *
+ * When invoking a procedure this is used to store the argument values
+ * in the activation record.
+ */
+void run_proc_ar_set_args(run_t *run, run_proc_ar_t *proc_ar, list_t *arg_vals)
 {
 	stree_fun_t *fun;
+	stree_prop_t *prop;
+	list_t *args;
+	stree_proc_arg_t *varg;
+
 	run_block_ar_t *block_ar;
-	list_node_t *rarg_n, *farg_n;
+	list_node_t *block_ar_n;
+	list_node_t *rarg_n, *parg_n;
 	list_node_t *cn;
 	rdata_item_t *rarg;
-	stree_fun_arg_t *farg;
+	stree_proc_arg_t *parg;
 	rdata_var_t *var;
 	rdata_var_t *ref_var;
@@ -633,24 +655,39 @@
 	int n_vargs, idx;
 
-	/* 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);
+	/* AR should have been created with run_proc_ar_create(). */
+	assert(proc_ar->proc_sym != NULL);
+
+	/*
+	 * The procedure being activated should be a member function or
+	 * property getter/setter.
+	 */
+	switch (proc_ar->proc_sym->sc) {
+	case sc_fun:
+		fun = symbol_to_fun(proc_ar->proc_sym);
+		args = &fun->args;
+		varg = fun->varg;
+		break;
+	case sc_prop:
+		prop = symbol_to_prop(proc_ar->proc_sym);
+		args = &prop->args;
+		varg = prop->varg;
+		break;
+	default:
+		assert(b_false);
+	}
+
+	/* Fetch first block activation record. */
+	block_ar_n = list_first(&proc_ar->block_ar);
+	assert(block_ar_n != NULL);
+	block_ar = list_node_data(block_ar_n, run_block_ar_t *);
 
 	/* Declare local variables to hold argument values. */
-	rarg_n = list_first(args);
-	farg_n = list_first(&fun->args);
-
-	while (farg_n != NULL) {
+	rarg_n = list_first(arg_vals);
+	parg_n = list_first(args);
+
+	while (parg_n != NULL) {
 		if (rarg_n == NULL) {
 			printf("Error: Too few arguments to function '");
-			symbol_print_fqn(run->program, fun_ar->fun_sym);
+			symbol_print_fqn(run->program, proc_ar->proc_sym);
 			printf("'.\n");
 			exit(1);
@@ -658,5 +695,5 @@
 
 		rarg = list_node_data(rarg_n, rdata_item_t *);
-		farg = list_node_data(farg_n, stree_fun_arg_t *);
+		parg = list_node_data(parg_n, stree_proc_arg_t *);
 
 		assert(rarg->ic == ic_value);
@@ -666,11 +703,11 @@
 
 		/* 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);
-	}
-
-	if (fun->varg != NULL) {
+		intmap_set(&block_ar->vars, parg->name->sid, var);
+
+		rarg_n = list_next(arg_vals, rarg_n);
+		parg_n = list_next(args, parg_n);
+	}
+
+	if (varg != NULL) {
 		/* Function is variadic. Count number of variadic arguments. */
 		cn = rarg_n;
@@ -678,5 +715,5 @@
 		while (cn != NULL) {
 			n_vargs += 1;
-			cn = list_next(args, cn);
+			cn = list_next(arg_vals, cn);
 		}
 
@@ -695,5 +732,5 @@
 			rdata_var_write(array->element[idx], rarg->u.value);
 
-			rarg_n = list_next(args, rarg_n);
+			rarg_n = list_next(arg_vals, rarg_n);
 			idx += 1;
 		}
@@ -709,5 +746,5 @@
 
 		/* Declare variable using name of formal argument. */
-		intmap_set(&block_ar->vars, fun->varg->name->sid,
+		intmap_set(&block_ar->vars, varg->name->sid,
 		    ref_var);
 	}
@@ -716,8 +753,44 @@
 	if (rarg_n != NULL) {
 		printf("Error: Too many arguments to function '");
-		symbol_print_fqn(run->program, fun_ar->fun_sym);
+		symbol_print_fqn(run->program, proc_ar->proc_sym);
 		printf("'.\n");
 		exit(1);
 	}
+}
+
+/** Fill setter argument in a procedure AR.
+ *
+ * When invoking a setter this is used to store its argument value in its
+ * procedure activation record.
+ */
+void run_proc_ar_set_setter_arg(run_t *run, run_proc_ar_t *proc_ar,
+    rdata_item_t *arg_val)
+{
+	stree_prop_t *prop;
+	run_block_ar_t *block_ar;
+	list_node_t *block_ar_n;
+	rdata_var_t *var;
+
+	(void) run;
+
+	/* AR should have been created with run_proc_ar_create(). */
+	assert(proc_ar->proc_sym != NULL);
+
+	/* The procedure being activated should be a property setter. */
+	prop = symbol_to_prop(proc_ar->proc_sym);
+	assert(prop != NULL);
+
+	/* Fetch first block activation record. */
+	block_ar_n = list_first(&proc_ar->block_ar);
+	assert(block_ar_n != NULL);
+	block_ar = list_node_data(block_ar_n, run_block_ar_t *);
+
+	assert(arg_val->ic == ic_value);
+
+	/* Construct a variable from the argument value. */
+	run_value_item_to_var(arg_val, &var);
+
+	/* Declare variable using name of formal argument. */
+	intmap_set(&block_ar->vars, prop->setter_arg_name->sid, var);
 }
 
@@ -726,17 +799,273 @@
 {
 	list_node_t *node;
-	run_fun_ar_t *fun_ar;
+	run_proc_ar_t *proc_ar;
 
 	printf("Backtrace:\n");
-	node = list_last(&run->thread_ar->fun_ar);
+	node = list_last(&run->thread_ar->proc_ar);
 	while (node != NULL) {
 		printf(" * ");
-		fun_ar = list_node_data(node, run_fun_ar_t *);
-		symbol_print_fqn(run->program, fun_ar->fun_sym);
+		proc_ar = list_node_data(node, run_proc_ar_t *);
+		symbol_print_fqn(run->program, proc_ar->proc_sym);
 		printf("\n");
 
-		node = list_prev(&run->thread_ar->fun_ar, node);
-	}
-}
+		node = list_prev(&run->thread_ar->proc_ar, node);
+	}
+}
+
+/** 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;
+
+	/* 
+	 * 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) {
+		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.
+ */
+void run_address_read(run_t *run, rdata_address_t *address,
+    rdata_item_t **ritem)
+{
+	(void) run;
+
+	switch (address->ac) {
+	case ac_var:
+		rdata_var_read(address->u.var_a->vref, ritem);
+		break;
+	case ac_prop:
+		run_aprop_read(run, address->u.prop_a, ritem);
+		break;
+	}
+
+	assert((*ritem)->ic == ic_value);
+}
+
+/** Write data to an address.
+ *
+ * Store @a value to the variable at @a address.
+ */
+void run_address_write(run_t *run, rdata_address_t *address,
+    rdata_value_t *value)
+{
+	(void) run;
+
+	switch (address->ac) {
+	case ac_var:
+		rdata_var_write(address->u.var_a->vref, value);
+		break;
+	case ac_prop:
+		run_aprop_write(run, address->u.prop_a, value);
+		break;
+	}
+}
+
+static void run_aprop_read(run_t *run, rdata_addr_prop_t *addr_prop,
+    rdata_item_t **ritem)
+{
+	rdata_deleg_t *deleg;
+	rdata_var_t *obj;
+	stree_symbol_t *prop_sym;
+	stree_prop_t *prop;
+
+	run_proc_ar_t *proc_ar;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Read from property.\n");
+#endif
+	/*
+	 * If @c tvalue is present, we need to use the relevant part from that
+	 * instead of re-reading the whole thing.
+	 */
+	if (addr_prop->tvalue != NULL) {
+		printf("Unimplemented: Property field access.\n");
+		exit(1);
+	}
+
+	if (addr_prop->apc == apc_named)
+		deleg = addr_prop->u.named->prop_d;
+	else
+		deleg = addr_prop->u.indexed->object_d;
+
+	obj = deleg->obj;
+	prop_sym = deleg->sym;
+	prop = symbol_to_prop(prop_sym);
+	assert(prop != NULL);
+
+	if (prop->getter_body == NULL) {
+		printf("Error: Property is not readable.\n");
+		exit(1);
+	}
+
+	/* Create procedure activation record. */
+	run_proc_ar_create(run, obj, prop_sym, prop->getter_body, &proc_ar);
+
+	/* Fill in arguments (indices). */
+	if (addr_prop->apc == apc_indexed) {
+		run_proc_ar_set_args(run, proc_ar,
+		    &addr_prop->u.indexed->args);
+	}
+
+	/* Run getter. */
+	run_proc(run, proc_ar, ritem);
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Getter returns ");
+	rdata_item_print(*ritem);
+	printf(".\n");
+	printf("Done reading from property.\n");
+#endif
+}
+
+static void run_aprop_write(run_t *run, rdata_addr_prop_t *addr_prop,
+    rdata_value_t *value)
+{
+	rdata_deleg_t *deleg;
+	rdata_var_t *obj;
+	stree_symbol_t *prop_sym;
+	stree_prop_t *prop;
+
+	run_proc_ar_t *proc_ar;
+	rdata_item_t *vitem;
+	rdata_item_t *ritem;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Write to property.\n");
+#endif
+	/* If @c tvalue is present, we need to modify it and write it back. */
+	if (addr_prop->tvalue != NULL) {
+		printf("Unimplemented: Read-modify-write property access.\n");
+		exit(1);
+	}
+
+	if (addr_prop->apc == apc_named)
+		deleg = addr_prop->u.named->prop_d;
+	else
+		deleg = addr_prop->u.indexed->object_d;
+
+	obj = deleg->obj;
+	prop_sym = deleg->sym;
+	prop = symbol_to_prop(prop_sym);
+	assert(prop != NULL);
+
+	if (prop->setter_body == NULL) {
+		printf("Error: Property is not writable.\n");
+		exit(1);
+	}
+
+	vitem = rdata_item_new(ic_value);
+	vitem->u.value = value;
+
+	/* Create procedure activation record. */
+	run_proc_ar_create(run, obj, prop_sym, prop->setter_body, &proc_ar);
+
+	/* Fill in arguments (indices). */
+	if (addr_prop->apc == apc_indexed) {
+		run_proc_ar_set_args(run, proc_ar,
+		    &addr_prop->u.indexed->args);
+	}
+
+	/* Fill in value argument for setter. */
+	run_proc_ar_set_setter_arg(run, proc_ar, vitem);
+
+	/* Run setter. */
+	run_proc(run, proc_ar, &ritem);
+
+	/* Setter should not return a value. */
+	assert(ritem == NULL);
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Done writing to property.\n");
+#endif
+}
+
+/** Return reference to a variable.
+ *
+ * Constructs a reference (value item) pointing to @a var.
+ */
+void run_reference(run_t *run, 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;
+
+	(void) run;
+
+	/* 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 run_dereference(run_t *run, rdata_item_t *ref, rdata_item_t **ritem)
+{
+	rdata_item_t *ref_val;
+	rdata_item_t *item;
+	rdata_address_t *address;
+	rdata_addr_var_t *addr_var;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("run_dereference()\n");
+#endif
+	run_cvt_value_item(run, ref, &ref_val);
+	assert(ref_val->u.value->var->vc == vc_ref);
+
+	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 = ref_val->u.value->var->u.ref_v->vref;
+
+	if (addr_var->vref == NULL) {
+		printf("Error: Accessing null reference.\n");
+		exit(1);
+	}
+
+#ifdef DEBUG_RUN_TRACE
+	printf("vref set to %p\n", addr_var->vref);
+#endif
+	*ritem = item;
+}
+
 
 run_thread_ar_t *run_thread_ar_new(void)
@@ -753,15 +1082,15 @@
 }
 
-run_fun_ar_t *run_fun_ar_new(void)
-{
-	run_fun_ar_t *fun_ar;
-
-	fun_ar = calloc(1, sizeof(run_fun_ar_t));
-	if (fun_ar == NULL) {
+run_proc_ar_t *run_proc_ar_new(void)
+{
+	run_proc_ar_t *proc_ar;
+
+	proc_ar = calloc(1, sizeof(run_proc_ar_t));
+	if (proc_ar == NULL) {
 		printf("Memory allocation failed.\n");
 		exit(1);
 	}
 
-	return fun_ar;
+	return proc_ar;
 }
 
Index: uspace/app/sbi/src/run.h
===================================================================
--- uspace/app/sbi/src/run.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/run.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -34,20 +34,31 @@
 void run_init(run_t *run);
 void run_program(run_t *run, stree_program_t *prog);
-void run_fun(run_t *run, run_fun_ar_t *fun_ar, rdata_item_t **res);
+void run_proc(run_t *run, run_proc_ar_t *proc_ar, rdata_item_t **res);
 
 void run_print_fun_bt(run_t *run);
 
 rdata_var_t *run_local_vars_lookup(run_t *run, sid_t name);
-run_fun_ar_t *run_get_current_fun_ar(run_t *run);
+run_proc_ar_t *run_get_current_proc_ar(run_t *run);
 run_block_ar_t *run_get_current_block_ar(run_t *run);
 stree_csi_t *run_get_current_csi(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);
+void run_proc_ar_set_args(run_t *run, run_proc_ar_t *proc_ar,
+    list_t *arg_vals);
+void run_proc_ar_set_setter_arg(run_t *run, run_proc_ar_t *proc_ar,
+    rdata_item_t *arg_val);
+void run_proc_ar_create(run_t *run, rdata_var_t *obj, stree_symbol_t *proc_sym,
+    stree_block_t *proc_block, run_proc_ar_t **rproc_ar);
+
+void run_cvt_value_item(run_t *run, rdata_item_t *item, rdata_item_t **ritem);
+void run_address_read(run_t *run, rdata_address_t *address,
+    rdata_item_t **ritem);
+void run_address_write(run_t *run, rdata_address_t *address,
+    rdata_value_t *value);
+void run_reference(run_t *run, rdata_var_t *var, rdata_item_t **res);
+void run_dereference(run_t *run, rdata_item_t *ref, rdata_item_t **ritem);
 
 run_thread_ar_t *run_thread_ar_new(void);
-run_fun_ar_t *run_fun_ar_new(void);
+run_proc_ar_t *run_proc_ar_new(void);
 run_block_ar_t *run_block_ar_new(void);
 
Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/run_expr.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -41,4 +41,5 @@
 #include "run_texpr.h"
 #include "symbol.h"
+#include "stree.h"
 #include "strtab.h"
 
@@ -87,4 +88,10 @@
 static void run_call(run_t *run, stree_call_t *call, rdata_item_t **res);
 static void run_index(run_t *run, stree_index_t *index, rdata_item_t **res);
+static void run_index_array(run_t *run, stree_index_t *index,
+    rdata_item_t *base, list_t *args, rdata_item_t **res);
+static void run_index_object(run_t *run, stree_index_t *index,
+    rdata_item_t *base, list_t *args, rdata_item_t **res);
+static void run_index_string(run_t *run, stree_index_t *index,
+    rdata_item_t *base, list_t *args, rdata_item_t **res);
 static void run_assign(run_t *run, stree_assign_t *assign, rdata_item_t **res);
 
@@ -143,9 +150,10 @@
 	rdata_item_t *item;
 	rdata_address_t *address;
+	rdata_addr_var_t *addr_var;
 	rdata_value_t *value;
 	rdata_var_t *var;
 	rdata_deleg_t *deleg_v;
 
-	run_fun_ar_t *fun_ar;
+	run_proc_ar_t *proc_ar;
 	stree_symbol_t *csi_sym;
 	stree_csi_t *csi;
@@ -164,8 +172,10 @@
 		/* Found a local variable. */
 		item = rdata_item_new(ic_address);
-		address = rdata_address_new();
+		address = rdata_address_new(ac_var);
+		addr_var = rdata_addr_var_new();
 
 		item->u.address = address;
-		address->vref = var;
+		address->u.var_a = addr_var;
+		addr_var->vref = var;
 
 		*res = item;
@@ -181,13 +191,13 @@
 
 	/* 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;
+	proc_ar = run_get_current_proc_ar(run);
+	if (proc_ar->obj != NULL) {
+		assert(proc_ar->obj->vc == vc_object);
+		obj = proc_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;
+		csi = proc_ar->proc_sym->outer_csi;
 		obj = NULL;
 	}
@@ -238,5 +248,5 @@
 		var->u.deleg_v = deleg_v;
 
-		deleg_v->obj = fun_ar->obj;
+		deleg_v->obj = proc_ar->obj;
 		deleg_v->sym = sym;
 
@@ -270,8 +280,10 @@
 		/* Return address of the variable. */
 		item = rdata_item_new(ic_address);
-		address = rdata_address_new();
+		address = rdata_address_new(ac_var);
+		addr_var = rdata_addr_var_new();
 
 		item->u.address = address;
-		address->vref = member_var;
+		address->u.var_a = addr_var;
+		addr_var->vref = member_var;
 
 		*res = item;
@@ -393,5 +405,5 @@
     rdata_item_t **res)
 {
-	run_fun_ar_t *fun_ar;
+	run_proc_ar_t *proc_ar;
 
 #ifdef DEBUG_RUN_TRACE
@@ -399,8 +411,8 @@
 #endif
 	(void) self_ref;
-	fun_ar = run_get_current_fun_ar(run);
+	proc_ar = run_get_current_proc_ar(run);
 
 	/* Return reference to the currently active object. */
-	rdata_reference(fun_ar->obj, res);
+	run_reference(run, proc_ar->obj, res);
 }
 
@@ -438,6 +450,6 @@
 #endif
 
-	rdata_cvt_value_item(rarg1_i, &rarg1_vi);
-	rdata_cvt_value_item(rarg2_i, &rarg2_vi);
+	run_cvt_value_item(run, rarg1_i, &rarg1_vi);
+	run_cvt_value_item(run, rarg2_i, &rarg2_vi);
 
 	v1 = rarg1_vi->u.value;
@@ -687,5 +699,5 @@
 		/* Evaluate extent argument. */
 		run_expr(run, expr, &rexpr);
-		rdata_cvt_value_item(rexpr, &rexpr_vi);
+		run_cvt_value_item(run, rexpr, &rexpr_vi);
 		assert(rexpr_vi->ic == ic_value);
 		rexpr_var = rexpr_vi->u.value->var;
@@ -727,5 +739,5 @@
 
 	/* Create reference to the new array. */
-	rdata_reference(array_var, res);
+	run_reference(run, array_var, res);
 }
 
@@ -782,5 +794,5 @@
 
 	/* Create reference to the new object. */
-	rdata_reference(obj_var, res);
+	run_reference(run, obj_var, res);
 }
 
@@ -811,15 +823,5 @@
 	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();
-	}
+	vc = rdata_item_get_vc(arg);
 
 	switch (vc) {
@@ -847,5 +849,5 @@
 
 	/* Implicitly dereference. */
-	rdata_dereference(arg, &darg);
+	run_dereference(run, arg, &darg);
 
 	/* Try again. */
@@ -865,5 +867,5 @@
 	printf("Run delegate access operation.\n");
 #endif
-	rdata_cvt_value_item(arg, &arg_vi);
+	run_cvt_value_item(run, arg, &arg_vi);
 	arg_val = arg_vi->u.value;
 	assert(arg_val->var->vc == vc_deleg);
@@ -906,7 +908,12 @@
 {
 	stree_symbol_t *member;
+	rdata_var_t *object_var;
 	rdata_object_t *object;
 	rdata_item_t *ritem;
 	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;
@@ -918,7 +925,9 @@
 #endif
 	assert(arg->ic == ic_address);
-	assert(arg->u.value->var->vc == vc_object);
-
-	object = arg->u.value->var->u.object_v;
+	assert(arg->u.address->ac == ac_var);
+	assert(arg->u.address->u.var_a->vref->vc == vc_object);
+
+	object_var = arg->u.address->u.var_a->vref;
+	object = object_var->u.object_v;
 
 	member = symbol_search_csi(run->program, object->class_sym->u.csi,
@@ -953,5 +962,5 @@
 		var->u.deleg_v = deleg_v;
 
-		deleg_v->obj = arg->u.value->var;
+		deleg_v->obj = arg->u.address->u.var_a->vref;
 		deleg_v->sym = member;
 		break;
@@ -959,14 +968,28 @@
 		/* Construct variable address item. */
 		ritem = rdata_item_new(ic_address);
-		address = rdata_address_new();
+		address = rdata_address_new(ac_var);
+		addr_var = rdata_addr_var_new();
 		ritem->u.address = address;
-
-		address->vref = intmap_get(&object->fields,
+		address->u.var_a = addr_var;
+
+		addr_var->vref = intmap_get(&object->fields,
 		    access->member_name->sid);
-		assert(address->vref != NULL);
+		assert(addr_var->vref != NULL);
 		break;
 	case sc_prop:
-		printf("Unimplemented: Accessing object property.\n");
-		exit(1);
+		/* Construct named property address. */
+		ritem = 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();
+		ritem->u.address = address;
+		address->u.prop_a = addr_prop;
+		addr_prop->u.named = aprop_named;
+
+		deleg_p = rdata_deleg_new();
+		deleg_p->obj = object_var;
+		deleg_p->sym = member;
+		addr_prop->u.named->prop_d = deleg_p;
+		break;
 	}
 
@@ -985,5 +1008,5 @@
 
 	stree_fun_t *fun;
-	run_fun_ar_t *fun_ar;
+	run_proc_ar_t *proc_ar;
 
 #ifdef DEBUG_RUN_TRACE
@@ -1017,5 +1040,5 @@
 		arg = list_node_data(node, stree_expr_t *);
 		run_expr(run, arg, &rarg_i);
-		rdata_cvt_value_item(rarg_i, &rarg_vi);
+		run_cvt_value_item(run, rarg_i, &rarg_vi);
 
 		list_append(&arg_vals, rarg_vi);
@@ -1026,12 +1049,13 @@
 	assert(fun != NULL);
 
-	/* Create function activation record. */
-	run_fun_ar_create(run, deleg_v->obj, fun, &fun_ar);
+	/* Create procedure activation record. */
+	run_proc_ar_create(run, deleg_v->obj, deleg_v->sym, fun->body,
+	    &proc_ar);
 
 	/* Fill in argument values. */
-	run_fun_ar_set_args(run, fun_ar, &arg_vals);
+	run_proc_ar_set_args(run, proc_ar, &arg_vals);
 
 	/* Run the function. */
-	run_fun(run, fun_ar, res);
+	run_proc(run, proc_ar, res);
 
 #ifdef DEBUG_RUN_TRACE
@@ -1048,6 +1072,60 @@
 	stree_expr_t *arg;
 	rdata_item_t *rarg_i, *rarg_vi;
+	var_class_t vc;
+	list_t arg_vals;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run index operation.\n");
+#endif
+	run_expr(run, index->base, &rbase);
+
+	vc = rdata_item_get_vc(rbase);
+
+	/* Implicitly dereference. */
+	if (vc == vc_ref) {
+		run_dereference(run, rbase, &base_i);
+	} else {
+		base_i = rbase;
+	}
+
+	vc = rdata_item_get_vc(base_i);
+
+	/* Evaluate arguments (indices). */
+	node = list_first(&index->args);
+	list_init(&arg_vals);
+
+	while (node != NULL) {
+		arg = list_node_data(node, stree_expr_t *);
+		run_expr(run, arg, &rarg_i);
+		run_cvt_value_item(run, rarg_i, &rarg_vi);
+
+		list_append(&arg_vals, rarg_vi);
+
+		node = list_next(&index->args, node);
+	}
+
+	switch (vc) {
+	case vc_array:
+		run_index_array(run, index, base_i, &arg_vals, res);
+		break;
+	case vc_object:
+		run_index_object(run, index, base_i, &arg_vals, res);
+		break;
+	case vc_string:
+		run_index_string(run, index, base_i, &arg_vals, res);
+		break;
+	default:
+		printf("Error: Indexing object of bad type (%d).\n", vc);
+		exit(1);
+	}
+}
+
+/** Run index operation on array. */
+static void run_index_array(run_t *run, stree_index_t *index,
+    rdata_item_t *base, list_t *args, rdata_item_t **res)
+{
+	list_node_t *node;
 	rdata_array_t *array;
-	var_class_t vc;
+	rdata_item_t *arg;
 
 	int i;
@@ -1057,39 +1135,16 @@
 	rdata_item_t *ritem;
 	rdata_address_t *address;
-
-#ifdef DEBUG_RUN_TRACE
-	printf("Run index operation.\n");
-#endif
-	run_expr(run, index->base, &rbase);
-
-	switch (rbase->ic) {
-	case ic_value:
-		vc = rbase->u.value->var->vc;
-		break;
-	case ic_address:
-		vc = rbase->u.address->vref->vc;
-		break;
-	default:
-		/* Silence warning. */
-		abort();
-	}
-
-	if (vc != vc_ref) {
-		printf("Error: Base of index operation is not a reference.\n");
-		exit(1);
-	}
-
-	rdata_dereference(rbase, &base_i);
-	assert(base_i->ic == ic_address);
-
-	if (base_i->u.value->var->vc != vc_array) {
-		printf("Error: Indexing something which is not an array.\n");
-		exit(1);
-	}
-
-	array = base_i->u.value->var->u.array_v;
-
-	/* Evaluate arguments (indices). */
-	node = list_first(&index->args);
+	rdata_addr_var_t *addr_var;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run array index operation.\n");
+#endif
+	(void) run;
+	(void) index;
+
+	assert(base->ic == ic_address);
+	assert(base->u.address->ac == ac_var);
+	assert(base->u.address->u.var_a->vref->vc == vc_array);
+	array = base->u.address->u.var_a->vref->u.array_v;
 
 	/*
@@ -1099,5 +1154,7 @@
 	elem_index = 0;
 
+	node = list_first(args);
 	i = 0;
+
 	while (node != NULL) {
 		if (i >= array->rank) {
@@ -1107,15 +1164,13 @@
 		}
 
-		arg = list_node_data(node, stree_expr_t *);
-		run_expr(run, arg, &rarg_i);
-		rdata_cvt_value_item(rarg_i, &rarg_vi);
-		assert(rarg_vi->ic == ic_value);
-
-		if (rarg_vi->u.value->var->vc != vc_int) {
+		arg = list_node_data(node, rdata_item_t *);
+		assert(arg->ic == ic_value);
+
+		if (arg->u.value->var->vc != vc_int) {
 			printf("Error: Array index is not an integer.\n");
 			exit(1);
 		}
 
-		arg_val = rarg_vi->u.value->var->u.int_v->value;
+		arg_val = arg->u.value->var->u.int_v->value;
 
 		if (arg_val < 0 || arg_val >= array->extent[i]) {
@@ -1127,5 +1182,5 @@
 		elem_index = elem_index * array->extent[i] + arg_val;
 
-		node = list_next(&index->args, node);
+		node = list_next(args, node);
 		i += 1;
 	}
@@ -1139,11 +1194,164 @@
 	/* Construct variable address item. */
 	ritem = rdata_item_new(ic_address);
-	address = rdata_address_new();
+	address = rdata_address_new(ac_var);
+	addr_var = rdata_addr_var_new();
 	ritem->u.address = address;
-
-	address->vref = array->element[elem_index];
+	address->u.var_a = addr_var;
+
+	addr_var->vref = array->element[elem_index];
 
 	*res = ritem;
 }
+
+/** Index an object (via its indexer). */
+static void run_index_object(run_t *run, stree_index_t *index,
+    rdata_item_t *base, list_t *args, rdata_item_t **res)
+{
+	rdata_item_t *ritem;
+	rdata_address_t *address;
+	rdata_addr_prop_t *addr_prop;
+	rdata_aprop_indexed_t *aprop_indexed;
+	rdata_var_t *obj_var;
+	stree_csi_t *obj_csi;
+	rdata_deleg_t *object_d;
+	stree_symbol_t *indexer_sym;
+	stree_ident_t *indexer_ident;
+
+	list_node_t *node;
+	rdata_item_t *arg;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run object index operation.\n");
+#endif
+	(void) run;
+	(void) index;
+
+	/* Construct property address item. */
+	ritem = rdata_item_new(ic_address);
+	address = rdata_address_new(ac_prop);
+	addr_prop = rdata_addr_prop_new(apc_indexed);
+	aprop_indexed = rdata_aprop_indexed_new();
+	ritem->u.address = address;
+	address->u.prop_a = addr_prop;
+	addr_prop->u.indexed = aprop_indexed;
+
+	if (base->ic != ic_address || base->u.address->ac != ac_var) {
+		/* XXX Several other cases can occur. */
+		printf("Unimplemented: Indexing object varclass via something "
+		    "which is not a simple variable reference.\n");
+		exit(1);
+	}
+
+	/* Find indexer symbol. */
+	obj_var = base->u.address->u.var_a->vref;
+	assert(obj_var->vc == vc_object);
+	indexer_ident = stree_ident_new();
+	indexer_ident->sid = strtab_get_sid(INDEXER_IDENT);
+	obj_csi = symbol_to_csi(obj_var->u.object_v->class_sym);
+	assert(obj_csi != NULL);
+	indexer_sym = symbol_search_csi(run->program, obj_csi, indexer_ident);
+
+	/* Construct delegate. */
+	object_d = rdata_deleg_new();
+	object_d->obj = obj_var;
+	object_d->sym = indexer_sym;
+	aprop_indexed->object_d = object_d;
+
+	/* Copy list of argument values. */
+	list_init(&aprop_indexed->args);
+
+	node = list_first(args);
+	while (node != NULL) {
+		arg = list_node_data(node, rdata_item_t *);
+		list_append(&aprop_indexed->args, arg);
+		node = list_next(args, node);
+	}
+
+	*res = ritem;
+}
+
+/** Run index operation on string. */
+static void run_index_string(run_t *run, stree_index_t *index,
+    rdata_item_t *base, list_t *args, rdata_item_t **res)
+{
+	list_node_t *node;
+	rdata_string_t *string;
+	rdata_item_t *base_vi;
+	rdata_item_t *arg;
+
+	int i;
+	int elem_index;
+	int arg_val;
+	int rc;
+
+	rdata_value_t *value;
+	rdata_var_t *cvar;
+	rdata_item_t *ritem;
+	int cval;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run string index operation.\n");
+#endif
+	(void) run;
+	(void) index;
+
+	run_cvt_value_item(run, base, &base_vi);
+	assert(base_vi->u.value->var->vc == vc_string);
+	string = base->u.value->var->u.string_v;
+
+	/*
+	 * Linear index of the desired element. Elements are stored in
+	 * lexicographic order with the last index changing the fastest.
+	 */
+	node = list_first(args);
+	elem_index = 0;
+
+	i = 0;
+	while (node != NULL) {
+		if (i >= 1) {
+			printf("Error: Too many indices string.\n");
+			exit(1);
+		}
+
+		arg = list_node_data(node, rdata_item_t *);
+		assert(arg->ic == ic_value);
+
+		if (arg->u.value->var->vc != vc_int) {
+			printf("Error: String index is not an integer.\n");
+			exit(1);
+		}
+
+		arg_val = arg->u.value->var->u.int_v->value;
+		elem_index = arg_val;
+
+		node = list_next(args, node);
+		i += 1;
+	}
+
+	if (i < 1) {
+		printf("Error: Too few indices for string.\n");
+		exit(1);
+	}
+
+	rc = os_str_get_char(string->value, elem_index, &cval);
+	if (rc != EOK) {
+		printf("Error: String index (value: %d) is out of range.\n",
+		    arg_val);
+		exit(1);
+	}
+
+	/* Construct character value. */
+	ritem = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	ritem->u.value = value;
+
+	cvar = rdata_var_new(vc_int);
+	cvar->u.int_v = rdata_int_new();
+	cvar->u.int_v->value = cval;
+	value->var = cvar;
+
+	*res = ritem;
+}
+
 
 /** Execute assignment. */
@@ -1160,5 +1368,6 @@
 	run_expr(run, assign->src, &rsrc_i);
 
-	rdata_cvt_value_item(rsrc_i, &rsrc_vi);
+	run_cvt_value_item(run, rsrc_i, &rsrc_vi);
+	assert(rsrc_vi->ic == ic_value);
 	src_val = rsrc_vi->u.value;
 
@@ -1169,5 +1378,5 @@
 	}
 
-	rdata_address_write(rdest_i->u.address, rsrc_vi->u.value);
+	run_address_write(run, rdest_i->u.address, rsrc_vi->u.value);
 
 	*res = NULL;
@@ -1187,5 +1396,5 @@
 
 	(void) run;
-	rdata_cvt_value_item(item, &vitem);
+	run_cvt_value_item(run, item, &vitem);
 
 	assert(vitem->ic == ic_value);
Index: uspace/app/sbi/src/run_t.h
===================================================================
--- uspace/app/sbi/src/run_t.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/run_t.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -44,21 +44,26 @@
 
 
-/** Function activation record
+/** Procedure activation record
  *
- * One is created whenever a function is invoked.
+ * A procedure can be a member function, a named property or an indexed
+ * property. A procedure activation record is created whenever a procedure
+ * is invoked.
  */
-typedef struct run_fun_ar {
-	/** Object on which the member function is being invoked or @c NULL. */
+typedef struct run_proc_ar {
+	/** Object on which the procedure is being invoked or @c NULL. */
 	struct rdata_var *obj;
 
-	/** Definition of function being invoked */
-	struct stree_symbol *fun_sym;
+	/** Definition of function or property being invoked */
+	struct stree_symbol *proc_sym;
+
+	/** Main block of procedure being invoked */
+	struct stree_block *proc_block;
 
 	/** Block activation records */
 	list_t block_ar; /* of run_block_ar_t */
 
-	/** Function return value or @c NULL if not set. */
+	/** Procedure return value or @c NULL if not set. */
 	struct rdata_item *retval;
-} run_fun_ar_t;
+} run_proc_ar_t;
 
 /** Bailout mode
@@ -73,6 +78,6 @@
 	bm_stat,
 
-	/** Return from function */
-	bm_fun,
+	/** Return from procedure */
+	bm_proc,
 
 	/** Exception */
@@ -86,5 +91,5 @@
 typedef struct run_thread_ar {
 	/** Function activation records */
-	list_t fun_ar; /* of run_fun_ar_t */
+	list_t proc_ar; /* of run_proc_ar_t */
 
 	/** Bailout mode */
Index: uspace/app/sbi/src/stree.c
===================================================================
--- uspace/app/sbi/src/stree.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/stree.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -136,15 +136,15 @@
 }
 
-stree_fun_arg_t *stree_fun_arg_new(void)
-{
-	stree_fun_arg_t *fun_arg;
-
-	fun_arg = calloc(1, sizeof(stree_fun_arg_t));
-	if (fun_arg == NULL) {
-		printf("Memory allocation failed.\n");
-		exit(1);
-	}
-
-	return fun_arg;
+stree_proc_arg_t *stree_proc_arg_new(void)
+{
+	stree_proc_arg_t *proc_arg;
+
+	proc_arg = calloc(1, sizeof(stree_proc_arg_t));
+	if (proc_arg == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return proc_arg;
 }
 
@@ -561,5 +561,5 @@
 
 /** Determine if argument @a arg has attribute of class @a aac. */
-bool_t stree_arg_has_attr(stree_fun_arg_t *arg, arg_attr_class_t aac)
+bool_t stree_arg_has_attr(stree_proc_arg_t *arg, arg_attr_class_t aac)
 {
 	list_node_t *node;
Index: uspace/app/sbi/src/stree.h
===================================================================
--- uspace/app/sbi/src/stree.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/stree.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -40,5 +40,5 @@
 stree_prop_t *stree_prop_new(void);
 
-stree_fun_arg_t *stree_fun_arg_new(void);
+stree_proc_arg_t *stree_proc_arg_new(void);
 stree_arg_attr_t *stree_arg_attr_new(arg_attr_class_t aac);
 
@@ -79,5 +79,5 @@
 stree_program_t *stree_program_new(void);
 
-bool_t stree_arg_has_attr(stree_fun_arg_t *arg, arg_attr_class_t aac);
+bool_t stree_arg_has_attr(stree_proc_arg_t *arg, arg_attr_class_t aac);
 bool_t stree_is_csi_derived_from_csi(stree_csi_t *a, stree_csi_t *b);
 
Index: uspace/app/sbi/src/stree_t.h
===================================================================
--- uspace/app/sbi/src/stree_t.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/stree_t.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -270,5 +270,5 @@
 
 /** Statement block */
-typedef struct {
+typedef struct stree_block {
 	/** List of statements in the block */
 	list_t stats; /* of stree_stat_t */
@@ -327,5 +327,4 @@
 	stree_block_t *finally_block;
 } stree_wef_t;
-
 
 /** Statement class */
@@ -378,5 +377,5 @@
 	/* Attributes */
 	list_t attr; /* of stree_arg_attr_t */
-} stree_fun_arg_t;
+} stree_proc_arg_t;
 
 /** Member function declaration */
@@ -389,8 +388,8 @@
 
 	/** Formal parameters */
-	list_t args; /* of stree_fun_arg_t */
+	list_t args; /* of stree_proc_arg_t */
 
 	/** Variadic argument or @c NULL if none. */
-	stree_fun_arg_t *varg;
+	stree_proc_arg_t *varg;
 
 	/** Return type */
@@ -413,5 +412,20 @@
 	struct stree_symbol *symbol;
 	stree_texpr_t *type;
+
+	stree_block_t *getter_body;
+	stree_ident_t *setter_arg_name;
+	stree_block_t *setter_body;
+
+	/** Formal parameters (for indexed properties) */
+	list_t args; /* of stree_proc_arg_t */
+
+	/** Variadic argument or @c NULL if none. */
+	stree_proc_arg_t *varg;
 } stree_prop_t;
+
+/**
+ * Fake identifier used with indexed properties. (Mostly for error messages.)
+ */
+#define INDEXER_IDENT "$indexer"
 
 typedef enum {
Index: uspace/app/sbi/src/strtab.c
===================================================================
--- uspace/app/sbi/src/strtab.c	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/strtab.c	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -49,5 +49,5 @@
 }
 
-sid_t strtab_get_sid(char *str)
+sid_t strtab_get_sid(const char *str)
 {
 	list_node_t *node;
Index: uspace/app/sbi/src/strtab.h
===================================================================
--- uspace/app/sbi/src/strtab.h	(revision 94d484ac742127ae8d87a7e0bb630fafe11f65be)
+++ uspace/app/sbi/src/strtab.h	(revision d0febca9f86b5690d11fec7c645836a758567fe6)
@@ -33,5 +33,5 @@
 
 void strtab_init(void);
-sid_t strtab_get_sid(char *str);
+sid_t strtab_get_sid(const char *str);
 char *strtab_get_str(sid_t sid);
 
