Index: uspace/app/sbi/Makefile
===================================================================
--- uspace/app/sbi/Makefile	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/Makefile	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -35,6 +35,8 @@
 SOURCES = \
 	src/builtin/bi_boxed.c \
+	src/builtin/bi_char.c \
 	src/builtin/bi_error.c \
 	src/builtin/bi_fun.c \
+	src/builtin/bi_int.c \
 	src/builtin/bi_textfile.c \
 	src/builtin/bi_string.c \
Index: uspace/app/sbi/src/ancr.c
===================================================================
--- uspace/app/sbi/src/ancr.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/ancr.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -51,4 +51,5 @@
 #include <assert.h>
 #include "builtin.h"
+#include "cspan.h"
 #include "list.h"
 #include "mytypes.h"
@@ -61,4 +62,6 @@
 static void ancr_csi_dfs(stree_program_t *prog, stree_csi_t *csi);
 static void ancr_csi_process(stree_program_t *prog, stree_csi_t *node);
+static stree_csi_t *ancr_csi_get_pred(stree_program_t *prog, stree_csi_t *csi,
+    stree_texpr_t *pred_ref);
 static void ancr_csi_print_cycle(stree_program_t *prog, stree_csi_t *node);
 
@@ -128,44 +131,34 @@
  *
  * @param prog		Program being processed.
- * @param node		CSI node to process.
- */
-static void ancr_csi_process(stree_program_t *prog, stree_csi_t *node)
-{
-	stree_symbol_t *base_sym;
+ * @param csi		CSI node to process.
+ */
+static void ancr_csi_process(stree_program_t *prog, stree_csi_t *csi)
+{
 	stree_csi_t *base_csi, *outer_csi;
 	stree_csi_t *gf_class;
 
-	if (node->ancr_state == ws_visited) {
+	list_node_t *pred_n;
+	stree_texpr_t *pred;
+	stree_csi_t *pred_csi;
+
+	if (csi->ancr_state == ws_visited) {
 		/* Node already processed */
 		return;
 	}
 
-	if (node->ancr_state == ws_active) {
+	if (csi->ancr_state == ws_active) {
 		/* Error, closed reference loop. */
 		printf("Error: Circular class, struct or interface chain: ");
-		ancr_csi_print_cycle(prog, node);
+		ancr_csi_print_cycle(prog, csi);
 		printf(".\n");
 		exit(1);
 	}
 
-	node->ancr_state = ws_active;
-
-	outer_csi = csi_to_symbol(node)->outer_csi;
+	csi->ancr_state = ws_active;
+
+	outer_csi = csi_to_symbol(csi)->outer_csi;
 	gf_class = builtin_get_gf_class(prog->builtin);
 
-	/* Process outer CSI */
-	if (outer_csi != NULL)
-		ancr_csi_process(prog, outer_csi);
-
-	if (node->base_csi_ref != NULL) {
-		/* Resolve base CSI. */
-		base_sym = symbol_xlookup_in_csi(prog, outer_csi,
-			node->base_csi_ref);
-		base_csi = symbol_to_csi(base_sym);
-		assert(base_csi != NULL);
-
-		/* Process base CSI. */
-		ancr_csi_process(prog, base_csi);
-	} else if (node != gf_class) {
+	if (csi != gf_class){
 		/* Implicit inheritance from grandfather class. */
 		base_csi = gf_class;
@@ -175,7 +168,100 @@
 	}
 
+	/* Process outer CSI */
+	if (outer_csi != NULL)
+		ancr_csi_process(prog, outer_csi);
+
+	/*
+	 * Process inheritance list.
+	 */
+	pred_n = list_first(&csi->inherit);
+
+	/* For a class node, the first entry can be a class. */
+	if (csi->cc == csi_class && pred_n != NULL) {
+		pred = list_node_data(pred_n, stree_texpr_t *);
+		pred_csi = ancr_csi_get_pred(prog, csi, pred);
+		assert(pred_csi != NULL);
+
+		if (pred_csi->cc == csi_class) {
+			/* Process base class */
+			base_csi = pred_csi;
+			ancr_csi_process(prog, pred_csi);
+
+			pred_n = list_next(&csi->inherit, pred_n);
+		}
+	}
+
+	/* Following entires can only be interfaces. */
+	while (pred_n != NULL) {
+		pred = list_node_data(pred_n, stree_texpr_t *);
+		pred_csi = ancr_csi_get_pred(prog, csi, pred);
+		assert(pred_csi != NULL);
+
+		/* Process implemented or accumulated interface. */
+		ancr_csi_process(prog, pred_csi);
+
+		switch (pred_csi->cc) {
+		case csi_class:
+			switch (csi->cc) {
+			case csi_class:
+				cspan_print(csi->name->cspan);
+				printf(" Error: Only the first predecessor "
+				    "can be a class. ('");
+				symbol_print_fqn(csi_to_symbol(csi));
+				printf("' deriving from '");
+				symbol_print_fqn(csi_to_symbol(pred_csi));
+				printf("').\n");
+				exit(1);
+				break;
+			case csi_struct:
+				assert(b_false); /* XXX */
+			case csi_interface:
+				cspan_print(csi->name->cspan);
+				printf(" Error: Interface predecessor must be "
+				    "an interface ('");
+				symbol_print_fqn(csi_to_symbol(csi));
+				printf("' deriving from '");
+				symbol_print_fqn(csi_to_symbol(pred_csi));
+				printf("').\n");
+				exit(1);
+				break;
+			}
+		case csi_struct:
+			assert(b_false); /* XXX */
+		case csi_interface:
+			break;
+		}
+
+		pred_n = list_next(&csi->inherit, pred_n);
+	}
+
 	/* Store base CSI and update node state. */
-	node->ancr_state = ws_visited;
-	node->base_csi = base_csi;
+	csi->ancr_state = ws_visited;
+	csi->base_csi = base_csi;
+}
+
+/** Resolve CSI predecessor reference.
+ *
+ * Returns the CSI predecessor referenced by @a pred_ref.
+ * If the referenced CSI does not exist, an error is generated.
+ *
+ * @param prog		Program being processed.
+ * @param csi		CSI node to process.
+ * @param pred_ref	Type expression referencing the predecessor.
+ * @return		Predecessor CSI.
+ */
+static stree_csi_t *ancr_csi_get_pred(stree_program_t *prog, stree_csi_t *csi,
+    stree_texpr_t *pred_ref)
+{
+	stree_csi_t *outer_csi;
+	stree_symbol_t *pred_sym;
+	stree_csi_t *pred_csi;
+
+	outer_csi = csi_to_symbol(csi)->outer_csi;
+	pred_sym = symbol_xlookup_in_csi(prog, outer_csi, pred_ref);
+	pred_csi = symbol_to_csi(pred_sym);
+	assert(pred_csi != NULL); /* XXX */
+
+	return pred_csi;
 }
 
@@ -191,6 +277,8 @@
 {
 	stree_csi_t *n;
-	stree_symbol_t *base_sym, *node_sym;
-	stree_csi_t *base_csi, *outer_csi;
+	stree_symbol_t *pred_sym, *node_sym;
+	stree_csi_t *pred_csi, *outer_csi;
+	stree_texpr_t *pred;
+	list_node_t *pred_n;
 
 	n = node;
@@ -204,15 +292,22 @@
 		if (outer_csi != NULL && outer_csi->ancr_state == ws_active) {
 			node = outer_csi;
-		} else if (node->base_csi_ref != NULL) {
-			/* Resolve base CSI. */
-			base_sym = symbol_xlookup_in_csi(prog, outer_csi,
-				node->base_csi_ref);
-			base_csi = symbol_to_csi(base_sym);
-			assert(base_csi != NULL);
-
-			assert(base_csi->ancr_state == ws_active);
-			node = base_csi;
 		} else {
-			assert(b_false);
+			node = NULL;
+
+			pred_n = list_first(&node->inherit);
+			while (pred_n != NULL) {
+				pred = list_node_data(pred_n, stree_texpr_t *);
+				pred_sym = symbol_xlookup_in_csi(prog,
+				    outer_csi, pred);
+				pred_csi = symbol_to_csi(pred_sym);
+				assert(pred_csi != NULL);
+
+				if (pred_csi->ancr_state == ws_active) {
+					node = pred_csi;
+					break;
+				}
+			}
+
+			assert(node != NULL);
 		}
 	} while (n != node);
Index: uspace/app/sbi/src/bigint.c
===================================================================
--- uspace/app/sbi/src/bigint.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/bigint.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -360,28 +360,31 @@
 }
 
-/** Print bigint to standard output. */
-void bigint_print(bigint_t *bigint)
-{
+/** Convert bigint to string.
+ *
+ * @param bigint	Bigint to convert.
+ * @param dptr		Place to store pointer to new string.
+ */
+void bigint_get_as_string(bigint_t *bigint, char **dptr)
+{
+	static const char digits[] = { '0', '1', '2', '3', '4', '5', '6',
+	    '7', '8', '9' };
+
 	bigint_t val, tmp;
 	bigint_word_t rem;
-	size_t ndigits;
-	int *digits;
-	size_t idx;
-
-#ifdef DEBUG_BIGINT_TRACE
-	printf("Print bigint.\n");
+	size_t nchars;
+	char *str;
+	size_t idx;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Convert bigint to string.\n");
 #endif
 	assert(BIGINT_BASE >= 10);
 
-	if (bigint_is_zero(bigint)) {
-		putchar('0');
-		return;
-	}
-
-	if (bigint->negative)
-		putchar('-');
-
-	/* Compute number of digits. */
-	ndigits = 0;
+	/* Compute number of characters. */
+	nchars = 0;
+
+	if (bigint_is_zero(bigint) || bigint->negative)
+		nchars += 1; /* '0' or '-' */
+
 	bigint_clone(bigint, &val);
 	while (bigint_is_zero(&val) != b_true) {
@@ -390,17 +393,23 @@
 		bigint_shallow_copy(&tmp, &val);
 
-		ndigits += 1;
+		nchars += 1;
 	}
 	bigint_destroy(&val);
 
-	/* Store digits to array. */
-
-	digits = malloc(ndigits * sizeof(int));
-	if (digits == NULL) {
+	/* Store characters to array. */
+
+	str = malloc(nchars * sizeof(char) + 1);
+	if (str == NULL) {
 		printf("Memory allocation failed.\n");
 		exit(1);
 	}
 
-	idx = 0;
+	if (bigint_is_zero(bigint)) {
+		str[0] = '0';
+	} else if (bigint->negative) {
+		str[0] = '-';
+	}
+
+	idx = 1;
 	bigint_clone(bigint, &val);
 	while (bigint_is_zero(&val) != b_true) {
@@ -409,12 +418,27 @@
 		bigint_shallow_copy(&tmp, &val);
 
-		digits[idx++] = (int) rem;
-	}
+		str[nchars - idx] = digits[(int) rem];
+		++idx;
+	}
+
 	bigint_destroy(&val);
-
-	for (idx = 0; idx < ndigits; ++idx)
-		printf("%u", digits[ndigits - 1 - idx]);
-
-	free(digits);
+	str[nchars] = '\0';
+	*dptr = str;
+}
+
+/** Print bigint to standard output.
+ *
+ * @param bigint	Bigint to print.
+ */
+void bigint_print(bigint_t *bigint)
+{
+	char *str;
+
+#ifdef DEBUG_BIGINT_TRACE
+	printf("Print bigint.\n");
+#endif
+	bigint_get_as_string(bigint, &str);
+	printf("%s", str);
+	free(str);
 }
 
Index: uspace/app/sbi/src/bigint.h
===================================================================
--- uspace/app/sbi/src/bigint.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/bigint.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -48,4 +48,6 @@
 void bigint_sub(bigint_t *a, bigint_t *b, bigint_t *dest);
 void bigint_mul(bigint_t *a, bigint_t *b, bigint_t *dest);
+
+void bigint_get_as_string(bigint_t *bigint, char **dptr);
 void bigint_print(bigint_t *bigint);
 
Index: uspace/app/sbi/src/builtin.c
===================================================================
--- uspace/app/sbi/src/builtin.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/builtin.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -42,5 +42,7 @@
 #include "builtin/bi_boxed.h"
 #include "builtin/bi_error.h"
+#include "builtin/bi_char.h"
 #include "builtin/bi_fun.h"
+#include "builtin/bi_int.h"
 #include "builtin/bi_textfile.h"
 #include "builtin/bi_string.h"
@@ -52,4 +54,5 @@
 #include "os/os.h"
 #include "parse.h"
+#include "rdata.h"
 #include "run.h"
 #include "stree.h"
@@ -89,5 +92,7 @@
 
 	bi_error_declare(bi);
+	bi_char_declare(bi);
 	bi_fun_declare(bi);
+	bi_int_declare(bi);
 	bi_textfile_declare(bi);
 	bi_string_declare(bi);
@@ -105,5 +110,7 @@
 	bi_boxed_bind(bi);
 	bi_error_bind(bi);
+	bi_char_bind(bi);
 	bi_fun_bind(bi);
+	bi_int_bind(bi);
 	bi_textfile_bind(bi);
 	bi_string_bind(bi);
@@ -250,5 +257,4 @@
 {
 	stree_symbol_t *fun_sym;
-	builtin_t *bi;
 	builtin_proc_t bproc;
 
@@ -257,5 +263,4 @@
 #endif
 	fun_sym = proc->outer_symbol;
-	bi = run->program->builtin;
 
 	bproc = proc->bi_handler;
@@ -298,5 +303,40 @@
 }
 
-/** Declare a builtin function in @a csi.
+/** Return string value from builtin procedure.
+ *
+ * Makes it easy for a builtin procedure to return value of type @c string.
+ *
+ * @param run		Runner object
+ * @param str		String value. Must be allocated from heap and its
+ *			ownership is hereby given up.
+ */
+void builtin_return_string(run_t *run, const char *astr)
+{
+	rdata_string_t *rstring;
+	rdata_var_t *rvar;
+	rdata_value_t *rval;
+	rdata_item_t *ritem;
+
+	run_proc_ar_t *proc_ar;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Return string '%s' from builtin function.\n", astr);
+#endif
+	rstring = rdata_string_new();
+	rstring->value = astr;
+
+	rvar = rdata_var_new(vc_string);
+	rvar->u.string_v = rstring;
+	rval = rdata_value_new();
+	rval->var = rvar;
+
+	ritem = rdata_item_new(ic_value);
+	ritem->u.value = rval;
+
+	proc_ar = run_get_current_proc_ar(run);
+	proc_ar->retval = ritem;
+}
+
+/** Declare a static builtin function in @a csi.
  *
  * Declare a builtin function member of CSI @a csi. Deprecated in favor
@@ -314,4 +354,5 @@
 	stree_csimbr_t *csimbr;
 	stree_symbol_t *fun_sym;
+	stree_symbol_attr_t *sym_attr;
 
 	ident = stree_ident_new();
@@ -333,4 +374,8 @@
 	fun_sym->u.fun = fun;
 	fun_sym->outer_csi = csi;
+
+	sym_attr = stree_symbol_attr_new(sac_static);
+	list_append(&fun_sym->attr, sym_attr);
+
 	fun->symbol = fun_sym;
 	fun->proc->outer_symbol = fun_sym;
Index: uspace/app/sbi/src/builtin.h
===================================================================
--- uspace/app/sbi/src/builtin.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/builtin.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -40,4 +40,5 @@
 
 rdata_var_t *builtin_get_self_mbr_var(run_t *run, const char *mbr_name);
+void builtin_return_string(run_t *run, const char *str);
 
 stree_symbol_t *builtin_declare_fun(stree_csi_t *csi, const char *name);
Index: uspace/app/sbi/src/builtin/bi_char.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_char.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
+++ uspace/app/sbi/src/builtin/bi_char.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Char builtin binding. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "../bigint.h"
+#include "../builtin.h"
+#include "../debug.h"
+#include "../mytypes.h"
+#include "../os/os.h"
+#include "../rdata.h"
+#include "../run.h"
+#include "../strtab.h"
+
+#include "bi_char.h"
+
+static void bi_char_get_as_string(run_t *run);
+
+/** Declare Char builtin.
+ *
+ * @param bi	Builtin object
+ */
+void bi_char_declare(builtin_t *bi)
+{
+	(void) bi;
+}
+
+/** Bind Char builtin.
+ *
+ * @param bi	Builtin object
+ */
+void bi_char_bind(builtin_t *bi)
+{
+	builtin_fun_bind(bi, "Char", "get_as_string", bi_char_get_as_string);
+}
+
+/** Return string representation.
+ *
+ * @param run	Runner object
+ */
+static void bi_char_get_as_string(run_t *run)
+{
+        rdata_var_t *self_value_var;
+        bigint_t *cval;
+        char *str;
+        int char_val;
+        int rc;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Convert char to string.\n");
+#endif
+	/* Extract self.Value */
+	self_value_var = builtin_get_self_mbr_var(run, "Value");
+	assert(self_value_var->vc == vc_char);
+	cval = &self_value_var->u.char_v->value;
+
+	rc = bigint_get_value_int(cval, &char_val);
+	if (rc != EOK) {
+		/* XXX Should raise exception. */
+		builtin_return_string(run, os_str_dup("?"));
+		return;
+	}
+
+	str = os_chr_to_astr((wchar_t) char_val);
+
+	/* Ownership of str is transferred. */
+	builtin_return_string(run, str);
+}
Index: uspace/app/sbi/src/builtin/bi_char.h
===================================================================
--- uspace/app/sbi/src/builtin/bi_char.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
+++ uspace/app/sbi/src/builtin/bi_char.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BI_CHAR_H_
+#define BI_CHAR_H_
+
+#include "../mytypes.h"
+
+void bi_char_declare(builtin_t *bi);
+void bi_char_bind(builtin_t *bi);
+
+#endif
Index: uspace/app/sbi/src/builtin/bi_fun.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_fun.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/builtin/bi_fun.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -94,5 +94,5 @@
 	builtin_code_snippet(bi,
 		"class Task is\n"
-			"fun Exec(args : string[], packed), builtin;\n"
+			"fun Exec(args : string[], packed), static, builtin;\n"
 		"end\n");
 }
Index: uspace/app/sbi/src/builtin/bi_int.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_int.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
+++ uspace/app/sbi/src/builtin/bi_int.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file Int builtin binding. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "../bigint.h"
+#include "../builtin.h"
+#include "../debug.h"
+#include "../mytypes.h"
+#include "../os/os.h"
+#include "../rdata.h"
+#include "../run.h"
+#include "../strtab.h"
+
+#include "bi_int.h"
+
+static void bi_int_get_as_string(run_t *run);
+
+/** Declare Int builtin.
+ *
+ * @param bi	Builtin object
+ */
+void bi_int_declare(builtin_t *bi)
+{
+	(void) bi;
+}
+
+/** Bind Int builtin.
+ *
+ * @param bi	Builtin object
+ */
+void bi_int_bind(builtin_t *bi)
+{
+	builtin_fun_bind(bi, "Int", "get_as_string", bi_int_get_as_string);
+}
+
+/** Return string representation.
+ *
+ * @param run	Runner object
+ */
+static void bi_int_get_as_string(run_t *run)
+{
+        rdata_var_t *self_value_var;
+        bigint_t *ival;
+        char *str;
+
+	/* Extract self.Value */
+	self_value_var = builtin_get_self_mbr_var(run, "Value");
+	assert(self_value_var->vc == vc_int);
+	ival = &self_value_var->u.int_v->value;
+
+	bigint_get_as_string(ival, &str);
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Convert int to string '%s'.\n", str);
+#endif
+	/* Ownership of str is transferred. */
+	builtin_return_string(run, str);
+}
Index: uspace/app/sbi/src/builtin/bi_int.h
===================================================================
--- uspace/app/sbi/src/builtin/bi_int.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
+++ uspace/app/sbi/src/builtin/bi_int.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BI_INT_H_
+#define BI_INT_H_
+
+#include "../mytypes.h"
+
+void bi_int_declare(builtin_t *bi);
+void bi_int_bind(builtin_t *bi);
+
+#endif
Index: uspace/app/sbi/src/builtin/bi_string.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_string.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/builtin/bi_string.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -116,4 +116,5 @@
         rdata_var_t *self_value_var;
         const char *str;
+        const char *slice;
         size_t str_l;
 
@@ -125,11 +126,4 @@
 
 	int rc;
-
-	rdata_string_t *rstring;
-	rdata_var_t *rvar;
-	rdata_value_t *rval;
-	rdata_item_t *ritem;
-
-	run_proc_ar_t *proc_ar;
 
 	/* Extract self.Value */
@@ -165,17 +159,7 @@
 	    start, length, str);
 #endif
-	/* Construct return value. */
-	rstring = rdata_string_new();
-	rstring->value = os_str_aslice(str, start, length);
+	slice = os_str_aslice(str, start, length);
 
-	rvar = rdata_var_new(vc_string);
-	rvar->u.string_v = rstring;
-	rval = rdata_value_new();
-	rval->var = rvar;
-
-	ritem = rdata_item_new(ic_value);
-	ritem->u.value = rval;
-
-	proc_ar = run_get_current_proc_ar(run);
-	proc_ar->retval = ritem;
+	/* Ownership of slice is transferred. */
+	builtin_return_string(run, slice);
 }
Index: uspace/app/sbi/src/imode.c
===================================================================
--- uspace/app/sbi/src/imode.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/imode.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -130,7 +130,9 @@
 
 	/* Construct run context. */
+	run_gdata_init(&run);
+
 	run.thread_ar = run_thread_ar_new();
 	list_init(&run.thread_ar->proc_ar);
-	run_proc_ar_create(&run, NULL, proc, &proc_ar);
+	run_proc_ar_create(&run, run.gdata, proc, &proc_ar);
 	list_append(&run.thread_ar->proc_ar, proc_ar);
 
Index: uspace/app/sbi/src/input.c
===================================================================
--- uspace/app/sbi/src/input.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/input.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -206,5 +206,5 @@
 			*dp++ = *sp++;
 
-		*dp++ = '\0';
+		*dp = '\0';
 		input->str = sp;
 		*line = input->buffer;
Index: uspace/app/sbi/src/mytypes.h
===================================================================
--- uspace/app/sbi/src/mytypes.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/mytypes.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -43,4 +43,10 @@
 } walk_state_t;
 
+/** Static vs. nonstatic */
+typedef enum {
+	sn_nonstatic,
+	sn_static
+} statns_t;
+
 /** Error return codes. */
 #include <errno.h>
Index: uspace/app/sbi/src/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/os/helenos.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -173,4 +173,31 @@
 }
 
+/** Convert character to new string.
+ *
+ * @param chr		Character
+ * @return		Newly allocated string.
+ */
+char *os_chr_to_astr(wchar_t chr)
+{
+	char *str;
+	size_t offset;
+
+	str = malloc(STR_BOUNDS(1) + 1);
+	if (str == NULL) {
+		printf("Memory allocation error.\n");
+		exit(1);
+	}
+
+	offset = 0;
+	if (chr_encode(chr, str, &offset, STR_BOUNDS(1)) != EOK) {
+		/* XXX Should handle gracefully */
+		printf("String conversion error.\n");
+		exit(1);
+	}
+
+	str[offset] = '\0';
+	return str;
+}
+
 /** Display survival help message. */
 void os_input_disp_help(void)
Index: uspace/app/sbi/src/os/os.h
===================================================================
--- uspace/app/sbi/src/os/os.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/os/os.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -36,4 +36,5 @@
 size_t os_str_length(const char *str);
 int os_str_get_char(const char *str, int index, int *out_char);
+char *os_chr_to_astr(wchar_t chr);
 void os_input_disp_help(void);
 int os_input_line(char **ptr);
Index: uspace/app/sbi/src/os/posix.c
===================================================================
--- uspace/app/sbi/src/os/posix.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/os/posix.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -159,4 +159,25 @@
 }
 
+/** Convert character to new string.
+ *
+ * @param chr		Character
+ * @return		Newly allocated string.
+ */
+char *os_chr_to_astr(wchar_t chr)
+{
+	char *str;
+
+	str = malloc(2);
+	if (str == NULL) {
+		printf("Memory allocation error.\n");
+		exit(1);
+	}
+
+	str[0] = (char) chr;
+	str[1] = '\0';
+
+	return str;
+}
+
 #define OS_INPUT_BUFFER_SIZE 256
 static char os_input_buffer[OS_INPUT_BUFFER_SIZE];
Index: uspace/app/sbi/src/parse.c
===================================================================
--- uspace/app/sbi/src/parse.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/parse.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -35,4 +35,5 @@
 #include <assert.h>
 #include <stdlib.h>
+#include "cspan.h"
 #include "debug.h"
 #include "lex.h"
@@ -64,4 +65,5 @@
 static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi);
 
+static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol);
 static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse);
 
@@ -70,4 +72,6 @@
 static stree_fun_sig_t *parse_fun_sig(parse_t *parse);
 
+static void parse_prop_get(parse_t *parse, stree_prop_t *prop);
+static void parse_prop_set(parse_t *parse, stree_prop_t *prop);
 
 /*
@@ -175,4 +179,5 @@
 	stree_ident_t *targ_name;
 	stree_targ_t *targ;
+	stree_texpr_t *pref;
 
 	switch (dclass) {
@@ -212,7 +217,16 @@
 		/* Inheritance list */
 		lskip(parse);
-		csi->base_csi_ref = parse_texpr(parse);
-	} else {
-		csi->base_csi_ref = NULL;
+
+		while (b_true) {
+			pref = parse_texpr(parse);
+			if (parse_is_error(parse))
+				break;
+
+			list_append(&csi->inherit, pref);
+			if (lcur_lc(parse) != lc_plus)
+				break;
+
+			lskip(parse);
+		}
 	}
 
@@ -224,10 +238,24 @@
 		csimbr = parse_csimbr(parse, csi);
 		if (csimbr == NULL)
+			continue;
+
+		list_append(&csi->members, csimbr);
+	}
+
+	lmatch(parse, lc_end);
+
+	if (outer_csi != NULL) {
+		switch (outer_csi->cc) {
+		case csi_class:
+		case csi_struct:
 			break;
-
-		list_append(&csi->members, csimbr);
-	}
-
-	lmatch(parse, lc_end);
+		case csi_interface:
+			cspan_print(csi->name->cspan);
+			printf(" Error: CSI declared inside interface.\n");
+			parse_note_error(parse);
+			/* XXX Free csi */
+			return NULL;
+		}
+	}
 
 	return csi;
@@ -253,4 +281,6 @@
 	stree_prop_t *prop;
 
+	csimbr = NULL;
+
 	switch (lcur_lc(parse)) {
 	case lc_class:
@@ -258,21 +288,29 @@
 	case lc_interface:
 		csi = parse_csi(parse, lcur_lc(parse), outer_csi);
-		csimbr = stree_csimbr_new(csimbr_csi);
-		csimbr->u.csi = csi;
+		if (csi != NULL) {
+			csimbr = stree_csimbr_new(csimbr_csi);
+			csimbr->u.csi = csi;
+		}
 		break;
 	case lc_new:
 		ctor = parse_ctor(parse, outer_csi);
-		csimbr = stree_csimbr_new(csimbr_ctor);
-		csimbr->u.ctor = ctor;
+		if (ctor != NULL) {
+			csimbr = stree_csimbr_new(csimbr_ctor);
+			csimbr->u.ctor = ctor;
+		}
 		break;
 	case lc_deleg:
 		deleg = parse_deleg(parse, outer_csi);
-		csimbr = stree_csimbr_new(csimbr_deleg);
-		csimbr->u.deleg = deleg;
+		if (deleg != NULL) {
+			csimbr = stree_csimbr_new(csimbr_deleg);
+			csimbr->u.deleg = deleg;
+		}
 		break;
 	case lc_enum:
 		enum_d = parse_enum(parse, outer_csi);
-		csimbr = stree_csimbr_new(csimbr_enum);
-		csimbr->u.enum_d = enum_d;
+		if (enum_d != NULL) {
+			csimbr = stree_csimbr_new(csimbr_enum);
+			csimbr->u.enum_d = enum_d;
+		}
 		break;
 	case lc_fun:
@@ -283,6 +321,8 @@
 	case lc_var:
 		var = parse_var(parse, outer_csi);
-		csimbr = stree_csimbr_new(csimbr_var);
-		csimbr->u.var = var;
+		if (var != NULL) {
+			csimbr = stree_csimbr_new(csimbr_var);
+			csimbr->u.var = var;
+		}
 		break;
 	case lc_prop:
@@ -294,5 +334,4 @@
 		lunexpected_error(parse);
 		lex_next(parse->lex);
-		csimbr = NULL;
 		break;
 	}
@@ -311,5 +350,5 @@
 	stree_ctor_t *ctor;
 	stree_symbol_t *symbol;
-	stree_symbol_attr_t *attr;
+	cspan_t *cspan;
 
 	ctor = stree_ctor_new();
@@ -321,4 +360,5 @@
 
 	lmatch(parse, lc_new);
+	cspan = lprev_span(parse);
 
 	/* Fake identifier. */
@@ -334,5 +374,6 @@
 	ctor->sig = parse_fun_sig(parse);
 	if (ctor->sig->rtype != NULL) {
-		printf("Error: Constructor of CSI '");
+		cspan_print(cspan);
+		printf(" Error: Constructor of CSI '");
 		symbol_print_fqn(csi_to_symbol(outer_csi));
 		printf("' has a return type.\n");
@@ -340,12 +381,6 @@
 	}
 
-	list_init(&symbol->attr);
-
 	/* Parse attributes. */
-	while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
-		lskip(parse);
-		attr = parse_symbol_attr(parse);
-		list_append(&symbol->attr, attr);
-	}
+	parse_symbol_attrs(parse, symbol);
 
 	ctor->proc = stree_proc_new();
@@ -356,5 +391,6 @@
 
 		/* This constructor has no body. */
-		printf("Error: Constructor of CSI '");
+		cspan_print(cspan);
+		printf(" Error: Constructor of CSI '");
 		symbol_print_fqn(csi_to_symbol(outer_csi));
 		printf("' has no body.\n");
@@ -368,4 +404,16 @@
 	}
 
+	switch (outer_csi->cc) {
+	case csi_class:
+	case csi_struct:
+		break;
+	case csi_interface:
+		cspan_print(ctor->name->cspan);
+		printf(" Error: Constructor declared inside interface.\n");
+		parse_note_error(parse);
+		/* XXX Free ctor */
+		return NULL;
+	}
+
 	return ctor;
 }
@@ -409,4 +457,5 @@
 
 	if (list_is_empty(&enum_d->members)) {
+		cspan_print(enum_d->name->cspan);
 		printf("Error: Enum type '%s' has no members.\n",
 		    strtab_get_str(enum_d->name->sid));
@@ -416,4 +465,18 @@
 	lmatch(parse, lc_end);
 
+	if (outer_csi != NULL) {
+		switch (outer_csi->cc) {
+		case csi_class:
+		case csi_struct:
+			break;
+		case csi_interface:
+			cspan_print(enum_d->name->cspan);
+			printf(" Error: Enum declared inside interface.\n");
+			parse_note_error(parse);
+			/* XXX Free enum */
+			return NULL;
+		}
+	}
+
 	return enum_d;
 }
@@ -449,5 +512,4 @@
 	stree_deleg_t *deleg;
 	stree_symbol_t *symbol;
-	stree_symbol_attr_t *attr;
 
 	deleg = stree_deleg_new();
@@ -467,14 +529,20 @@
 	deleg->sig = parse_fun_sig(parse);
 
-	list_init(&symbol->attr);
-
 	/* Parse attributes. */
-	while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
-		lskip(parse);
-		attr = parse_symbol_attr(parse);
-		list_append(&symbol->attr, attr);
-	}
+	parse_symbol_attrs(parse, symbol);
 
 	lmatch(parse, lc_scolon);
+
+	switch (outer_csi->cc) {
+	case csi_class:
+	case csi_struct:
+		break;
+	case csi_interface:
+		cspan_print(deleg->name->cspan);
+		printf(" Error: Delegate declared inside interface.\n");
+		parse_note_error(parse);
+		/* XXX Free deleg */
+		return NULL;
+	}
 
 	return deleg;
@@ -491,5 +559,5 @@
 	stree_fun_t *fun;
 	stree_symbol_t *symbol;
-	stree_symbol_attr_t *attr;
+	bool_t body_expected;
 
 	fun = stree_fun_new();
@@ -508,12 +576,9 @@
 	fun->sig = parse_fun_sig(parse);
 
-	list_init(&symbol->attr);
-
 	/* Parse attributes. */
-	while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
-		lskip(parse);
-		attr = parse_symbol_attr(parse);
-		list_append(&symbol->attr, attr);
-	}
+	parse_symbol_attrs(parse, symbol);
+
+	body_expected = !stree_symbol_has_attr(symbol, sac_builtin) &&
+	    (outer_csi->cc != csi_interface);
 
 	fun->proc = stree_proc_new();
@@ -523,11 +588,13 @@
 		lskip(parse);
 
-		/* This function has no body. */
-		if (!stree_symbol_has_attr(symbol, sac_builtin)) {
-			printf("Error: Function '");
+		/* Body not present */
+		if (body_expected) {
+			cspan_print(fun->name->cspan);
+			printf(" Error: Function '");
 			symbol_print_fqn(symbol);
-			printf("' has no body.\n");
+			printf("' should have a body.\n");
 			parse_note_error(parse);
 		}
+
 		fun->proc->body = NULL;
 	} else {
@@ -535,4 +602,13 @@
 		fun->proc->body = parse_block(parse);
 		lmatch(parse, lc_end);
+
+		/* Body present */
+		if (!body_expected) {
+			cspan_print(fun->name->cspan);
+			printf(" Error: Function declaration '");
+			symbol_print_fqn(symbol);
+			printf("' should not have a body.\n");
+			parse_note_error(parse);
+		}
 	}
 
@@ -561,5 +637,20 @@
 	lmatch(parse, lc_colon);
 	var->type =  parse_texpr(parse);
+
+	parse_symbol_attrs(parse, symbol);
+
 	lmatch(parse, lc_scolon);
+
+	switch (outer_csi->cc) {
+	case csi_class:
+	case csi_struct:
+		break;
+	case csi_interface:
+		cspan_print(var->name->cspan);
+		printf(" Error: Variable declared inside interface.\n");
+		parse_note_error(parse);
+		/* XXX Free var */
+		return NULL;
+	}
 
 	return var;
@@ -576,4 +667,5 @@
 	stree_prop_t *prop;
 	stree_symbol_t *symbol;
+	bool_t body_expected;
 
 	stree_ident_t *ident;
@@ -625,4 +717,10 @@
 	lmatch(parse, lc_colon);
 	prop->type = parse_texpr(parse);
+
+	/* Parse attributes. */
+	parse_symbol_attrs(parse, symbol);
+
+	body_expected = (outer_csi->cc != csi_interface);
+
 	lmatch(parse, lc_is);
 
@@ -630,40 +728,8 @@
 		switch (lcur_lc(parse)) {
 		case lc_get:
-			lskip(parse);
-			lmatch(parse, lc_is);
-			if (prop->getter != NULL) {
-				printf("Error: Duplicate getter.\n");
-				(void) parse_block(parse); /* XXX Free */
-				lmatch(parse, lc_end);
-				parse_note_error(parse);
-				break;
-			}
-
-			/* Create setter procedure */
-			prop->getter = stree_proc_new();
-			prop->getter->body = parse_block(parse);
-			prop->getter->outer_symbol = symbol;
-
-			lmatch(parse, lc_end);
+			parse_prop_get(parse, prop);
 			break;
 		case lc_set:
-			lskip(parse);
-			prop->setter_arg = stree_proc_arg_new();
-			prop->setter_arg->name = parse_ident(parse);
-			prop->setter_arg->type = prop->type;
-			lmatch(parse, lc_is);
-			if (prop->setter != NULL) {
-				printf("Error: Duplicate setter.\n");
-				(void) parse_block(parse); /* XXX Free */
-				lmatch(parse, lc_end);
-				parse_note_error(parse);
-			}
-
-			/* Create setter procedure */
-			prop->setter = stree_proc_new();
-			prop->setter->body = parse_block(parse);
-			prop->setter->outer_symbol = symbol;
-
-			lmatch(parse, lc_end);
+			parse_prop_set(parse, prop);
 			break;
 		default:
@@ -677,24 +743,51 @@
 }
 
+/** Parse symbol attributes.
+ *
+ * Parse list of attributes and add them to @a symbol.
+ *
+ * @param parse		Parser object
+ * @param symbol	Symbol to add these attributes to
+ */
+static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol)
+{
+	stree_symbol_attr_t *attr;
+
+	/* Parse attributes. */
+	while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
+		lskip(parse);
+		attr = parse_symbol_attr(parse);
+		list_append(&symbol->attr, attr);
+	}
+}
+
 /** Parse symbol attribute.
  *
- * @param parse		Parser object.
- * @param outer_csi	CSI containing this declaration or @c NULL if global.
- * @return		New syntax tree node.
+ * @param parse		Parser object
+ * @return		New syntax tree node
  */
 static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse)
 {
 	stree_symbol_attr_t *attr;
-
-	if (lcur_lc(parse) != lc_builtin) {
-		printf("Error: Unexpected attribute '");
+	symbol_attr_class_t sac;
+
+	/* Make compiler happy. */
+	sac = 0;
+
+	switch (lcur_lc(parse)) {
+	case lc_builtin: sac = sac_builtin; break;
+	case lc_static: sac = sac_static; break;
+	default:
+		cspan_print(lcur_span(parse));
+		printf(" Error: Unexpected attribute '");
 		lem_print(lcur(parse));
 		printf("'.\n");
 		parse_note_error(parse);
+		break;
 	}
 
 	lskip(parse);
 
-	attr = stree_symbol_attr_new(sac_builtin);
+	attr = stree_symbol_attr_new(sac);
 	return attr;
 }
@@ -718,5 +811,5 @@
 	printf("Parse procedure argument.\n");
 #endif
- 	list_init(&arg->attr);
+	list_init(&arg->attr);
 
 	/* Parse attributes. */
@@ -740,5 +833,6 @@
 
 	if (lcur_lc(parse) != lc_packed) {
-		printf("Error: Unexpected attribute '");
+		cspan_print(lcur_span(parse));
+		printf(" Error: Unexpected attribute '");
 		lem_print(lcur(parse));
 		printf("'.\n");
@@ -802,4 +896,138 @@
 
 	return sig;
+}
+
+/** Parse member property getter.
+ *
+ * @param parse		Parser object.
+ * @param prop		Property containing this declaration.
+ */
+static void parse_prop_get(parse_t *parse, stree_prop_t *prop)
+{
+	cspan_t *cspan;
+	stree_block_t *block;
+	stree_proc_t *getter;
+	bool_t body_expected;
+
+	body_expected = (prop->symbol->outer_csi->cc != csi_interface);
+
+	lskip(parse);
+	cspan = lprev_span(parse);
+
+	if (prop->getter != NULL) {
+		cspan_print(cspan);
+		printf(" Error: Duplicate getter.\n");
+		parse_note_error(parse);
+		return;
+	}
+
+	if (lcur_lc(parse) == lc_scolon) {
+		/* Body not present */
+		lskip(parse);
+		block = NULL;
+
+		if (body_expected) {
+			cspan_print(prop->name->cspan);
+			printf(" Error: Property '");
+			symbol_print_fqn(prop->symbol);
+			printf("' getter should have "
+			    "a body.\n");
+			parse_note_error(parse);
+		}
+	} else {
+		/* Body present */
+		lmatch(parse, lc_is);
+		block = parse_block(parse);
+		lmatch(parse, lc_end);
+
+		if (!body_expected) {
+			cspan_print(prop->name->cspan);
+			printf(" Error: Property '");
+			symbol_print_fqn(prop->symbol);
+			printf("' getter declaration should "
+			    "not have a body.\n");
+			parse_note_error(parse);
+
+			/* XXX Free block */
+			block = NULL;
+		}
+	}
+
+	/* Create getter procedure */
+	getter = stree_proc_new();
+	getter->body = block;
+	getter->outer_symbol = prop->symbol;
+
+	/* Store getter in property. */
+	prop->getter = getter;
+}
+
+
+/** Parse member property setter.
+ *
+ * @param parse		Parser object.
+ * @param prop		Property containing this declaration.
+ */
+static void parse_prop_set(parse_t *parse, stree_prop_t *prop)
+{
+	cspan_t *cspan;
+	stree_block_t *block;
+	stree_proc_t *setter;
+	bool_t body_expected;
+
+	body_expected = (prop->symbol->outer_csi->cc != csi_interface);
+
+	lskip(parse);
+	cspan = lprev_span(parse);
+
+	if (prop->setter != NULL) {
+		cspan_print(cspan);
+		printf(" Error: Duplicate setter.\n");
+		parse_note_error(parse);
+		return;
+	}
+
+	prop->setter_arg = stree_proc_arg_new();
+	prop->setter_arg->name = parse_ident(parse);
+	prop->setter_arg->type = prop->type;
+
+	if (lcur_lc(parse) == lc_scolon) {
+		/* Body not present */
+		lskip(parse);
+
+		block = NULL;
+
+		if (body_expected) {
+			cspan_print(prop->name->cspan);
+			printf(" Error: Property '");
+			symbol_print_fqn(prop->symbol);
+			printf("' setter should have "
+			    "a body.\n");
+			parse_note_error(parse);
+		}
+	} else {
+		/* Body present */
+		lmatch(parse, lc_is);
+		block = parse_block(parse);
+		lmatch(parse, lc_end);
+
+		if (!body_expected) {
+			cspan_print(prop->name->cspan);
+			printf(" Error: Property '");
+			symbol_print_fqn(prop->symbol);
+			printf("' setter declaration should "
+			    "not have a body.\n");
+			parse_note_error(parse);
+		}
+	}
+
+
+	/* Create setter procedure */
+	setter = stree_proc_new();
+	setter->body = block;
+	setter->outer_symbol = prop->symbol;
+
+	/* Store setter in property. */
+	prop->setter = setter;
 }
 
Index: uspace/app/sbi/src/program.c
===================================================================
--- uspace/app/sbi/src/program.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/program.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -85,4 +85,9 @@
  * is read from '<libdir>/libflist'. Each line of the file contains one file
  * name relative to <libdir>.
+ *
+ * @param program 	The program to which the parsed code is added.
+ * @return		EOK on success, EIO if some file comprising the
+ *			library is not found, EINVAL if the library
+ *			has syntax errors.
  */
 int program_lib_process(stree_program_t *program)
@@ -147,4 +152,4 @@
 	fclose(f);
 
-	return rc;
+	return EOK;
 }
Index: uspace/app/sbi/src/rdata.c
===================================================================
--- uspace/app/sbi/src/rdata.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/rdata.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -609,5 +609,5 @@
 	(void) src; (void) dest;
 	printf("Unimplemented: Copy object.\n");
-	exit(1);
+	abort();
 }
 
Index: uspace/app/sbi/src/rdata_t.h
===================================================================
--- uspace/app/sbi/src/rdata_t.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/rdata_t.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -71,9 +71,9 @@
  *
  * A delegate variable points to a static or non-static symbol. If the
- * symbol is non static, @c obj points to the object the symbol instance
+ * symbol is non static, @c obj points to the object the symbol
  * belongs to.
  */
 typedef struct {
-	/** Object or @c NULL if deleg. points to a CSI or static member. */
+	/** Object or @c NULL if deleg. points to a static function. */
 	struct rdata_var *obj;
 
@@ -107,4 +107,7 @@
 	/** Class of this object (symbol) */
 	struct stree_symbol *class_sym;
+
+	/** @c sn_static if this is a static object (i.e. class object) */
+	statns_t static_obj;
 
 	/** Map field name SID to field data */
Index: uspace/app/sbi/src/run.c
===================================================================
--- uspace/app/sbi/src/run.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/run.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -99,4 +99,5 @@
 	stree_symbol_t *main_fun_sym;
 	stree_fun_t *main_fun;
+	rdata_var_t *main_obj;
 	stree_ident_t *fake_ident;
 	list_t main_args;
@@ -111,4 +112,7 @@
 	list_init(&run->thread_ar->proc_ar);
 	run->thread_ar->bo_mode = bm_none;
+
+	/* Initialize global data structure. */
+	run_gdata_init(run);
 
 	/*
@@ -126,4 +130,6 @@
 	assert(main_fun != NULL);
 
+	main_obj = run_fun_sobject_find(run, main_fun);
+
 #ifdef DEBUG_RUN_TRACE
 	printf("Found function '"); symbol_print_fqn(main_fun_sym);
@@ -133,9 +139,26 @@
 	/* Run function @c main. */
 	list_init(&main_args);
-	run_proc_ar_create(run, NULL, main_fun->proc, &proc_ar);
+	run_proc_ar_create(run, main_obj, main_fun->proc, &proc_ar);
 	run_proc_ar_set_args(run, proc_ar, &main_args);
 	run_proc(run, proc_ar, &res);
 
 	run_exc_check_unhandled(run);
+}
+
+/** Initialize global data.
+ *
+ * @param run		Runner object
+ */
+void run_gdata_init(run_t *run)
+{
+	rdata_object_t *gobject;
+
+	run->gdata = rdata_var_new(vc_object);
+	gobject = rdata_object_new();
+	run->gdata->u.object_v = gobject;
+
+	gobject->class_sym = NULL;
+	gobject->static_obj = sn_static;
+	intmap_init(&gobject->fields);
 }
 
@@ -787,4 +810,102 @@
 	proc_ar = run_get_current_proc_ar(run);
 	return proc_ar->proc->outer_symbol->outer_csi;
+}
+
+/** Get static object (i.e. class object).
+ *
+ * Looks for a child static object named @a name in static object @a pobject.
+ * If the child does not exist yet, it is created.
+ *
+ * @param run		Runner object
+ * @param csi		CSI of the static object named @a name
+ * @param pobject	Parent static object
+ * @param name		Static object name
+ *
+ * @return		Static (class) object of the given name
+ */
+rdata_var_t *run_sobject_get(run_t *run, stree_csi_t *csi,
+    rdata_var_t *pobj_var, sid_t name)
+{
+	rdata_object_t *pobject;
+	rdata_var_t *mbr_var;
+	rdata_var_t *rvar;
+	stree_ident_t *ident;
+
+	assert(pobj_var->vc == vc_object);
+	pobject = pobj_var->u.object_v;
+#ifdef DEBUG_RUN_TRACE
+	printf("Get static object '%s' in '", strtab_get_str(name));
+	if (pobject->class_sym != NULL)
+		symbol_print_fqn(pobject->class_sym);
+	else
+		printf("global");
+#endif
+
+	assert(pobject->static_obj == sn_static);
+
+	mbr_var = intmap_get(&pobject->fields, name);
+	if (mbr_var != NULL) {
+#ifdef DEBUG_RUN_TRACE
+		printf("Return exising static object (mbr_var=%p).\n", mbr_var);
+#endif
+		/* Return existing object. */
+		return mbr_var;
+	}
+
+	/* Construct new object. */
+#ifdef DEBUG_RUN_TRACE
+	printf("Construct new static object.\n");
+#endif
+	ident = stree_ident_new();
+	ident->sid = name;
+
+	run_new_csi_inst(run, csi, sn_static, &rvar);
+
+	/* Store static object reference for future use. */
+	intmap_set(&pobject->fields, name, rvar);
+
+	return rvar;
+}
+
+/** Get static object for CSI.
+ *
+ * In situations where we do not have the parent static object and need
+ * to find static object for a CSI from the gdata root we use this.
+ *
+ * This is only used in special cases such as when invoking the entry
+ * point. This is too slow to use during normal execution.
+ *
+ * @param run		Runner object
+ * @param csi		CSI to get static object of
+ *
+ * @return		Static (class) object
+ */
+rdata_var_t *run_sobject_find(run_t *run, stree_csi_t *csi)
+{
+	rdata_var_t *pobj_var;
+
+	if (csi == NULL)
+		return run->gdata;
+
+	assert(csi->ancr_state == ws_visited);
+	pobj_var = run_sobject_find(run, csi_to_symbol(csi)->outer_csi);
+
+	return run_sobject_get(run, csi, pobj_var, csi->name->sid);
+}
+
+/** Get static object for CSI containing function.
+ *
+ * This is used to obtain active object for invoking static function
+ * @a fun. Only used in cases where we don't already have the object such
+ * as when running the entry point. Otherwise this would be slow.
+ *
+ * @param run		Runner object
+ * @param fun		Function to get static class object of
+ *
+ * @return		Static (class) object
+ */
+rdata_var_t *run_fun_sobject_find(run_t *run, stree_fun_t *fun)
+{
+	return run_sobject_find(run, fun_to_symbol(fun)->outer_csi);
 }
 
@@ -1512,5 +1633,5 @@
 
 	/* Create exception object. */
-	run_new_csi_inst(run, csi, &exc_vi);
+	run_new_csi_inst_ref(run, csi, sn_nonstatic, &exc_vi);
 	assert(exc_vi->ic == ic_value);
 
Index: uspace/app/sbi/src/run.h
===================================================================
--- uspace/app/sbi/src/run.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/run.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -33,4 +33,5 @@
 
 void run_init(run_t *run);
+void run_gdata_init(run_t *run);
 void run_program(run_t *run, stree_program_t *prog);
 void run_proc(run_t *run, run_proc_ar_t *proc_ar, rdata_item_t **res);
@@ -47,4 +48,9 @@
 run_block_ar_t *run_get_current_block_ar(run_t *run);
 stree_csi_t *run_get_current_csi(run_t *run);
+
+rdata_var_t *run_sobject_get(run_t *run, stree_csi_t *pcsi,
+    rdata_var_t *pobj_var, sid_t name);
+rdata_var_t *run_sobject_find(run_t *run, stree_csi_t *csi);
+rdata_var_t *run_fun_sobject_find(run_t *run, stree_fun_t *fun);
 
 void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var);
Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/run_expr.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -104,4 +104,8 @@
 static void run_access_object(run_t *run, stree_access_t *access,
     rdata_item_t *arg, rdata_item_t **res);
+static void run_access_object_static(run_t *run, stree_access_t *access,
+    rdata_var_t *obj_var, rdata_item_t **res);
+static void run_access_object_nonstatic(run_t *run, stree_access_t *access,
+    rdata_var_t *obj_var, rdata_item_t **res);
 static void run_access_symbol(run_t *run, stree_access_t *access,
     rdata_item_t *arg, rdata_item_t **res);
@@ -207,4 +211,8 @@
 	rdata_var_t *member_var;
 
+	rdata_var_t *psobj;
+	rdata_var_t *sobj;
+	rdata_object_t *aobj;
+
 #ifdef DEBUG_RUN_TRACE
 	printf("Run nameref.\n");
@@ -238,13 +246,16 @@
 	/* Determine currently active object or CSI. */
 	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;
+
+	assert (proc_ar->obj != NULL);
+	assert(proc_ar->obj->vc == vc_object);
+	obj = proc_ar->obj->u.object_v;
+	csi_sym = obj->class_sym;
+
+	if (csi_sym != NULL) {
 		csi = symbol_to_csi(csi_sym);
 		assert(csi != NULL);
 	} else {
-		csi = proc_ar->proc->outer_symbol->outer_csi;
-		obj = NULL;
+		/* This happens in interactive mode. */
+		csi = NULL;
 	}
 
@@ -259,16 +270,11 @@
 		printf("Referencing CSI.\n");
 #endif
-		item = rdata_item_new(ic_value);
-		value = rdata_value_new();
-		var = rdata_var_new(vc_deleg);
-		deleg_v = rdata_deleg_new();
-
-		item->u.value = value;
-		value->var = var;
-		var->u.deleg_v = deleg_v;
-
-		deleg_v->obj = NULL;
-		deleg_v->sym = sym;
-		*res = item;
+		/* Obtain static object for the referenced CSI. */
+		psobj = run->gdata; /* XXX */
+		sobj = run_sobject_get(run, sym->u.csi, psobj,
+		    nameref->name->sid);
+
+		/* Return reference to the object. */
+		run_reference(run, sobj, res);
 		break;
 	case sc_ctor:
@@ -334,9 +340,6 @@
 		assert(csi != NULL);
 
-		/* XXX Assume variable is not static for now. */
-		assert(obj != NULL);
-
 		if (symbol_search_csi(run->program, csi, nameref->name)
-		    == NULL) {
+		    == NULL && !stree_symbol_is_static(sym)) {
 			/* Variable is not in the current object. */
 			printf("Error: Cannot access non-static member "
@@ -349,6 +352,22 @@
 		}
 
+		if (stree_symbol_is_static(sym)) {
+			/*
+			 * XXX This is too slow!
+			 *
+			 * However fixing this is non-trivial. We would
+			 * have to have pointer to static object available
+			 * for each object (therefore also for each object
+			 * type).
+			 */
+			sobj = run_sobject_find(run, sym->outer_csi);
+			assert(sobj->vc == vc_object);
+			aobj = sobj->u.object_v;
+		} else {
+			aobj = obj;
+		}
+
 		/* Find member variable in object. */
-		member_var = intmap_get(&obj->fields, nameref->name->sid);
+		member_var = intmap_get(&aobj->fields, nameref->name->sid);
 		assert(member_var != NULL);
 
@@ -1361,5 +1380,5 @@
 
 	/* Create CSI instance. */
-	run_new_csi_inst(run, csi, res);
+	run_new_csi_inst_ref(run, csi, sn_nonstatic, res);
 
 	/* Run the constructor. */
@@ -1467,5 +1486,5 @@
 }
 
-/** Evaluate delegate-member acccess.
+/** Evaluate delegate member acccess.
  *
  * @param run		Runner object
@@ -1477,41 +1496,11 @@
     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 delegate access operation.\n");
-#endif
-	run_cvt_value_item(run, 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);
-
-	/* Member existence should be ensured by static type checking. */
-	assert(member != NULL);
-
-#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;
+	(void) run;
+	(void) access;
+	(void) arg;
+	(void) res;
+
+	printf("Error: Using '.' with delegate.\n");
+	exit(1);
 }
 
@@ -1526,8 +1515,42 @@
     rdata_item_t *arg, rdata_item_t **res)
 {
+	rdata_var_t *obj_var;
+	rdata_object_t *object;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run object access operation.\n");
+#endif
+	assert(arg->ic == ic_address);
+	assert(arg->u.address->ac == ac_var);
+
+	obj_var = arg->u.address->u.var_a->vref;
+	assert(obj_var->vc == vc_object);
+
+	object = obj_var->u.object_v;
+
+	if (object->static_obj == sn_static)
+		run_access_object_static(run, access, obj_var, res);
+	else
+		run_access_object_nonstatic(run, access, obj_var, res);
+}
+
+/** Evaluate static object member acccess.
+ *
+ * @param run		Runner object
+ * @param access	Access operation
+ * @param arg		Evaluated base expression
+ * @param res		Place to store result
+ */
+static void run_access_object_static(run_t *run, stree_access_t *access,
+    rdata_var_t *obj_var, rdata_item_t **res)
+{
+	rdata_object_t *object;
 	stree_symbol_t *member;
-	rdata_var_t *object_var;
-	rdata_object_t *object;
+	stree_csi_t *member_csi;
+
+	rdata_deleg_t *deleg_v;
 	rdata_item_t *ritem;
+	rdata_value_t *rvalue;
+	rdata_var_t *rvar;
 	rdata_address_t *address;
 	rdata_addr_var_t *addr_var;
@@ -1535,29 +1558,19 @@
 	rdata_aprop_named_t *aprop_named;
 	rdata_deleg_t *deleg_p;
-
-	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.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;
+	rdata_var_t *mvar;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run static object access operation.\n");
+#endif
+	assert(obj_var->vc == vc_object);
+	object = obj_var->u.object_v;
+
+	assert(object->static_obj == sn_static);
 
 	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(object->class_sym);
-		printf("' has no member named '%s'.\n",
-		    strtab_get_str(access->member_name->sid));
-		exit(1);
-	}
+	/* Member existence should be ensured by static type checking. */
+	assert(member != NULL);
 
 #ifdef DEBUG_RUN_TRACE
@@ -1566,11 +1579,26 @@
 #endif
 
-	/* Make compiler happy. */
-	ritem = NULL;
-
 	switch (member->sc) {
 	case sc_csi:
-		printf("Error: Accessing object member which is nested CSI.\n");
-		exit(1);
+		/* Get child static object. */
+		member_csi = symbol_to_csi(member);
+		assert(member_csi != NULL);
+
+		mvar = run_sobject_get(run, member_csi, obj_var,
+		    access->member_name->sid);
+
+		ritem = rdata_item_new(ic_address);
+		address = rdata_address_new(ac_var);
+		ritem->u.address = address;
+
+		addr_var = rdata_addr_var_new();
+		address->u.var_a = addr_var;
+		addr_var->vref = mvar;
+
+		*res = ritem;
+		break;
+	case sc_ctor:
+		/* It is not possible to reference a constructor explicitly. */
+		assert(b_false);
 	case sc_deleg:
 		printf("Error: Accessing object member which is a delegate.\n");
@@ -1579,32 +1607,33 @@
 		printf("Error: Accessing object member which is an enum.\n");
 		exit(1);
-	case sc_ctor:
-		/* It is not possible to reference a constructor explicitly. */
-		assert(b_false);
 	case sc_fun:
 		/* Construct anonymous delegate. */
 		ritem = rdata_item_new(ic_value);
-		value = rdata_value_new();
-		ritem->u.value = value;
-
-		var = rdata_var_new(vc_deleg);
-		value->var = var;
+		rvalue = rdata_value_new();
+		ritem->u.value = rvalue;
+
+		rvar = rdata_var_new(vc_deleg);
+		rvalue->var = rvar;
+
 		deleg_v = rdata_deleg_new();
-		var->u.deleg_v = deleg_v;
-
-		deleg_v->obj = arg->u.address->u.var_a->vref;
+		rvar->u.deleg_v = deleg_v;
+
+		deleg_v->obj = obj_var;
 		deleg_v->sym = member;
+		*res = ritem;
 		break;
 	case sc_var:
-		/* Construct variable address item. */
+		/* Get static object member variable. */
+		mvar = intmap_get(&object->fields, access->member_name->sid);
+
 		ritem = rdata_item_new(ic_address);
 		address = rdata_address_new(ac_var);
+		ritem->u.address = address;
+
 		addr_var = rdata_addr_var_new();
-		ritem->u.address = address;
 		address->u.var_a = addr_var;
-
-		addr_var->vref = intmap_get(&object->fields,
-		    access->member_name->sid);
-		assert(addr_var->vref != NULL);
+		addr_var->vref = mvar;
+
+		*res = ritem;
 		break;
 	case sc_prop:
@@ -1619,5 +1648,114 @@
 
 		deleg_p = rdata_deleg_new();
-		deleg_p->obj = object_var;
+		deleg_p->obj = obj_var;
+		deleg_p->sym = member;
+		addr_prop->u.named->prop_d = deleg_p;
+
+		*res = ritem;
+		break;
+	}
+}
+
+/** Evaluate object member acccess.
+ *
+ * @param run		Runner object
+ * @param access	Access operation
+ * @param arg		Evaluated base expression
+ * @param res		Place to store result
+ */
+static void run_access_object_nonstatic(run_t *run, stree_access_t *access,
+    rdata_var_t *obj_var, rdata_item_t **res)
+{
+	rdata_object_t *object;
+	stree_symbol_t *member;
+	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;
+	rdata_deleg_t *deleg_v;
+	rdata_var_t *var;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run nonstatic object access operation.\n");
+#endif
+	assert(obj_var->vc == vc_object);
+	object = obj_var->u.object_v;
+
+	assert(object->static_obj == sn_nonstatic);
+
+	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(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
+
+	/* Make compiler happy. */
+	ritem = NULL;
+
+	switch (member->sc) {
+	case sc_csi:
+		printf("Error: Accessing object member which is nested CSI.\n");
+		exit(1);
+	case sc_ctor:
+		/* It is not possible to reference a constructor explicitly. */
+		assert(b_false);
+	case sc_deleg:
+		printf("Error: Accessing object member which is a delegate.\n");
+		exit(1);
+	case sc_enum:
+		printf("Error: Accessing object member which is an enum.\n");
+		exit(1);
+	case sc_fun:
+		/* Construct anonymous 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 = obj_var;
+		deleg_v->sym = member;
+		break;
+	case sc_var:
+		/* Construct variable address item. */
+		ritem = rdata_item_new(ic_address);
+		address = rdata_address_new(ac_var);
+		addr_var = rdata_addr_var_new();
+		ritem->u.address = address;
+		address->u.var_a = addr_var;
+
+		addr_var->vref = intmap_get(&object->fields,
+		    access->member_name->sid);
+		assert(addr_var->vref != NULL);
+		break;
+	case sc_prop:
+		/* 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 = obj_var;
 		deleg_p->sym = member;
 		addr_prop->u.named->prop_d = deleg_p;
@@ -2168,5 +2306,4 @@
 	rdata_item_t *rdest_i, *rsrc_i;
 	rdata_item_t *rsrc_vi;
-	rdata_value_t *src_val;
 
 #ifdef DEBUG_RUN_TRACE
@@ -2187,5 +2324,4 @@
 	run_cvt_value_item(run, rsrc_i, &rsrc_vi);
 	assert(rsrc_vi->ic == ic_value);
-	src_val = rsrc_vi->u.value;
 
 	if (rdest_i->ic != ic_address) {
@@ -2331,5 +2467,5 @@
 
 	/* Construct object of the relevant boxed type. */
-	run_new_csi_inst(run, csi, res);
+	run_new_csi_inst_ref(run, csi, sn_nonstatic, res);
 
 	/* Set the 'Value' field */
@@ -2348,5 +2484,5 @@
 }
 
-/** Create new CSI instance.
+/** Create new CSI instance and return reference to it.
  *
  * Create a new object, instance of @a csi.
@@ -2357,9 +2493,47 @@
  * run any constructor.
  *
- * @param run		Runner object
- * @param as_op		@c as conversion expression
- * @param res		Place to store result
- */
-void run_new_csi_inst(run_t *run, stree_csi_t *csi, rdata_item_t **res)
+ * If @a sn is @c sn_nonstatic a regular object is created, containing all
+ * non-static member variables. If @a sn is @c sn_static a static object
+ * is created, containing all static member variables.
+ *
+ * @param run		Runner object
+ * @param csi		CSI to create instance of
+ * @param sn		@c sn_static to create a static (class) object,
+ *			@c sn_nonstatic to create a regular object
+ * @param res		Place to store result
+ */
+void run_new_csi_inst_ref(run_t *run, stree_csi_t *csi, statns_t sn,
+    rdata_item_t **res)
+{
+	rdata_var_t *obj_var;
+
+	/* Create object. */
+	run_new_csi_inst(run, csi, sn, &obj_var);
+
+	/* Create reference to the new object. */
+	run_reference(run, obj_var, res);
+}
+
+/** Create new CSI instance.
+ *
+ * Create a new object, instance of @a csi.
+ * XXX This does not work with generics as @a csi cannot specify a generic
+ * type.
+ *
+ * Initialize the fields with default values of their types, but do not
+ * run any constructor.
+ *
+ * If @a sn is @c sn_nonstatic a regular object is created, containing all
+ * non-static member variables. If @a sn is @c sn_static a static object
+ * is created, containing all static member variables.
+ *
+ * @param run		Runner object
+ * @param csi		CSI to create instance of
+ * @param sn		@c sn_static to create a static (class) object,
+ *			@c sn_nonstatic to create a regular object
+ * @param res		Place to store result
+ */
+void run_new_csi_inst(run_t *run, stree_csi_t *csi, statns_t sn,
+    rdata_var_t **res)
 {
 	rdata_object_t *obj;
@@ -2368,4 +2542,6 @@
 	stree_symbol_t *csi_sym;
 	stree_csimbr_t *csimbr;
+	stree_var_t *var;
+	statns_t var_sn;
 
 	rdata_var_t *mbr_var;
@@ -2384,4 +2560,5 @@
 	obj = rdata_object_new();
 	obj->class_sym = csi_sym;
+	obj->static_obj = sn;
 	intmap_init(&obj->fields);
 
@@ -2389,22 +2566,31 @@
 	obj_var->u.object_v = obj;
 
-	/* Create object fields. */
+	/* For this CSI and all base CSIs */
 	while (csi != NULL) {
+
+		/* For all members */
 		node = list_first(&csi->members);
 		while (node != NULL) {
 			csimbr = list_node_data(node, stree_csimbr_t *);
+
+			/* Is it a member variable? */
 			if (csimbr->cc == csimbr_var) {
-				/* Compute field type. XXX Memoize. */
-				run_texpr(run->program, csi,
-				    csimbr->u.var->type,
-				    &field_ti);
-
-				/* Create and initialize field. */
-				run_var_new(run, field_ti, &mbr_var);
-
-				/* Add to field map. */
-				intmap_set(&obj->fields,
-				    csimbr->u.var->name->sid,
-				    mbr_var);
+				var = csimbr->u.var;
+
+				/* Is it static/nonstatic? */
+				var_sn = stree_symbol_has_attr(
+				    var_to_symbol(var), sac_static);
+				if (var_sn == sn) {
+					/* Compute field type. XXX Memoize. */
+					run_texpr(run->program, csi, var->type,
+					    &field_ti);
+
+					/* Create and initialize field. */
+					run_var_new(run, field_ti, &mbr_var);
+
+					/* Add to field map. */
+					intmap_set(&obj->fields, var->name->sid,
+					    mbr_var);
+				}
 			}
 
@@ -2416,6 +2602,5 @@
 	}
 
-	/* Create reference to the new object. */
-	run_reference(run, obj_var, res);
+	*res = obj_var;
 }
 
Index: uspace/app/sbi/src/run_expr.h
===================================================================
--- uspace/app/sbi/src/run_expr.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/run_expr.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -34,5 +34,9 @@
 void run_expr(run_t *run, stree_expr_t *expr, rdata_item_t **res);
 
-void run_new_csi_inst(run_t *run, stree_csi_t *csi, rdata_item_t **res);
+void run_new_csi_inst_ref(run_t *run, stree_csi_t *csi, statns_t sn,
+    rdata_item_t **res);
+void run_new_csi_inst(run_t *run, stree_csi_t *csi, statns_t sn,
+    rdata_var_t **res);
+
 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 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/run_t.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -114,4 +114,7 @@
 	/** Thread-private state */
 	run_thread_ar_t *thread_ar;
+
+	/** Global state */
+	struct rdata_var *gdata;
 } run_t;
 
Index: uspace/app/sbi/src/run_texpr.c
===================================================================
--- uspace/app/sbi/src/run_texpr.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/run_texpr.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -140,4 +140,7 @@
 	}
 
+	/* Make compiler happy. */
+	titem = NULL;
+
 	switch (sym->sc) {
 	case sc_csi:
@@ -147,5 +150,5 @@
 		titem->u.tobject = tobject;
 
-		tobject->static_ref = b_false;
+		tobject->static_ref = sn_nonstatic;
 		tobject->csi = sym->u.csi;
 		list_init(&tobject->targs);
@@ -278,4 +281,7 @@
 	(void) tliteral;
 
+	/* Make compiler happy. */
+	tpc = 0;
+
 	switch (tliteral->tlc) {
 	case tlc_bool: tpc = tpc_bool; break;
@@ -342,4 +348,7 @@
 	}
 
+	/* Make compiler happy. */
+	titem = NULL;
+
 	switch (sym->sc) {
 	case sc_csi:
@@ -349,5 +358,5 @@
 		titem->u.tobject = tobject;
 
-		tobject->static_ref = b_false;
+		tobject->static_ref = sn_nonstatic;
 		tobject->csi = sym->u.csi;
 		list_init(&tobject->targs);
@@ -429,5 +438,4 @@
 
 	list_node_t *farg_n;
-	stree_targ_t *farg;
 
 #ifdef DEBUG_RUN_TRACE
@@ -450,5 +458,5 @@
 	}
 
-	tobject->static_ref = b_false;
+	tobject->static_ref = sn_nonstatic;
 	tobject->csi = base_ti->u.tobject->csi;
 	list_init(&tobject->targs);
@@ -458,5 +466,4 @@
 	arg_n = list_first(&tapply->targs);
 	while (farg_n != NULL && arg_n != NULL) {
-		farg = list_node_data(farg_n, stree_targ_t *);
 		arg = list_node_data(arg_n, stree_texpr_t *);
 
Index: uspace/app/sbi/src/stree.c
===================================================================
--- uspace/app/sbi/src/stree.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/stree.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -92,6 +92,9 @@
 	csi->ancr_state = ws_unvisited;
 	csi->name = NULL;
-	csi->base_csi_ref = NULL;
+	csi->base_csi = NULL;
+	list_init(&csi->inherit);
+	list_init(&csi->impl_if_ti);
 	list_init(&csi->members);
+
 	return csi;
 }
@@ -930,4 +933,6 @@
 
 	symbol->sc = sc;
+	list_init(&symbol->attr);
+
 	return symbol;
 }
@@ -1018,4 +1023,34 @@
 
 	/* We went all the way to the root and did not find b. */
+	return b_false;
+}
+
+/** Determine if @a symbol is static.
+ *
+ * @param symbol	Symbol
+ * @return		@c b_true if symbol is static, @c b_false otherwise
+ */
+bool_t stree_symbol_is_static(stree_symbol_t *symbol)
+{
+	/* Module-wide symbols are static. */
+	if (symbol->outer_csi == NULL)
+		return b_true;
+
+	/* Symbols with @c static attribute are static. */
+	if (stree_symbol_has_attr(symbol, sac_static))
+		return b_true;
+
+	switch (symbol->sc) {
+	case sc_csi:
+	case sc_deleg:
+	case sc_enum:
+		return b_true;
+	case sc_ctor:
+	case sc_fun:
+	case sc_var:
+	case sc_prop:
+		break;
+	}
+
 	return b_false;
 }
Index: uspace/app/sbi/src/stree.h
===================================================================
--- uspace/app/sbi/src/stree.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/stree.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -96,4 +96,5 @@
 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);
+bool_t stree_symbol_is_static(stree_symbol_t *symbol);
 stree_targ_t *stree_csi_find_targ(stree_csi_t *csi, stree_ident_t *ident);
 stree_embr_t *stree_enum_find_mbr(stree_enum_t *enum_d, stree_ident_t *ident);
Index: uspace/app/sbi/src/stree_t.h
===================================================================
--- uspace/app/sbi/src/stree_t.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/stree_t.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -639,4 +639,7 @@
 	/** Variadic argument or @c NULL if none. */
 	stree_proc_arg_t *varg;
+
+	/** Type of the property */
+	struct tdata_item *titem;
 } stree_prop_t;
 
@@ -698,9 +701,12 @@
 	struct stree_symbol *symbol;
 
-	/** Type expression referencing base CSI. */
-	stree_texpr_t *base_csi_ref;
+	/** Type expressions referencing inherited CSIs. */
+	list_t inherit; /* of stree_texpr_t */
 
 	/** Base CSI. Only available when ancr_state == ws_visited. */
 	struct stree_csi *base_csi;
+
+	/** Types of implemented or accumulated interfaces. */
+	list_t impl_if_ti; /* of tdata_item_t */
 
 	/** Node state for ancr walks. */
@@ -736,5 +742,8 @@
 typedef enum {
 	/** Builtin symbol (interpreter hook) */
-	sac_builtin
+	sac_builtin,
+
+	/** Static symbol */
+	sac_static
 } symbol_attr_class_t;
 
Index: uspace/app/sbi/src/stype.c
===================================================================
--- uspace/app/sbi/src/stype.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/stype.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -63,4 +63,14 @@
 static void stype_fun_body(stype_t *stype, stree_fun_t *fun);
 static void stype_block(stype_t *stype, stree_block_t *block);
+
+static void stype_class_impl_check(stype_t *stype, stree_csi_t *csi);
+static void stype_class_impl_check_if(stype_t *stype, stree_csi_t *csi,
+    tdata_item_t *iface_ti);
+static void stype_class_impl_check_mbr(stype_t *stype, stree_csi_t *csi,
+    tdata_tvv_t *if_tvv, stree_csimbr_t *ifmbr);
+static void stype_class_impl_check_fun(stype_t *stype,
+    stree_symbol_t *cfun_sym, tdata_tvv_t *if_tvv, stree_symbol_t *ifun_sym);
+static void stype_class_impl_check_prop(stype_t *stype,
+    stree_symbol_t *cprop_sym, tdata_tvv_t *if_tvv, stree_symbol_t *iprop_sym);
 
 static void stype_vdecl(stype_t *stype, stree_vdecl_t *vdecl_s);
@@ -90,6 +100,4 @@
 static stree_expr_t *stype_convert_tvref(stype_t *stype, stree_expr_t *expr,
     tdata_item_t *dest);
-static void stype_convert_failure(stype_t *stype, stree_expr_t *expr,
-    tdata_item_t *dest);
 
 static bool_t stype_fun_sig_equal(stype_t *stype, tdata_fun_sig_t *asig,
@@ -168,4 +176,7 @@
 	}
 
+	if (csi->cc == csi_class)
+		stype_class_impl_check(stype, csi);
+
 	stype->current_csi = prev_ctx;
 }
@@ -310,6 +321,4 @@
 
 		enum_d->titem = titem;
-	} else {
-		titem = enum_d->titem;
 	}
 }
@@ -453,5 +462,5 @@
 	assert(stype->proc_vr == NULL);
 
-	/* Builtin functions do not have a body. */
+	/* Declarations and builtin functions do not have a body. */
 	if (fun->proc->body == NULL)
 		return;
@@ -475,7 +484,4 @@
 {
 	tdata_item_t *titem;
-
-	(void) stype;
-	(void) var;
 
 	run_texpr(stype->program, stype->current_csi, var->type,
@@ -484,5 +490,4 @@
 		/* An error occured. */
 		stype_note_error(stype);
-		return;
 	}
 }
@@ -500,13 +505,18 @@
 	printf("'.\n");
 #endif
+	if (prop->titem == NULL)
+		stype_prop_header(stype, prop);
+
 	stype->proc_vr = stype_proc_vr_new();
 	list_init(&stype->proc_vr->block_vr);
 
-	if (prop->getter != NULL) {
+	/* Property declarations do not have a getter body. */
+	if (prop->getter != NULL && prop->getter->body != NULL) {
 		stype->proc_vr->proc = prop->getter;
 		stype_block(stype, prop->getter->body);
 	}
 
-	if (prop->setter != NULL) {
+	/* Property declarations do not have a setter body. */
+	if (prop->setter != NULL && prop->setter->body != NULL) {
 		stype->proc_vr->proc = prop->setter;
 		stype_block(stype, prop->setter->body);
@@ -515,4 +525,29 @@
 	free(stype->proc_vr);
 	stype->proc_vr = NULL;
+}
+
+/** Type property header.
+ *
+ * @param stype		Static typing object
+ * @param prop		Property
+ */
+void stype_prop_header(stype_t *stype, stree_prop_t *prop)
+{
+	tdata_item_t *titem;
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Type property '");
+	symbol_print_fqn(prop_to_symbol(prop));
+	printf("' header.\n");
+#endif
+	run_texpr(stype->program, stype->current_csi, prop->type,
+	    &titem);
+	if (titem->tic == tic_ignore) {
+		/* An error occured. */
+		stype_note_error(stype);
+		return;
+	}
+
+	prop->titem = titem;
 }
 
@@ -552,4 +587,286 @@
 	assert(list_node_data(bvr_n, stype_block_vr_t *) == block_vr);
 	list_remove(&stype->proc_vr->block_vr, bvr_n);
+}
+
+/** Verify that class fully implements all interfaces as it claims.
+ *
+ * @param stype		Static typing object
+ * @param csi		CSI to check
+ */
+static void stype_class_impl_check(stype_t *stype, stree_csi_t *csi)
+{
+	list_node_t *pred_n;
+	stree_texpr_t *pred_te;
+	tdata_item_t *pred_ti;
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Verify that class implements all interfaces.\n");
+#endif
+	assert(csi->cc == csi_class);
+
+	pred_n = list_first(&csi->inherit);
+	while (pred_n != NULL) {
+		pred_te = list_node_data(pred_n, stree_texpr_t *);
+		run_texpr(stype->program, csi, pred_te, &pred_ti);
+
+		assert(pred_ti->tic == tic_tobject);
+		switch (pred_ti->u.tobject->csi->cc) {
+		case csi_class:
+			break;
+		case csi_struct:
+			assert(b_false);
+		case csi_interface:
+			/* Store to impl_if_ti for later use. */
+			list_append(&csi->impl_if_ti, pred_ti);
+
+			/* Check implementation of this interface. */
+			stype_class_impl_check_if(stype, csi, pred_ti);
+			break;
+		}
+
+		pred_n = list_next(&csi->inherit, pred_n);
+	}
+}
+
+/** Verify that class fully implements an interface.
+ *
+ * @param stype		Static typing object
+ * @param csi		CSI to check
+ * @param iface		Interface that must be fully implemented
+ */
+static void stype_class_impl_check_if(stype_t *stype, stree_csi_t *csi,
+    tdata_item_t *iface_ti)
+{
+	tdata_tvv_t *iface_tvv;
+	list_node_t *pred_n;
+	tdata_item_t *pred_ti;
+	tdata_item_t *pred_sti;
+
+	stree_csi_t *iface;
+	list_node_t *ifmbr_n;
+	stree_csimbr_t *ifmbr;
+
+	assert(csi->cc == csi_class);
+
+	assert(iface_ti->tic == tic_tobject);
+	iface = iface_ti->u.tobject->csi;
+	assert(iface->cc = csi_interface);
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Verify that class fully implements interface.\n");
+#endif
+	/* Compute TVV for this interface reference. */
+	stype_titem_to_tvv(stype, iface_ti, &iface_tvv);
+
+	/*
+	 * Recurse to accumulated interfaces.
+	 */
+	pred_n = list_first(&iface->impl_if_ti);
+	while (pred_n != NULL) {
+		pred_ti = list_node_data(pred_n, tdata_item_t *);
+		assert(pred_ti->tic == tic_tobject);
+		assert(pred_ti->u.tobject->csi->cc == csi_interface);
+
+		/* Substitute real type parameters to predecessor reference. */
+		tdata_item_subst(pred_ti, iface_tvv, &pred_sti);
+
+		/* Check accumulated interface. */
+		stype_class_impl_check_if(stype, csi, pred_sti);
+
+		pred_n = list_next(&iface->impl_if_ti, pred_n);
+	}
+
+	/*
+	 * Check all interface members.
+	 */
+	ifmbr_n = list_first(&iface->members);
+	while (ifmbr_n != NULL) {
+		ifmbr = list_node_data(ifmbr_n, stree_csimbr_t *);
+		stype_class_impl_check_mbr(stype, csi, iface_tvv, ifmbr);
+
+		ifmbr_n = list_next(&iface->members, ifmbr_n);
+	}
+}
+
+/** Verify that class fully implements an interface member.
+ *
+ * @param stype		Static typing object
+ * @param csi		CSI to check
+ * @param if_tvv	TVV for @a ifmbr
+ * @param ifmbr		Interface that must be fully implemented
+ */
+static void stype_class_impl_check_mbr(stype_t *stype, stree_csi_t *csi,
+    tdata_tvv_t *if_tvv, stree_csimbr_t *ifmbr)
+{
+	stree_symbol_t *cmbr_sym;
+	stree_symbol_t *ifmbr_sym;
+	stree_ident_t *ifmbr_name;
+
+	assert(csi->cc == csi_class);
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Verify that class implements interface member.\n");
+#endif
+	ifmbr_name = stree_csimbr_get_name(ifmbr);
+
+	cmbr_sym = symbol_search_csi(stype->program, csi, ifmbr_name);
+	if (cmbr_sym == NULL) {
+		printf("Error: CSI '");
+		symbol_print_fqn(csi_to_symbol(csi));
+		printf("' should implement '");
+		symbol_print_fqn(csimbr_to_symbol(ifmbr));
+		printf("' but it does not.\n");
+		stype_note_error(stype);
+		return;
+	}
+
+	ifmbr_sym = csimbr_to_symbol(ifmbr);
+	if (cmbr_sym->sc != ifmbr_sym->sc) {
+		printf("Error: CSI '");
+		symbol_print_fqn(csi_to_symbol(csi));
+		printf("' implements '");
+		symbol_print_fqn(csimbr_to_symbol(ifmbr));
+		printf("' as a different kind of symbol.\n");
+		stype_note_error(stype);
+	}
+
+	switch (cmbr_sym->sc) {
+	case sc_csi:
+	case sc_ctor:
+	case sc_deleg:
+	case sc_enum:
+		/*
+		 * Checked at parse time. Interface should not have these
+		 * member types.
+		 */
+		assert(b_false);
+	case sc_fun:
+		stype_class_impl_check_fun(stype, cmbr_sym, if_tvv, ifmbr_sym);
+		break;
+	case sc_var:
+		/*
+		 * Checked at parse time. Interface should not have these
+		 * member types.
+		 */
+		assert(b_false);
+	case sc_prop:
+		stype_class_impl_check_prop(stype, cmbr_sym, if_tvv, ifmbr_sym);
+		break;
+	}
+}
+
+/** Verify that class properly implements a function from an interface.
+ *
+ * @param stype		Static typing object
+ * @param cfun_sym	Function symbol in class
+ * @param if_tvv	TVV for @a ifun_sym
+ * @param ifun_sym	Function declaration symbol in interface
+ */
+static void stype_class_impl_check_fun(stype_t *stype,
+    stree_symbol_t *cfun_sym, tdata_tvv_t *if_tvv, stree_symbol_t *ifun_sym)
+{
+	stree_fun_t *cfun;
+	tdata_fun_t *tcfun;
+	stree_fun_t *ifun;
+	tdata_item_t *sifun_ti;
+	tdata_fun_t *tifun;
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Verify that class '");
+	symbol_print_fqn(csi_to_symbol(cfun_sym->outer_csi));
+	printf("' implements function '");
+	symbol_print_fqn(ifun_sym);
+	printf("' properly.\n");
+#endif
+	assert(cfun_sym->sc == sc_fun);
+	cfun = cfun_sym->u.fun;
+
+	assert(ifun_sym->sc == sc_fun);
+	ifun = ifun_sym->u.fun;
+
+	assert(cfun->titem->tic == tic_tfun);
+	tcfun = cfun->titem->u.tfun;
+
+	tdata_item_subst(ifun->titem, if_tvv, &sifun_ti);
+	assert(sifun_ti->tic == tic_tfun);
+	tifun = sifun_ti->u.tfun;
+
+	if (!stype_fun_sig_equal(stype, tcfun->tsig, tifun->tsig)) {
+		cspan_print(cfun->name->cspan);
+		printf(" Error: Type of function '");
+		symbol_print_fqn(cfun_sym);
+		printf("' (");
+		tdata_item_print(cfun->titem);
+		printf(") does not match type of '");
+		symbol_print_fqn(ifun_sym);
+		printf("' (");
+		tdata_item_print(sifun_ti);
+		printf(") which it should implement.\n");
+		stype_note_error(stype);
+	}
+}
+
+/** Verify that class properly implements a function from an interface.
+ *
+ * @param stype		Static typing object
+ * @param cprop_sym	Property symbol in class
+ * @param if_tvv	TVV for @a ifun_sym
+ * @param iprop_sym	Property declaration symbol in interface
+ */
+static void stype_class_impl_check_prop(stype_t *stype,
+    stree_symbol_t *cprop_sym, tdata_tvv_t *if_tvv, stree_symbol_t *iprop_sym)
+{
+	stree_prop_t *cprop;
+	stree_prop_t *iprop;
+	tdata_item_t *siprop_ti;
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Verify that class '");
+	symbol_print_fqn(csi_to_symbol(cprop_sym->outer_csi));
+	printf("' implements property '");
+	symbol_print_fqn(iprop_sym);
+	printf("' properly.\n");
+#endif
+	assert(cprop_sym->sc == sc_prop);
+	cprop = cprop_sym->u.prop;
+
+	assert(iprop_sym->sc == sc_prop);
+	iprop = iprop_sym->u.prop;
+
+	tdata_item_subst(iprop->titem, if_tvv, &siprop_ti);
+
+	if (!tdata_item_equal(cprop->titem, siprop_ti)) {
+		cspan_print(cprop->name->cspan);
+		printf(" Error: Type of property '");
+		symbol_print_fqn(cprop_sym);
+		printf("' (");
+		tdata_item_print(cprop->titem);
+		printf(") does not match type of '");
+		symbol_print_fqn(iprop_sym);
+		printf("' (");
+		tdata_item_print(siprop_ti);
+		printf(") which it should implement.\n");
+		stype_note_error(stype);
+	}
+
+	if (iprop->getter != NULL && cprop->getter == NULL) {
+		cspan_print(cprop->name->cspan);
+		printf(" Error: Property '");
+		symbol_print_fqn(cprop_sym);
+		printf("' is missing a getter, which is required by '");
+		symbol_print_fqn(iprop_sym);
+		printf("'.\n");
+		stype_note_error(stype);
+	}
+
+	if (iprop->setter != NULL && cprop->setter == NULL) {
+		cspan_print(cprop->name->cspan);
+		printf(" Error: Property '");
+		symbol_print_fqn(cprop_sym);
+		printf("' is missing a setter, which is required by '");
+		symbol_print_fqn(iprop_sym);
+		printf("'.\n");
+		stype_note_error(stype);
+	}
 }
 
@@ -824,6 +1141,8 @@
 	stype_expr(stype, exp_s->expr);
 
-	if (want_value == b_false && exp_s->expr->titem != NULL)
-		printf("Warning: Expression value ignored.\n");
+	if (want_value == b_false && exp_s->expr->titem != NULL) {
+		cspan_print(exp_s->expr->cspan);
+		printf(" Warning: Expression value ignored.\n");
+	}
 }
 
@@ -925,5 +1244,5 @@
 
 	if (src->tic == tic_tebase) {
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		printf("Invalid use of reference to enum type in "
 		    "expression.\n");
@@ -932,5 +1251,5 @@
 
 	if (src->tic != dest->tic) {
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		return expr;
 	}
@@ -987,5 +1306,5 @@
 	/* Check if both have the same tprimitive class. */
 	if (src->u.tprimitive->tpc != dest->u.tprimitive->tpc)
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 
 	return expr;
@@ -1020,4 +1339,7 @@
 	bi = stype->program->builtin;
 	csi_sym = csi_to_symbol(dest->u.tobject->csi);
+
+	/* Make compiler happy. */
+	bp_sym = NULL;
 
 	switch (src->u.tprimitive->tpc) {
@@ -1028,5 +1350,5 @@
 	case tpc_string: bp_sym = bi->boxed_string; break;
 	case tpc_resource:
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		return expr;
 	}
@@ -1034,5 +1356,5 @@
 	/* Target type must be boxed @a src or Object */
 	if (csi_sym != bp_sym && csi_sym != bi->gf_class)
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 
 	/* Patch the code to box the primitive value */
@@ -1058,80 +1380,31 @@
 {
 	tdata_item_t *src;
-	tdata_item_t *cur;
-	stree_csi_t *cur_csi;
-	tdata_tvv_t *tvv;
-	tdata_item_t *b_ti, *bs_ti;
+	tdata_item_t *pred_ti;
 
 #ifdef DEBUG_TYPE_TRACE
 	printf("Convert object type.\n");
 #endif
-	list_node_t *ca_n, *da_n;
-	tdata_item_t *carg, *darg;
-
 	src = expr->titem;
 	assert(src->tic == tic_tobject);
 	assert(dest->tic == tic_tobject);
 
-	cur = src;
-
-	while (cur->u.tobject->csi != dest->u.tobject->csi) {
-
-		cur_csi = cur->u.tobject->csi;
-		stype_titem_to_tvv(stype, cur, &tvv);
-
-		if (cur_csi->base_csi_ref != NULL) {
-			run_texpr(stype->program, cur_csi, cur_csi->base_csi_ref, &b_ti);
-			if (b_ti->tic == tic_ignore) {
-				/* An error occured. */
-				stype_note_error(stype);
-				return expr;
-			}
-
-			tdata_item_subst(b_ti, tvv, &bs_ti);
-			cur = bs_ti;
-			assert(cur->tic == tic_tobject);
-
-		} else if (cur_csi->base_csi != NULL) {
-			/* No explicit reference. Use grandfather class. */
-			cur = tdata_item_new(tic_tobject);
-			cur->u.tobject = tdata_object_new();
-			cur->u.tobject->csi = cur_csi->base_csi;
-			cur->u.tobject->static_ref = b_false;
-
-			list_init(&cur->u.tobject->targs);
-		} else {
-			/* No match */
-			stype_convert_failure(stype, expr, dest);
-			return expr;
-		}
-	}
-
-	/* Verify that type arguments match */
-	ca_n = list_first(&cur->u.tobject->targs);
-	da_n = list_first(&dest->u.tobject->targs);
-
-	while (ca_n != NULL && da_n != NULL) {
-		carg = list_node_data(ca_n, tdata_item_t *);
-		darg = list_node_data(da_n, tdata_item_t *);
-
-		if (tdata_item_equal(carg, darg) != b_true) {
-			/* Diferent argument type */
-			stype_convert_failure(stype, expr, dest);
-			printf("Different argument type '");
-			tdata_item_print(carg);
-			printf("' vs. '");
-			tdata_item_print(darg);
-			printf("'.\n");
-			return expr;
-		}
-
-		ca_n = list_next(&cur->u.tobject->targs, ca_n);
-		da_n = list_next(&dest->u.tobject->targs, da_n);
-	}
-
-	if (ca_n != NULL || da_n != NULL) {
-		/* Diferent number of arguments */
-		stype_convert_failure(stype, expr, dest);
-		printf("Different number of arguments.\n");
+	/*
+	 * Find predecessor of the right type. This determines the
+	 * type arguments that the destination type should have.
+	 */
+	pred_ti = stype_tobject_find_pred(stype, src, dest);
+	if (pred_ti == NULL) {
+		stype_convert_failure(stype, convc_implicit, expr, dest);
+		printf("Not a base class or implemented or accumulated "
+		    "interface.\n");
+		return expr;
+	}
+
+	/*
+	 * Verify that type arguments match with those specified for
+	 * conversion destination.
+	 */
+	if (stype_targs_check_equal(stype, pred_ti, dest) != EOK) {
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		return expr;
 	}
@@ -1160,5 +1433,5 @@
 	/* Compare rank and base type. */
 	if (src->u.tarray->rank != dest->u.tarray->rank) {
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		return expr;
 	}
@@ -1167,5 +1440,5 @@
 	if (tdata_item_equal(src->u.tarray->base_ti,
 	    dest->u.tarray->base_ti) != b_true) {
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 	}
 
@@ -1205,5 +1478,5 @@
 	/* Both must be the same delegate. */
 	if (sdeleg->deleg != ddeleg->deleg) {
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		return expr;
 	}
@@ -1240,5 +1513,5 @@
 	/* Both must be of the same enum type (with the same declaration). */
 	if (senum->enum_d != denum->enum_d) {
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		return expr;
 	}
@@ -1279,5 +1552,5 @@
 
 	if (!stype_fun_sig_equal(stype, ssig, dsig)) {
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		return expr;
 	}
@@ -1311,5 +1584,5 @@
 	/* Currently only allow if both types are the same. */
 	if (src->u.tvref->targ != dest->u.tvref->targ) {
-		stype_convert_failure(stype, expr, dest);
+		stype_convert_failure(stype, convc_implicit, expr, dest);
 		return expr;
 	}
@@ -1324,9 +1597,14 @@
  * @param dest		Destination type
  */
-static void stype_convert_failure(stype_t *stype, stree_expr_t *expr,
-    tdata_item_t *dest)
+void stype_convert_failure(stype_t *stype, stype_conv_class_t convc,
+    stree_expr_t *expr, tdata_item_t *dest)
 {
 	cspan_print(expr->cspan);
-	printf(" Error: Cannot convert ");
+	printf(" Error: ");
+	switch (convc) {
+	case convc_implicit: printf("Cannot implicitly convert '"); break;
+	case convc_as: printf("Cannot use 'as' to convert '"); break;
+	}
+
 	tdata_item_print(expr->titem);
 	printf(" to ");
@@ -1397,4 +1675,166 @@
 }
 
+/** Find predecessor CSI and return its type item.
+ *
+ * Looks for predecessor of CSI type @a src that matches @a dest.
+ * The type maches if they use the same generic CSI definition, type
+ * arguments are ignored. If found, returns the type arguments that
+ * @a dest should have in order to be a true predecessor of @a src.
+ *
+ * @param stype		Static typing object
+ * @param src		Source type
+ * @param dest		Destination type
+ * @return		Type matching @a dest with correct type arguments
+ */
+tdata_item_t *stype_tobject_find_pred(stype_t *stype, tdata_item_t *src,
+    tdata_item_t *dest)
+{
+	stree_csi_t *src_csi;
+	tdata_tvv_t *tvv;
+	tdata_item_t *b_ti, *bs_ti;
+
+	list_node_t *pred_n;
+	stree_texpr_t *pred_te;
+
+	tdata_item_t *res_ti;
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Find CSI predecessor.\n");
+#endif
+	assert(src->tic == tic_tobject);
+	assert(dest->tic == tic_tobject);
+
+	if (src->u.tobject->csi == dest->u.tobject->csi)
+		return src;
+
+	src_csi = src->u.tobject->csi;
+	stype_titem_to_tvv(stype, src, &tvv);
+
+	res_ti = NULL;
+
+	switch (dest->u.tobject->csi->cc) {
+	case csi_class:
+		/* Destination is a class. Look at base class. */
+		pred_te = symbol_get_base_class_ref(stype->program,
+		    src_csi);
+		if (pred_te != NULL) {
+			run_texpr(stype->program, src_csi, pred_te,
+			    &b_ti);
+		} else if (src_csi->base_csi != NULL &&
+			src->u.tobject->csi->cc == csi_class) {
+			/* No explicit reference. Use grandfather class. */
+		    	b_ti = tdata_item_new(tic_tobject);
+			b_ti->u.tobject = tdata_object_new();
+			b_ti->u.tobject->csi = src_csi->base_csi;
+			b_ti->u.tobject->static_ref = sn_nonstatic;
+
+			list_init(&b_ti->u.tobject->targs);
+		} else {
+			/* No match */
+			return NULL;
+		}
+
+		/* Substitute type variables to get predecessor type. */
+		tdata_item_subst(b_ti, tvv, &bs_ti);
+		assert(bs_ti->tic == tic_tobject);
+
+		/* Recurse to compute the rest of the path. */
+		res_ti = stype_tobject_find_pred(stype, bs_ti, dest);
+	    	if (b_ti->tic == tic_ignore) {
+			/* An error occured. */
+			return NULL;
+		}
+		break;
+	case csi_struct:
+		assert(b_false);
+	case csi_interface:
+		/*
+		 * Destination is an interface. Look at implemented
+		 * or accumulated interfaces.
+		 */
+		pred_n = list_first(&src_csi->inherit);
+		while (pred_n != NULL) {
+			pred_te = list_node_data(pred_n, stree_texpr_t *);
+			run_texpr(stype->program, src_csi, pred_te,
+			    &b_ti);
+
+			/* Substitute type variables to get predecessor type. */
+			tdata_item_subst(b_ti, tvv, &bs_ti);
+			assert(bs_ti->tic == tic_tobject);
+
+			/* Recurse to compute the rest of the path. */
+			res_ti = stype_tobject_find_pred(stype, bs_ti, dest);
+			if (res_ti != NULL)
+				break;
+
+			pred_n = list_next(&src_csi->inherit, pred_n);
+		}
+		break;
+	}
+
+	return res_ti;
+}
+
+/** Check whether type arguments of expression type and another type are equal.
+ *
+ * Compare type arguments of the type of @a expr and of type @a b_ti.
+ * @a convc denotes the type of conversion for which we perform this check
+ * (for sake of error reporting).
+ *
+ * If the type arguments are not equal a typing error and a conversion error
+ * message is generated.
+ *
+ * @param stype		Static typing object
+ * @param expr		Expression
+ * @param b_ti		b_tiination type
+ * @return		EOK if equal, EINVAL if not.
+ */
+int stype_targs_check_equal(stype_t *stype, tdata_item_t *a_ti,
+    tdata_item_t *b_ti)
+{
+	list_node_t *arg_a_n, *arg_b_n;
+	tdata_item_t *arg_a, *arg_b;
+
+	(void) stype;
+
+#ifdef DEBUG_TYPE_TRACE
+	printf("Check if type arguments match.\n");
+#endif
+	assert(a_ti->tic == tic_tobject);
+	assert(b_ti->tic == tic_tobject);
+
+	/*
+	 * Verify that type arguments match with those specified for
+	 * conversion b_tiination.
+	 */
+	arg_a_n = list_first(&a_ti->u.tobject->targs);
+	arg_b_n = list_first(&b_ti->u.tobject->targs);
+
+	while (arg_a_n != NULL && arg_b_n != NULL) {
+		arg_a = list_node_data(arg_a_n, tdata_item_t *);
+		arg_b = list_node_data(arg_b_n, tdata_item_t *);
+
+		if (tdata_item_equal(arg_a, arg_b) != b_true) {
+			/* Diferent argument type */
+			printf("Different argument type '");
+			tdata_item_print(arg_a);
+			printf("' vs. '");
+			tdata_item_print(arg_b);
+			printf("'.\n");
+			return EINVAL;
+		}
+
+		arg_a_n = list_next(&a_ti->u.tobject->targs, arg_a_n);
+		arg_b_n = list_next(&b_ti->u.tobject->targs, arg_b_n);
+	}
+
+	if (arg_a_n != NULL || arg_b_n != NULL) {
+		/* Diferent number of arguments */
+		printf("Different number of arguments.\n");
+		return EINVAL;
+	}
+
+	return EOK;
+}
 
 
@@ -1448,6 +1888,15 @@
 
 	/* Compare return type */
-	if (!tdata_item_equal(asig->rtype, bsig->rtype))
-		return b_false;
+
+	if (asig->rtype != NULL || bsig->rtype != NULL) {
+		if (asig->rtype == NULL ||
+		    bsig->rtype == NULL) {
+			return b_false;
+		}
+
+		if (!tdata_item_equal(asig->rtype, bsig->rtype)) {
+			return b_false;
+		}
+	}
 
 	return b_true;
Index: uspace/app/sbi/src/stype.h
===================================================================
--- uspace/app/sbi/src/stype.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/stype.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -37,4 +37,5 @@
 void stype_enum(stype_t *stype, stree_enum_t *enum_d);
 void stype_fun_header(stype_t *stype, stree_fun_t *fun);
+void stype_prop_header(stype_t *stype, stree_prop_t *prop);
 void stype_stat(stype_t *stype, stree_stat_t *stat, bool_t want_value);
 
@@ -44,5 +45,11 @@
 stree_expr_t *stype_convert(stype_t *stype, stree_expr_t *expr,
     tdata_item_t *dest);
+void stype_convert_failure(stype_t *stype, stype_conv_class_t convc,
+    stree_expr_t *expr, tdata_item_t *dest);
 stree_expr_t *stype_box_expr(stype_t *stype, stree_expr_t *expr);
+tdata_item_t *stype_tobject_find_pred(stype_t *stype, tdata_item_t *src,
+    tdata_item_t *dest);
+int stype_targs_check_equal(stype_t *stype, tdata_item_t *a_ti,
+    tdata_item_t *b_ti);
 
 tdata_fun_sig_t *stype_deleg_get_sig(stype_t *stype, tdata_deleg_t *tdeleg);
Index: uspace/app/sbi/src/stype_expr.c
===================================================================
--- uspace/app/sbi/src/stype_expr.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/stype_expr.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -97,5 +97,5 @@
 static void stype_new(stype_t *stype, stree_new_t *new,
     tdata_item_t **rtitem);
-static void stype_new_object_args(stype_t *stype, stree_new_t *new_op,
+static void stype_new_object(stype_t *stype, stree_new_t *new_op,
     tdata_item_t *obj_ti);
 
@@ -194,4 +194,5 @@
 	tdata_ebase_t *tebase;
 	stree_fun_t *fun;
+	bool_t static_ctx;
 
 #ifdef DEBUG_TYPE_TRACE
@@ -257,4 +258,30 @@
 	}
 
+	/* Determine if current procedure is static. */
+	static_ctx = stree_symbol_is_static(stype->proc_vr->proc->outer_symbol);
+
+	/*
+	 * If the symbol is not found in current CSI, then we access it
+	 * in a static context. (Context of current object cannot be used.)
+	 */
+	if (sym->outer_csi != stype->current_csi)
+		static_ctx = b_true;
+
+	/* Check for referencing non-static symbol in static context. */
+	if (static_ctx && !stree_symbol_is_static(sym)) {
+		cspan_print(nameref->expr->cspan);
+		printf(" Error: Referencing non-static symbol '");
+		symbol_print_fqn(sym);
+		printf("' in static context.\n");
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	/* Referencing static member in non-static context is allowed. */
+
+	/* Make compiler happy. */
+	titem = NULL;
+
 	switch (sym->sc) {
 	case sc_var:
@@ -263,6 +290,7 @@
 		break;
 	case sc_prop:
-		run_texpr(stype->program, stype->current_csi,
-		    sym->u.prop->type, &titem);
+		/* Type property header if it has not been typed yet. */
+		stype_prop_header(stype, sym->u.prop);
+		titem = sym->u.prop->titem;
 		break;
 	case sc_csi:
@@ -274,6 +302,5 @@
 		titem->u.tobject = tobject;
 
-		/* This is a static CSI reference. */
-		tobject->static_ref = b_true;
+		tobject->static_ref = sn_static;
 		tobject->csi = csi;
 		break;
@@ -330,4 +357,7 @@
 	(void) stype;
 
+	/* Make compiler happy. */
+	tpc = 0;
+
 	switch (literal->ltc) {
 	case ltc_bool: tpc = tpc_bool; break;
@@ -375,5 +405,5 @@
 	titem->u.tobject = tobject;
 
-	tobject->static_ref = b_false;
+	tobject->static_ref = sn_nonstatic;
 	tobject->csi = cur_csi;
 	list_init(&tobject->targs);
@@ -513,4 +543,7 @@
 	tdata_item_t *res_ti;
 
+	/* Make compiler happy. */
+	rtpc = 0;
+
 	switch (binop->bc) {
 	case bo_equal:
@@ -560,4 +593,7 @@
 	(void) stype;
 
+	/* Make compiler happy. */
+	rtpc = 0;
+
 	switch (binop->bc) {
 	case bo_equal:
@@ -604,4 +640,7 @@
 	(void) stype;
 
+	/* Make compiler happy. */
+	rtpc = 0;
+
 	switch (binop->bc) {
 	case bo_equal:
@@ -666,4 +705,7 @@
 	tdata_item_t *res_ti;
 
+	/* Make compiler happy. */
+	rtpc = 0;
+
 	switch (binop->bc) {
 	case bo_equal:
@@ -941,5 +983,5 @@
 
 	if ((*rtitem)->tic == tic_tobject)
-		stype_new_object_args(stype, new_op, *rtitem);
+		stype_new_object(stype, new_op, *rtitem);
 }
 
@@ -949,5 +991,5 @@
  * @param new_op	@c new operation
  */
-static void stype_new_object_args(stype_t *stype, stree_new_t *new_op,
+static void stype_new_object(stype_t *stype, stree_new_t *new_op,
     tdata_item_t *obj_ti)
 {
@@ -957,7 +999,17 @@
 	stree_ident_t *ctor_ident;
 	tdata_fun_sig_t *tsig;
+	tdata_tvv_t *obj_tvv;
+	tdata_item_t *ctor_sti;
 
 	assert(obj_ti->tic == tic_tobject);
 	csi = obj_ti->u.tobject->csi;
+
+	if (csi->cc == csi_interface) {
+		cspan_print(new_op->expr->cspan);
+		printf(" Error: Cannot instantiate an interface.\n");
+		stype_note_error(stype);
+		return;
+	}
+
 	ctor_ident = stree_ident_new();
 	ctor_ident->sid = strtab_get_sid(CTOR_IDENT);
@@ -986,6 +1038,11 @@
 		return;
 
-	assert(ctor->titem->tic == tic_tfun);
-	tsig = ctor->titem->u.tfun->tsig;
+	/* Substitute type arguments in constructor type. */
+	stype_titem_to_tvv(stype, obj_ti, &obj_tvv);
+	tdata_item_subst(ctor->titem, obj_tvv, &ctor_sti);
+	/* XXX Free obj_tvv */
+
+	assert(ctor_sti->tic == tic_tfun);
+	tsig = ctor_sti->u.tfun->tsig;
 
 	stype_call_args(stype, new_op->expr->cspan, &tsig->arg_ti,
@@ -1104,4 +1161,5 @@
 	tdata_item_t *mtitem;
 	tdata_tvv_t *tvv;
+	stree_csi_t *member_csi;
 
 #ifdef DEBUG_TYPE_TRACE
@@ -1131,13 +1189,43 @@
 	    strtab_get_str(access->member_name->sid));
 #endif
+	/* Check for accessing non-static member in static context. */
+	if (tobject->static_ref == sn_static &&
+	    !stree_symbol_is_static(member_sym)) {
+		cspan_print(access->member_name->cspan);
+		printf(" Error: Accessing non-static member '");
+		symbol_print_fqn(member_sym);
+		printf("' in static context.\n");
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	/* Check for accessing static member in non-static context. */
+	if (tobject->static_ref != sn_static &&
+	    stree_symbol_is_static(member_sym)) {
+		cspan_print(access->member_name->cspan);
+		printf(" Error: Accessing static member '");
+		symbol_print_fqn(member_sym);
+		printf("' in non-static context.\n");
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	/* Make compiler happy. */
+	mtitem = NULL;
 
 	switch (member_sym->sc) {
 	case sc_csi:
-		cspan_print(access->member_name->cspan);
-		printf(" Error: Accessing object member which is nested "
-		    "CSI.\n");
-		stype_note_error(stype);
-		*rtitem = stype_recovery_titem(stype);
-		return;
+		member_csi = symbol_to_csi(member_sym);
+		assert(member_csi != NULL);
+
+		mtitem = tdata_item_new(tic_tobject);
+		tobject = tdata_object_new();
+		mtitem->u.tobject = tobject;
+
+		tobject->static_ref = sn_static;
+		tobject->csi = member_csi;
+		break;
 	case sc_ctor:
 		/* It is not possible to reference a constructor explicitly. */
@@ -1337,11 +1425,8 @@
 	stree_expr_t *carg;
 
-	int cnt;
-
 	/* Type and check regular arguments. */
 	fargt_n = list_first(farg_tis);
 	arg_n = list_first(args);
 
-	cnt = 0;
 	while (fargt_n != NULL && arg_n != NULL) {
 		farg_ti = list_node_data(fargt_n, tdata_item_t *);
@@ -1656,4 +1741,5 @@
 {
 	tdata_item_t *titem;
+	tdata_item_t *pred_ti;
 
 #ifdef DEBUG_TYPE_TRACE
@@ -1664,13 +1750,21 @@
 	run_texpr(stype->program, stype->current_csi, as_op->dtype, &titem);
 
-	/* Check that target type is derived from argument type. */
-	if (tdata_is_ti_derived_from_ti(titem, as_op->arg->titem) != b_true) {
-		cspan_print(as_op->dtype->cspan);
-		printf(" Error: Target of 'as' operator '");
-		tdata_item_print(titem);
-		printf("' is not derived from '");
-		tdata_item_print(as_op->arg->titem);
-		printf("'.\n");
-		stype_note_error(stype);
+	pred_ti = stype_tobject_find_pred(stype, titem, as_op->arg->titem);
+	if (pred_ti == NULL) {
+		/* No CSI match. */
+		stype_convert_failure(stype, convc_as, as_op->arg, titem);
+		*rtitem = titem;
+		return;
+	}
+
+	/*
+	 * Verify that type arguments match with those specified for
+	 * conversion destination.
+	 */
+	if (stype_targs_check_equal(stype, pred_ti, as_op->arg->titem)
+	    != EOK) {
+		stype_convert_failure(stype, convc_as, as_op->arg, titem);
+		*rtitem = titem;
+		return;
 	}
 
@@ -1720,5 +1814,5 @@
 
 	btitem->u.tobject = tobject;
-	tobject->static_ref = b_false;
+	tobject->static_ref = sn_nonstatic;
 	tobject->csi = symbol_to_csi(csi_sym);
 	assert(tobject->csi != NULL);
Index: uspace/app/sbi/src/stype_t.h
===================================================================
--- uspace/app/sbi/src/stype_t.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/stype_t.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -59,4 +59,12 @@
 } stype_proc_vr_t;
 
+/** Conversion class */
+typedef enum {
+	/** Implicit conversion */
+	convc_implicit,
+	/** 'as' conversion */
+	convc_as
+} stype_conv_class_t;
+
 /** Static typer state object */
 typedef struct stype {
Index: uspace/app/sbi/src/symbol.c
===================================================================
--- uspace/app/sbi/src/symbol.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/symbol.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -42,5 +42,4 @@
 static stree_symbol_t *symbol_find_epoint_rec(stree_program_t *prog,
     stree_ident_t *name, stree_csi_t *csi);
-static stree_symbol_t *csimbr_to_symbol(stree_csimbr_t *csimbr);
 static stree_ident_t *symbol_get_ident(stree_symbol_t *symbol);
 
@@ -132,5 +131,4 @@
     stree_csi_t *scope, stree_ident_t *name)
 {
-	stree_symbol_t *base_csi_sym;
 	stree_csi_t *base_csi;
 	stree_symbol_t *symbol;
@@ -142,12 +140,7 @@
 
 	/* 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);
-
+	base_csi = symbol_get_base_class(prog, scope);
+	if (base_csi != NULL)
 		return symbol_search_csi(prog, base_csi, name);
-	}
 
 	/* No match */
@@ -212,4 +205,7 @@
 		modm = list_node_data(node, stree_modm_t *);
 
+		/* Make compiler happy. */
+		mbr_name = NULL;
+
 		switch (modm->mc) {
 		case mc_csi: mbr_name = modm->u.csi->name; break;
@@ -217,5 +213,11 @@
 		}
 
+		/* The Clang static analyzer is just too picky. */
+		assert(mbr_name != NULL);
+
 		if (name->sid == mbr_name->sid) {
+			/* Make compiler happy. */
+			symbol = NULL;
+
 			/* Match */
 			switch (modm->mc) {
@@ -231,4 +233,75 @@
 		node = list_next(&prog->module->members, node);
 	}
+
+	return NULL;
+}
+
+/** Get explicit base class for a CSI.
+ *
+ * Note that if there is no explicit base class (class is derived implicitly
+ * from @c object, then @c NULL is returned.
+ *
+ * @param prog	Program to look in
+ * @param csi	CSI
+ *
+ * @return	Base class (CSI) or @c NULL if no explicit base class.
+ */
+stree_csi_t *symbol_get_base_class(stree_program_t *prog, stree_csi_t *csi)
+{
+	list_node_t *pred_n;
+	stree_texpr_t *pred;
+	stree_symbol_t *pred_sym;
+	stree_csi_t *pred_csi;
+	stree_csi_t *outer_csi;
+
+	outer_csi = csi_to_symbol(csi)->outer_csi;
+
+	pred_n = list_first(&csi->inherit);
+	if (pred_n == NULL)
+		return NULL;
+
+	pred = list_node_data(pred_n, stree_texpr_t *);
+	pred_sym = symbol_xlookup_in_csi(prog, outer_csi, pred);
+	pred_csi = symbol_to_csi(pred_sym);
+	assert(pred_csi != NULL); /* XXX! */
+
+	if (pred_csi->cc == csi_class)
+		return pred_csi;
+
+	return NULL;
+}
+
+/** Get type expression referencing base class for a CSI.
+ *
+ * Note that if there is no explicit base class (class is derived implicitly
+ * from @c object, then @c NULL is returned.
+ *
+ * @param prog	Program to look in
+ * @param csi	CSI
+ *
+ * @return	Type expression or @c NULL if no explicit base class.
+ */
+stree_texpr_t *symbol_get_base_class_ref(stree_program_t *prog,
+    stree_csi_t *csi)
+{
+	list_node_t *pred_n;
+	stree_texpr_t *pred;
+	stree_symbol_t *pred_sym;
+	stree_csi_t *pred_csi;
+	stree_csi_t *outer_csi;
+
+	outer_csi = csi_to_symbol(csi)->outer_csi;
+
+	pred_n = list_first(&csi->inherit);
+	if (pred_n == NULL)
+		return NULL;
+
+	pred = list_node_data(pred_n, stree_texpr_t *);
+	pred_sym = symbol_xlookup_in_csi(prog, outer_csi, pred);
+	pred_csi = symbol_to_csi(pred_sym);
+	assert(pred_csi != NULL); /* XXX! */
+
+	if (pred_csi->cc == csi_class)
+		return pred;
 
 	return NULL;
@@ -286,4 +359,5 @@
 	stree_csimbr_t *csimbr;
 	stree_symbol_t *entry, *etmp;
+	stree_symbol_t *fun_sym;
 
 	entry = NULL;
@@ -305,10 +379,13 @@
 			break;
 		case csimbr_fun:
-			if (csimbr->u.fun->name->sid == name->sid) {
+			fun_sym = fun_to_symbol(csimbr->u.fun);
+
+			if (csimbr->u.fun->name->sid == name->sid &&
+			    stree_symbol_has_attr(fun_sym, sac_static)) {
 				if (entry != NULL) {
 					printf("Error: Duplicate entry point.\n");
 					exit(1);
 				}
-				entry = fun_to_symbol(csimbr->u.fun);
+				entry = fun_sym;
 			}
 		default:
@@ -494,5 +571,5 @@
  * @return		Symbol
  */
-static stree_symbol_t *csimbr_to_symbol(stree_csimbr_t *csimbr)
+stree_symbol_t *csimbr_to_symbol(stree_csimbr_t *csimbr)
 {
 	stree_symbol_t *symbol;
@@ -569,4 +646,7 @@
 	stree_ident_t *ident;
 
+	/* Make compiler happy. */
+	ident = NULL;
+
 	switch (symbol->sc) {
 	case sc_csi: ident = symbol->u.csi->name; break;
Index: uspace/app/sbi/src/symbol.h
===================================================================
--- uspace/app/sbi/src/symbol.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/symbol.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -40,4 +40,7 @@
 stree_symbol_t *symbol_search_csi_no_base(stree_program_t *prog,
     stree_csi_t *scope, stree_ident_t *name);
+stree_csi_t *symbol_get_base_class(stree_program_t *prog, stree_csi_t *csi);
+stree_texpr_t *symbol_get_base_class_ref(stree_program_t *prog,
+    stree_csi_t *csi);
 stree_symbol_t *symbol_find_epoint(stree_program_t *prog, stree_ident_t *name);
 
@@ -57,4 +60,6 @@
 stree_symbol_t *prop_to_symbol(stree_prop_t *prop);
 
+stree_symbol_t *csimbr_to_symbol(stree_csimbr_t *csimbr);
+
 void symbol_print_fqn(stree_symbol_t *symbol);
 
Index: uspace/app/sbi/src/tdata.c
===================================================================
--- uspace/app/sbi/src/tdata.c	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/tdata.c	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -343,6 +343,8 @@
 	/* Plain copy */
 	tnew = tdata_ebase_new();
+	tnew->enum_d = tebase->enum_d;
+
 	*res = tdata_item_new(tic_tebase);
-	(*res)->u.tebase = tebase;
+	(*res)->u.tebase = tnew;
 }
 
@@ -362,6 +364,8 @@
 	/* Plain copy */
 	tnew = tdata_enum_new();
+	tnew->enum_d = tenum->enum_d;
+
 	*res = tdata_item_new(tic_tenum);
-	(*res)->u.tenum = tenum;
+	(*res)->u.tenum = tnew;
 }
 
Index: uspace/app/sbi/src/tdata_t.h
===================================================================
--- uspace/app/sbi/src/tdata_t.h	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/app/sbi/src/tdata_t.h	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -58,6 +58,6 @@
 /** Object type. */
 typedef struct {
-	/** @c true if expression is a static CSI reference */
-	bool_t static_ref;
+	/** @c sn_static if expression is a static CSI reference */
+	statns_t static_ref;
 
 	/** CSI definition */
Index: uspace/dist/src/sysel/demos/arith.sy
===================================================================
--- uspace/dist/src/sysel/demos/arith.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/arith.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class ArithmeticDemo is
-	fun Main() is
+	fun Main(), static is
 		-- Test addition, multiplication and precedence.
 		Builtin.Write("2*2 + 2*2 = ");
@@ -88,5 +88,5 @@
 
 	-- Return factorial of n.
-	fun Factorial(n : int) : int is
+	fun Factorial(n : int) : int, static is
 		var i : int;
 		var val : int;
Index: uspace/dist/src/sysel/demos/array.sy
===================================================================
--- uspace/dist/src/sysel/demos/array.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/array.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class ArrayDemo is
-	fun Main() is
+	fun Main(), static is
 		var a : int[,];
 		var i : int;
Index: uspace/dist/src/sysel/demos/autobox.sy
===================================================================
--- uspace/dist/src/sysel/demos/autobox.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/autobox.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class AutoboxingDemo is
-	fun Main() is
+	fun Main(), static is
 		var b : Bool;
 		var c : Char;
@@ -51,5 +51,5 @@
 	end
 
-	fun foo(args : Object[], packed) is
+	fun foo(args : Object[], packed), static is
 	end
 end
Index: uspace/dist/src/sysel/demos/count.sy
===================================================================
--- uspace/dist/src/sysel/demos/count.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/count.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class CountDemo is
-	fun Count(a : int; b : int) is
+	fun Count(a : int; b : int), static is
 		var i : int;
 
@@ -39,5 +39,5 @@
 	end
 
-	fun Main() is
+	fun Main(), static is
 		Count(0, 10);
 	end
Index: uspace/dist/src/sysel/demos/ctor.sy
===================================================================
--- uspace/dist/src/sysel/demos/ctor.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/ctor.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class ConstructorDemo is
-	fun Main() is
+	fun Main(), static is
 		var a : A;
 
Index: uspace/dist/src/sysel/demos/deleg.sy
===================================================================
--- uspace/dist/src/sysel/demos/deleg.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/deleg.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class DelegateDemo is
-	fun Main() is
+	fun Main(), static is
 		var demo : DelegateClass;
 
Index: uspace/dist/src/sysel/demos/enum.sy
===================================================================
--- uspace/dist/src/sysel/demos/enum.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/enum.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class EnumDemo is
-	fun Main() is
+	fun Main(), static is
 		var color : ChessColor;
 
Index: uspace/dist/src/sysel/demos/except.sy
===================================================================
--- uspace/dist/src/sysel/demos/except.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/except.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,10 +28,10 @@
 
 class ExceptionDemo is
-	fun foo() is
+	fun foo(), static is
 	        Builtin.WriteLine("Entered foo().");
 		raise new BaseException();
 	end
 
-	fun Main() is
+	fun Main(), static is
 		do
 			foo();
Index: uspace/dist/src/sysel/demos/gen.sy
===================================================================
--- uspace/dist/src/sysel/demos/gen.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/gen.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -30,5 +30,5 @@
 
 class GenericsDemo is
-	fun Main() is
+	fun Main(), static is
 		Builtin.WriteLine("Let's try some generics.");
 
Index: uspace/dist/src/sysel/demos/hello.sy
===================================================================
--- uspace/dist/src/sysel/demos/hello.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/hello.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class HelloWorld is
-	fun Main() is
+	fun Main(), static is
 		Builtin.WriteLine("Hello world!");
 	end
Index: uspace/dist/src/sysel/demos/hexec.sy
===================================================================
--- uspace/dist/src/sysel/demos/hexec.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/hexec.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class HelenOSExecDemo is
-	fun Main() is
+	fun Main(), static is
 		Task.Exec("/app/tester");
 		Task.Exec("/app/tester", "print1");
Index: uspace/dist/src/sysel/demos/htxtfile.sy
===================================================================
--- uspace/dist/src/sysel/demos/htxtfile.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/htxtfile.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class TextFileDemo is
-	fun Main() is
+	fun Main(), static is
 		var name : string;
 		var line : string;
Index: uspace/dist/src/sysel/demos/iface.sy
===================================================================
--- uspace/dist/src/sysel/demos/iface.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
+++ uspace/dist/src/sysel/demos/iface.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -0,0 +1,87 @@
+--
+-- Copyright (c) 2010 Jiri Svoboda
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- o Redistributions of source code must retain the above copyright
+--   notice, this list of conditions and the following disclaimer.
+-- o Redistributions in binary form must reproduce the above copyright
+--   notice, this list of conditions and the following disclaimer in the
+--   documentation and/or other materials provided with the distribution.
+-- o The name of the author may not be used to endorse or promote products
+--   derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+-- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+-- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+-- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--
+
+class InterfaceDemo is
+	fun Main(), static is
+		-- Create new instance of Foo
+		var f : Foo;
+		f = new Foo();
+
+		-- Variable of interface type
+		var g : IA/int;
+
+		-- Implicit conversion to interface implemented by Foo
+		g = f;
+
+		-- Explicit conversion of interface type IA/int to class type
+		-- Foo. Foo is implementing the interface IA/int.
+		f = g as Foo;
+
+		Builtin.WriteLine(g.a());
+	end
+end
+
+-- Generic interface implemented by class Foo
+interface IA/t is
+	fun a() : t;
+end
+
+-- Non-generic interface implemented by class Foo
+interface IB is
+	fun b();
+	prop P : int is
+		get;
+		set value;
+	end
+end
+
+-- Base class of Foo
+class A is
+end
+
+-- Class unrelated to Foo
+class B is
+end
+
+-- Foo is derived from A and implements IA/int and IB
+class Foo : A + IA/int + IB is
+	fun a() : int is
+		return 0;
+	end
+
+	fun b() is
+	end
+
+	prop P : int is
+		get is
+			return 1;
+		end
+		set value is
+		end
+	end
+end
Index: uspace/dist/src/sysel/demos/inherit.sy
===================================================================
--- uspace/dist/src/sysel/demos/inherit.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/inherit.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -43,5 +43,5 @@
 
 class InheritanceDemo is
-	fun Main() is
+	fun Main(), static is
 		var a : A;
 		var c : C;
Index: uspace/dist/src/sysel/demos/list.sy
===================================================================
--- uspace/dist/src/sysel/demos/list.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/list.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -29,5 +29,5 @@
 -- Using the List class from the library.
 class ListDemo is
-	fun Main() is
+	fun Main(), static is
 		var list : List/int;
 
@@ -39,10 +39,9 @@
 		list.Append(8);
 
-		var n : ListNode/int;
+		var e : IEnumerator/int;
 
-		n = list.First;
-		while n != nil do
-			Builtin.WriteLine(n.Data);
-			n = n.Next;
+		e = list.GetEnumerator();
+		while e.MoveNext() do
+			Builtin.WriteLine(e.Data);
 		end
 	end
Index: uspace/dist/src/sysel/demos/map.sy
===================================================================
--- uspace/dist/src/sysel/demos/map.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/map.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -29,5 +29,5 @@
 -- Using the Map class from the library.
 class MapDemo is
-	fun Main() is
+	fun Main(), static is
 		var map : Map/string/int;
 
@@ -39,8 +39,12 @@
 		map["four"] = 4;
 
-		Builtin.WriteLine(map["one"]);
-		Builtin.WriteLine(map["two"]);
-		Builtin.WriteLine(map["three"]);
-		Builtin.WriteLine(map["four"]);
+		var e : IEnumerator/string;
+
+		e = map.GetEnumerator();
+		while e.MoveNext() do
+			Builtin.Write(e.Data);
+			Builtin.Write(" -> ");
+			Builtin.WriteLine(map[e.Data]);
+		end
 	end
 end
Index: uspace/dist/src/sysel/demos/property.sy
===================================================================
--- uspace/dist/src/sysel/demos/property.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/property.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -98,5 +98,5 @@
 
 class PropertyDemo is
-	fun Main() is
+	fun Main(), static is
 		var a : Foo;
 		var i : int;
Index: uspace/dist/src/sysel/demos/string.sy
===================================================================
--- uspace/dist/src/sysel/demos/string.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/string.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 class StringDemo is
-	fun Main() is
+	fun Main(), static is
 		-- Concatenate some strings.
 		Builtin.WriteLine("One-" + "two-" + "three!");
Index: uspace/dist/src/sysel/demos/svar.sy
===================================================================
--- uspace/dist/src/sysel/demos/svar.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
+++ uspace/dist/src/sysel/demos/svar.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -0,0 +1,59 @@
+--
+-- Copyright (c) 2010 Jiri Svoboda
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- o Redistributions of source code must retain the above copyright
+--   notice, this list of conditions and the following disclaimer.
+-- o Redistributions in binary form must reproduce the above copyright
+--   notice, this list of conditions and the following disclaimer in the
+--   documentation and/or other materials provided with the distribution.
+-- o The name of the author may not be used to endorse or promote products
+--   derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+-- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+-- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+-- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--
+
+class StaticPropertyDemo is
+	fun Main(), static is
+		-- Test static member variable
+		A.B.a = 1;
+		Builtin.WriteLine(A.B.a);
+		A.B.a = 2;
+		Builtin.WriteLine(A.B.a);
+
+		-- Test static property
+		A.B.P = 1;
+		Builtin.WriteLine(A.B.P);
+		A.B.P = 2;
+		Builtin.WriteLine(A.B.P);
+	end
+end
+
+class A is
+	class B is
+		var a : int, static;
+
+		prop P : int, static is
+			get is
+				return a;
+			end
+
+			set value is
+				a = value;
+			end
+		end
+	end
+end
Index: uspace/dist/src/sysel/demos/varargs.sy
===================================================================
--- uspace/dist/src/sysel/demos/varargs.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/demos/varargs.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -33,5 +33,5 @@
 	-- with the attribute 'packed'.
 	--
-	fun Print(args : string[], packed) is
+	fun Print(args : string[], packed), static is
 		var i : int;
 		var error : bool;
@@ -53,5 +53,5 @@
 	end
 
-	fun Main() is
+	fun Main(), static is
 		Print("One", "Two", "Three", "Four", "Five");
 	end
Index: uspace/dist/src/sysel/lib/arith.sy
===================================================================
--- uspace/dist/src/sysel/lib/arith.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/lib/arith.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -29,5 +29,5 @@
 class Arith is
 	-- Return factorial of n.
-	fun Factorial(n : int) : int is
+	fun Factorial(n : int) : int, static is
 		var i : int;
 		var val : int;
Index: uspace/dist/src/sysel/lib/boxed.sy
===================================================================
--- uspace/dist/src/sysel/lib/boxed.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/lib/boxed.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -38,8 +38,26 @@
 class Char is
 	var Value : char;
+
+	fun get_as_string() : string, builtin;
+
+	-- String representation.
+	prop AsString : string is
+		get is
+			return get_as_string();
+		end
+	end
 end
 
 class Int is
 	var Value : int;
+
+	fun get_as_string() : string, builtin;
+
+	-- String representation.
+	prop AsString : string is
+		get is
+			return get_as_string();
+		end
+	end
 end
 
Index: uspace/dist/src/sysel/lib/ienum.sy
===================================================================
--- uspace/dist/src/sysel/lib/ienum.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
+++ uspace/dist/src/sysel/lib/ienum.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -0,0 +1,41 @@
+--
+-- Copyright (c) 2010 Jiri Svoboda
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- o Redistributions of source code must retain the above copyright
+--   notice, this list of conditions and the following disclaimer.
+-- o Redistributions in binary form must reproduce the above copyright
+--   notice, this list of conditions and the following disclaimer in the
+--   documentation and/or other materials provided with the distribution.
+-- o The name of the author may not be used to endorse or promote products
+--   derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+-- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+-- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+-- IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+-- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--
+
+-- Enumerable collection interface.
+interface IEnumerable/tdata is
+	fun GetEnumerator() : IEnumerator/tdata;
+end
+
+-- Enumerator interface.
+interface IEnumerator/tdata is
+	fun MoveNext() : bool;
+
+	prop Data : tdata is
+		get;
+	end
+end
Index: uspace/dist/src/sysel/lib/libflist
===================================================================
--- uspace/dist/src/sysel/lib/libflist	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/lib/libflist	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -1,4 +1,5 @@
 arith.sy
 boxed.sy
+ienum.sy
 list.sy
 map.sy
Index: uspace/dist/src/sysel/lib/list.sy
===================================================================
--- uspace/dist/src/sysel/lib/list.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/lib/list.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -28,5 +28,5 @@
 
 -- Doubly-linked list.
-class List/t is
+class List/t : IEnumerable/t is
 	var head : ListNode/t;
 
@@ -59,6 +59,11 @@
 	prop First : ListNode/t is
 		get is
-		    return get_first();
+			return get_first();
 		end
+	end
+
+	-- Return first node in the list or @c nil if there is none.
+	fun GetEnumerator() : IEnumerator/t is
+		return new ListEnumerator/t(get_first());
 	end
 
@@ -131,4 +136,32 @@
 		end
 	end
+end
 
+class ListEnumerator/t : IEnumerator/t is
+	var first : ListNode/t;
+	var current : ListNode/t;
+	var started : bool;
+
+	new(first_node : ListNode/t) is
+		first = first_node;
+		current = nil;
+		started = false;
+	end
+
+	fun MoveNext() : bool is
+		if started then
+			current = current.Next;
+		else
+			current = first;
+			started = true;
+		end
+
+		return current != nil;
+	end
+
+	prop Data : t is
+		get is
+			return current.Data;
+		end
+	end
 end
Index: uspace/dist/src/sysel/lib/map.sy
===================================================================
--- uspace/dist/src/sysel/lib/map.sy	(revision 051bc69a7034999d45c93c61a56e515474aa78e3)
+++ uspace/dist/src/sysel/lib/map.sy	(revision c5cb943d5d19ad0d75578f54188f2491dfd64937)
@@ -91,4 +91,8 @@
 		end
 	end
+
+	fun GetEnumerator() : IEnumerator/tkey is
+		return new MapEnumerator/tkey/tvalue(data.get_first());
+	end
 end
 
@@ -97,2 +101,31 @@
 	var Value : tvalue;
 end
+
+class MapEnumerator/tkey/tvalue : IEnumerator/tkey is
+	var first : ListNode/(MapPair/tkey/tvalue);
+	var current : ListNode/(MapPair/tkey/tvalue);
+	var started : bool;
+
+	new(first_node : ListNode/(MapPair/tkey/tvalue)) is
+		first = first_node;
+		current = nil;
+		started = false;
+	end
+
+	fun MoveNext() : bool is
+		if started then
+			current = current.Next;
+		else
+			current = first;
+			started = true;
+		end
+
+		return current != nil;
+	end
+
+	prop Data : tkey is
+		get is
+			return current.Data.Key;
+		end
+	end
+end
