Index: uspace/app/sbi/Makefile
===================================================================
--- uspace/app/sbi/Makefile	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/Makefile	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -50,4 +50,5 @@
 	src/p_type.c \
 	src/parse.c \
+	src/program.c \
 	src/rdata.c \
 	src/run.c \
Index: uspace/app/sbi/src/builtin/bi_fun.c
===================================================================
--- uspace/app/sbi/src/builtin/bi_fun.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/builtin/bi_fun.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -99,4 +99,6 @@
 {
 	rdata_var_t *var;
+	int char_val;
+	int rc;
 
 #ifdef DEBUG_RUN_TRACE
@@ -107,4 +109,11 @@
 
 	switch (var->vc) {
+	case vc_char:
+		rc = bigint_get_value_int(&var->u.char_v->value, &char_val);
+		if (rc == EOK)
+			printf("%lc\n", char_val);
+		else
+			printf("???\n");
+		break;
 	case vc_int:
 		bigint_print(&var->u.int_v->value);
Index: uspace/app/sbi/src/imode.c
===================================================================
--- uspace/app/sbi/src/imode.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/imode.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -47,4 +47,5 @@
 #include "list.h"
 #include "mytypes.h"
+#include "program.h"
 #include "rdata.h"
 #include "stree.h"
@@ -90,4 +91,8 @@
 	builtin_declare(program);
 
+	/* Process the library. */
+	if (program_lib_process(program) != EOK)
+		exit(1);
+
 	/* Resolve ancestry. */
 	ancr_module_process(program, program->module);
@@ -130,4 +135,6 @@
 		parse.error = b_false;
 		stype.error = b_false;
+		run.thread_ar->exc_payload = NULL;
+		run.thread_ar->bo_mode = bm_none;
 
 		input_new_interactive(&input);
Index: uspace/app/sbi/src/input.c
===================================================================
--- uspace/app/sbi/src/input.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/input.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -45,5 +45,5 @@
 #define INPUT_BUFFER_SIZE 256
 
-static int input_init_file(input_t *input, char *fname);
+static int input_init_file(input_t *input, const char *fname);
 static void input_init_interactive(input_t *input);
 static void input_init_string(input_t *input, const char *str);
@@ -57,5 +57,5 @@
  *			ENOENT when opening file fails.
  */
-int input_new_file(input_t **input, char *fname)
+int input_new_file(input_t **input, const char *fname)
 {
 	*input = malloc(sizeof(input_t));
@@ -104,5 +104,5 @@
  * @return		EOK on success, ENOENT when opening file fails.
 */
-static int input_init_file(input_t *input, char *fname)
+static int input_init_file(input_t *input, const char *fname)
 {
 	FILE *f;
Index: uspace/app/sbi/src/input.h
===================================================================
--- uspace/app/sbi/src/input.h	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/input.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -32,5 +32,5 @@
 #include "mytypes.h"
 
-int input_new_file(input_t **input, char *fname);
+int input_new_file(input_t **input, const char *fname);
 int input_new_interactive(input_t **input);
 int input_new_string(input_t **input, const char *str);
Index: uspace/app/sbi/src/lex.c
===================================================================
--- uspace/app/sbi/src/lex.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/lex.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -53,4 +53,5 @@
 static bool_t is_digit(char c);
 static void lex_word(lex_t *lex);
+static void lex_char(lex_t *lex);
 static void lex_number(lex_t *lex);
 static void lex_string(lex_t *lex);
@@ -74,4 +75,6 @@
 static struct lc_name keywords[] = {
 	{ lc_as,	"as" },
+	{ lc_bool,	"bool" },
+	{ lc_char,	"char" },
 	{ lc_builtin,	"builtin" },
 	{ lc_class,	"class" },
@@ -81,4 +84,5 @@
 	{ lc_end,	"end" },
 	{ lc_except,	"except" },
+	{ lc_false,	"false" },
 	{ lc_finally,	"finally" },
 	{ lc_for,	"for" },
@@ -108,4 +112,5 @@
 	{ lc_then,	"then" },
 	{ lc_this,	"this" },
+	{ lc_true,	"true" },
 	{ lc_var,	"var" },
 	{ lc_with,	"with" },
@@ -338,4 +343,9 @@
 	}
 
+	if (bp[0] == '\'') {
+		lex_char(lex);
+		return b_true;
+	}
+
 	if (is_digit(bp[0])) {
 		lex_number(lex);
@@ -460,4 +470,50 @@
 	lex->current.lclass = lc_ident;
 	lex->current.u.ident.sid = strtab_get_sid(ident_buf);
+}
+
+/** Lex a character literal.
+ *
+ * Reads in a character literal and stores it in the current lem in @a lex.
+ *
+ * @param lex		Lexer object.
+ */
+static void lex_char(lex_t *lex)
+{
+	char *bp;
+	int idx;
+	size_t len;
+	int char_val;
+
+	bp = lex->ibp + 1;
+	idx = 0;
+
+	while (bp[idx] != '\'') {
+		if (idx >= SLBUF_SIZE) {
+			printf("Error: Character literal too long.\n");
+			exit(1);
+		}
+
+		if (bp[idx] == '\0') {
+			printf("Error: Unterminated character literal.\n");
+			exit(1);
+		}
+
+		strlit_buf[idx] = bp[idx];
+		++idx;
+	}
+
+	lex->ibp = bp + idx + 1;
+
+	strlit_buf[idx] = '\0';
+	len = os_str_length(strlit_buf);
+	if (len != 1) {
+		printf("Character literal should contain one character, "
+		    "but contains %u characters instead.\n", (unsigned) len);
+		exit(1);
+	}
+
+	os_str_get_char(strlit_buf, 0, &char_val);
+	lex->current.lclass = lc_lit_char;
+	bigint_init(&lex->current.u.lit_char.value, char_val);
 }
 
Index: uspace/app/sbi/src/lex_t.h
===================================================================
--- uspace/app/sbi/src/lex_t.h	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/lex_t.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -38,4 +38,5 @@
 
 	lc_ident,
+	lc_lit_char,
 	lc_lit_int,
 	lc_lit_string,
@@ -43,5 +44,7 @@
 	/* Keywords */
 	lc_as,
+	lc_bool,
 	lc_builtin,
+	lc_char,
 	lc_class,
 	lc_constructor,
@@ -50,4 +53,5 @@
 	lc_end,
 	lc_except,
+	lc_false,
 	lc_finally,
 	lc_for,
@@ -77,4 +81,5 @@
 	lc_then,
 	lc_this,
+	lc_true,
 	lc_var,
 	lc_with,
@@ -115,4 +120,9 @@
 
 typedef struct {
+	/* Character value */
+	bigint_t value;
+} lem_lit_char_t;
+
+typedef struct {
 	/* Integer value */
 	bigint_t value;
@@ -131,4 +141,5 @@
 	union {
 		lem_ident_t ident;
+		lem_lit_char_t lit_char;
 		lem_lit_int_t lit_int;
 		lem_lit_string_t lit_string;
Index: uspace/app/sbi/src/main.c
===================================================================
--- uspace/app/sbi/src/main.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/main.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -37,7 +37,9 @@
 #include <stdlib.h>
 #include "ancr.h"
+#include "os/os.h"
 #include "builtin.h"
 #include "imode.h"
 #include "mytypes.h"
+#include "program.h"
 #include "strtab.h"
 #include "stree.h"
@@ -48,5 +50,5 @@
 #include "run.h"
 
-void syntax_print(void);
+static void syntax_print(void);
 
 /** Main entry point.
@@ -56,7 +58,4 @@
 int main(int argc, char *argv[])
 {
-	input_t *input;
-	lex_t lex;
-	parse_t parse;
 	stree_program_t *program;
 	stype_t stype;
@@ -64,5 +63,11 @@
 	int rc;
 
-	if (argc == 1) {
+	/* Store executable file path under which we have been invoked. */
+	os_store_ef_path(*argv);
+
+	argv += 1;
+	argc -= 1;
+
+	if (argc == 0) {
 		/* Enter interactive mode */
 		strtab_init();
@@ -71,13 +76,7 @@
 	}
 
-	if (argc != 2) {
+	if (os_str_cmp(*argv, "-h") == 0) {
 		syntax_print();
-		exit(1);
-	}
-
-	rc = input_new_file(&input, argv[1]);
-	if (rc != EOK) {
-		printf("Failed opening source file '%s'.\n", argv[1]);
-		exit(1);
+		return 0;
 	}
 
@@ -89,15 +88,20 @@
 	builtin_declare(program);
 
-	/* Parse input file. */
-	lex_init(&lex, input);
-	parse_init(&parse, program, &lex);
-	parse_module(&parse);
-
-	/* Check for parse errors. */
-	if (parse.error)
+	/* Process source files in the library. */
+	if (program_lib_process(program) != EOK)
 		return 1;
 
+	/* Process all source files specified in command-line arguments. */
+	while (argc > 0) {
+		rc = program_file_process(program, *argv);
+		if (rc != EOK)
+			return 1;
+
+		argv += 1;
+		argc -= 1;
+	}
+
 	/* Resolve ancestry. */
-	ancr_module_process(program, parse.cur_mod);
+	ancr_module_process(program, program->module);
 
 	/* Type program. */
@@ -122,7 +126,6 @@
 
 /** Print command-line syntax help. */
-void syntax_print(void)
+static void syntax_print(void)
 {
-	printf("Missing or invalid arguments.\n");
 	printf("Syntax: sbi <source_file.sy>\n");
 }
Index: uspace/app/sbi/src/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/os/helenos.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -38,4 +38,7 @@
 #include "os.h"
 
+/** Path to executable file via which we have been invoked. */
+static char *ef_path;
+
 /*
  * Using HelenOS-specific string API.
@@ -70,4 +73,10 @@
 {
 	return str_cmp(a, b);
+}
+
+/** Return number of characters in string. */
+size_t os_str_length(const char *str)
+{
+	return str_length(str);
 }
 
@@ -156,2 +165,17 @@
 	return EOK;
 }
+
+/** Store the executable file path via which we were executed. */
+void os_store_ef_path(char *path)
+{
+	ef_path = path;
+}
+
+/** Return path to the Sysel library
+ *
+ * @return New string. Caller should deallocate it using @c free().
+ */
+char *os_get_lib_path(void)
+{
+	return os_str_dup("/src/sysel/lib");
+}
Index: uspace/app/sbi/src/os/os.h
===================================================================
--- uspace/app/sbi/src/os/os.h	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/os/os.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -33,4 +33,5 @@
 int os_str_cmp(const char *a, const char *b);
 char *os_str_dup(const char *str);
+size_t os_str_length(const char *str);
 int os_str_get_char(const char *str, int index, int *out_char);
 void os_input_disp_help(void);
@@ -38,4 +39,6 @@
 int os_exec(char *const cmd[]);
 
+void os_store_ef_path(char *path);
+char *os_get_lib_path(void);
 
 #endif
Index: uspace/app/sbi/src/os/posix.c
===================================================================
--- uspace/app/sbi/src/os/posix.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/os/posix.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -29,4 +29,5 @@
 /** @file POSIX-specific code. */
 
+#include <libgen.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -39,4 +40,7 @@
 
 #include "os.h"
+
+/** Path to executable file via which we have been invoked. */
+static char *ef_path;
 
 /*
@@ -71,4 +75,10 @@
 {
 	return strcmp(a, b);
+}
+
+/** Return number of characters in string. */
+size_t os_str_length(const char *str)
+{
+	return strlen(str);
 }
 
@@ -146,2 +156,17 @@
 	return EOK;
 }
+
+/** Store the executable file path via which we were executed. */
+void os_store_ef_path(char *path)
+{
+	ef_path = path;
+}
+
+/** Return path to the Sysel library
+ *
+ * @return New string. Caller should deallocate it using @c free().
+ */
+char *os_get_lib_path(void)
+{
+	return os_str_acat(dirname(ef_path), "/lib");
+}
Index: uspace/app/sbi/src/p_expr.c
===================================================================
--- uspace/app/sbi/src/p_expr.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/p_expr.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -56,4 +56,6 @@
 static stree_expr_t *parse_primitive(parse_t *parse);
 static stree_expr_t *parse_nameref(parse_t *parse);
+static stree_expr_t *parse_lit_bool(parse_t *parse);
+static stree_expr_t *parse_lit_char(parse_t *parse);
 static stree_expr_t *parse_lit_int(parse_t *parse);
 static stree_expr_t *parse_lit_ref(parse_t *parse);
@@ -494,4 +496,11 @@
 		expr = parse_nameref(parse);
 		break;
+	case lc_false:
+	case lc_true:
+		expr = parse_lit_bool(parse);
+		break;
+	case lc_lit_char:
+		expr = parse_lit_char(parse);
+		break;
 	case lc_lit_int:
 		expr = parse_lit_int(parse);
@@ -531,4 +540,54 @@
 }
 
+/** Parse boolean literal.
+ *
+ * @param parse		Parser object.
+ */
+static stree_expr_t *parse_lit_bool(parse_t *parse)
+{
+	stree_literal_t *literal;
+	stree_expr_t *expr;
+	bool_t value;
+
+	switch (lcur_lc(parse)) {
+	case lc_false: value = b_false; break;
+	case lc_true: value = b_true; break;
+	default: assert(b_false);
+	}
+
+	lskip(parse);
+
+	literal = stree_literal_new(ltc_bool);
+	literal->u.lit_bool.value = value;
+
+	expr = stree_expr_new(ec_literal);
+	expr->u.literal = literal;
+
+	return expr;
+}
+
+/** Parse character literal.
+ *
+ * @param parse		Parser object.
+ */
+static stree_expr_t *parse_lit_char(parse_t *parse)
+{
+	stree_literal_t *literal;
+	stree_expr_t *expr;
+
+	lcheck(parse, lc_lit_char);
+
+	literal = stree_literal_new(ltc_char);
+	bigint_clone(&lcur(parse)->u.lit_char.value,
+	    &literal->u.lit_char.value);
+
+	lskip(parse);
+
+	expr = stree_expr_new(ec_literal);
+	expr->u.literal = literal;
+
+	return expr;
+}
+
 /** Parse integer literal.
  *
Index: uspace/app/sbi/src/p_type.c
===================================================================
--- uspace/app/sbi/src/p_type.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/p_type.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -78,8 +78,17 @@
 static stree_texpr_t *parse_tapply(parse_t *parse)
 {
-	stree_texpr_t *a, *b, *tmp;
+	stree_texpr_t *gtype;
+	stree_texpr_t *aexpr;
+	stree_texpr_t *targ;
 	stree_tapply_t *tapply;
 
-	a = parse_tpostfix(parse);
+	gtype = parse_tpostfix(parse);
+	if (lcur_lc(parse) != lc_slash)
+		return gtype;
+
+	tapply = stree_tapply_new();
+	tapply->gtype = gtype;
+	list_init(&tapply->targs);
+
 	while (lcur_lc(parse) == lc_slash) {
 
@@ -88,16 +97,12 @@
 
 		lskip(parse);
-		b = parse_tpostfix(parse);
-
-		tapply = stree_tapply_new();
-		tapply->gtype = a;
-		tapply->targ = b;
-
-		tmp = stree_texpr_new(tc_tapply);
-		tmp->u.tapply = tapply;
-		a = tmp;
-	}
-
-	return a;
+		targ = parse_tpostfix(parse);
+
+		list_append(&tapply->targs, targ);
+	}
+
+	aexpr = stree_texpr_new(tc_tapply);
+	aexpr->u.tapply = tapply;
+	return aexpr;
 }
 
@@ -224,4 +229,6 @@
 		texpr->u.tnameref = parse_tnameref(parse);
 		break;
+	case lc_bool:
+	case lc_char:
 	case lc_int:
 	case lc_string:
@@ -249,4 +256,10 @@
 
 	switch (lcur_lc(parse)) {
+	case lc_bool:
+		tlc = tlc_bool;
+		break;
+	case lc_char:
+		tlc = tlc_char;
+		break;
 	case lc_int:
 		tlc = tlc_int;
Index: uspace/app/sbi/src/parse.c
===================================================================
--- uspace/app/sbi/src/parse.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/parse.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -156,4 +156,5 @@
 	stree_csimbr_t *csimbr;
 	stree_symbol_t *symbol;
+	stree_ident_t *targ_name;
 
 	switch (dclass) {
@@ -168,4 +169,12 @@
 	csi = stree_csi_new(cc);
 	csi->name = parse_ident(parse);
+
+	list_init(&csi->targ_names);
+
+	while (lcur_lc(parse) == lc_slash) {
+		lskip(parse);
+		targ_name = parse_ident(parse);
+		list_append(&csi->targ_names, targ_name);
+	}
 
 	symbol = stree_symbol_new(sc_csi);
Index: uspace/app/sbi/src/program.c
===================================================================
--- uspace/app/sbi/src/program.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
+++ uspace/app/sbi/src/program.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -0,0 +1,150 @@
+/*
+ * 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 Main module.
+ *
+ * Main entry point for SBI, the Sysel Bootstrap Interpreter.
+ * When run without parameters, the interpreter will enter interactive
+ * mode.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "os/os.h"
+#include "mytypes.h"
+#include "stype.h"
+#include "input.h"
+#include "lex.h"
+#include "parse.h"
+
+#include "program.h"
+
+#define MAX_NAME_SIZE 64
+static char name_buf[MAX_NAME_SIZE + 1];
+
+/** Process one specified source file.
+ *
+ * @param program 	The program to which the parsed code is added.
+ * @param fname		Name of file to read from.
+ * @return		EOK on success, EIO if file is not found,
+ *			EINVAL if file has syntax errors.
+ */
+int program_file_process(stree_program_t *program, const char *fname)
+{
+	input_t *input;
+	lex_t lex;
+	parse_t parse;
+	int rc;
+
+	rc = input_new_file(&input, fname);
+	if (rc != EOK) {
+		printf("Failed opening source file '%s'.\n", fname);
+		return EIO;
+	}
+
+	/* Parse input file. */
+	lex_init(&lex, input);
+	parse_init(&parse, program, &lex);
+	parse_module(&parse);
+
+	/* Check for parse errors. */
+	if (parse.error)
+		return EINVAL;
+
+	return EOK;
+}
+
+/** Process sources of the library. 
+ *
+ * Processes all source files in the library. The list of library source files
+ * is read from '<libdir>/libflist'. Each line of the file contains one file
+ * name relative to <libdir>.
+ */
+int program_lib_process(stree_program_t *program)
+{
+	int rc;
+	char *path, *fname;
+	char *tmp;
+	char *cp;
+
+	FILE *f;
+
+	path = os_get_lib_path();
+	fname = os_str_acat(path, "/libflist");
+
+	f = fopen(fname, "rt");
+	if (f == NULL) {
+		printf("Failed opening library list file '%s'.\n", fname);
+		free(path);
+		free(fname);
+		return EIO;
+	}
+
+	free(fname);
+
+	while (b_true) {
+		if (fgets(name_buf, MAX_NAME_SIZE + 1, f) == NULL)
+			break;
+
+		/*
+		 * Remove trailing newline, if present.
+		 */
+		cp = name_buf;
+		while (*cp != '\0' && *cp != '\n')
+			++cp;
+
+		if (*cp == '\n')
+			*cp = '\0';
+
+		tmp = os_str_acat(path, "/");
+		fname = os_str_acat(tmp, name_buf);
+		free(tmp);
+
+		rc = program_file_process(program, fname);
+		if (rc != EOK) {
+			free(fname);
+			free(path);
+			fclose(f);
+			return rc;
+		}
+
+		free(fname);
+	}
+
+	if (ferror(f)) {
+		printf("Error reading from library list file.\n");
+		free(path);
+		fclose(f);
+		return EIO;
+	}
+
+	free(path);
+	fclose(f);
+
+	return rc;
+}
Index: uspace/app/sbi/src/program.h
===================================================================
--- uspace/app/sbi/src/program.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
+++ uspace/app/sbi/src/program.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -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 PROGRAM_H_
+#define PROGRAM_H_
+
+#include "mytypes.h"
+
+int program_file_process(stree_program_t *program, const char *fname);
+int program_lib_process(stree_program_t *program);
+
+#endif
Index: uspace/app/sbi/src/rdata.c
===================================================================
--- uspace/app/sbi/src/rdata.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/rdata.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -51,7 +51,10 @@
 #include "mytypes.h"
 #include "stree.h"
+#include "symbol.h"
 
 #include "rdata.h"
 
+static void rdata_bool_copy(rdata_bool_t *src, rdata_bool_t **dest);
+static void rdata_char_copy(rdata_char_t *src, rdata_char_t **dest);
 static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest);
 static void rdata_string_copy(rdata_string_t *src, rdata_string_t **dest);
@@ -287,4 +290,38 @@
 }
 
+/** Allocate new boolean.
+ *
+ * @return	New boolean.
+ */
+rdata_bool_t *rdata_bool_new(void)
+{
+	rdata_bool_t *bool_v;
+
+	bool_v = calloc(1, sizeof(rdata_bool_t));
+	if (bool_v == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return bool_v;
+}
+
+/** Allocate new character.
+ *
+ * @return	New character.
+ */
+rdata_char_t *rdata_char_new(void)
+{
+	rdata_char_t *char_v;
+
+	char_v = calloc(1, sizeof(rdata_char_t));
+	if (char_v == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return char_v;
+}
+
 /** Allocate new integer.
  *
@@ -398,4 +435,10 @@
 
 	switch (src->vc) {
+	case vc_bool:
+		rdata_bool_copy(src->u.bool_v, &nvar->u.bool_v);
+		break;
+	case vc_char:
+		rdata_char_copy(src->u.char_v, &nvar->u.char_v);
+		break;
 	case vc_int:
 		rdata_int_copy(src->u.int_v, &nvar->u.int_v);
@@ -422,4 +465,26 @@
 
 	*dest = nvar;
+}
+
+/** Copy boolean.
+ *
+ * @param src		Source boolean.
+ * @param dest		Place to store pointer to new boolean.
+ */
+static void rdata_bool_copy(rdata_bool_t *src, rdata_bool_t **dest)
+{
+	*dest = rdata_bool_new();
+	(*dest)->value = src->value;
+}
+
+/** Copy character.
+ *
+ * @param src		Source character.
+ * @param dest		Place to store pointer to new character.
+ */
+static void rdata_char_copy(rdata_char_t *src, rdata_char_t **dest)
+{
+	*dest = rdata_char_new();
+	bigint_clone(&src->value, &(*dest)->value);
 }
 
@@ -550,4 +615,6 @@
 	var->vc = nvar->vc;
 	switch (nvar->vc) {
+	case vc_bool: var->u.bool_v = nvar->u.bool_v; break;
+	case vc_char: var->u.char_v = nvar->u.char_v; break;
 	case vc_int: var->u.int_v = nvar->u.int_v; break;
 	case vc_string: var->u.string_v = nvar->u.string_v; break;
@@ -621,5 +688,18 @@
 static void rdata_var_print(rdata_var_t *var)
 {
+	int val;
+
 	switch (var->vc) {
+	case vc_bool:
+		printf("bool(%s)", var->u.bool_v->value ? "true" : "false");
+		break;
+	case vc_char:
+		printf("char(");
+		if (bigint_get_value_int(&var->u.char_v->value, &val) == EOK)
+			printf("'%c'", val);
+		else
+			printf("???:x%x\n", (unsigned) val);
+		printf(")");
+		break;
 	case vc_int:
 		printf("int(");
@@ -631,15 +711,26 @@
 		break;
 	case vc_ref:
-		printf("ref");
+		printf("ref(");
+		rdata_var_print(var->u.ref_v->vref);
+		printf(")");
 		break;
 	case vc_deleg:
-		printf("deleg");
+		printf("deleg(");
+		if (var->u.deleg_v->obj != NULL) {
+			rdata_var_print(var->u.deleg_v->obj);
+			printf(",");
+		}
+		symbol_print_fqn(var->u.deleg_v->sym);
+		printf(")");
+		break;
+	case vc_array:
+		printf("array");
 		break;
 	case vc_object:
 		printf("object");
 		break;
-	default:
-		printf("print(%d)\n", var->vc);
-		assert(b_false);
-	}
-}
+	case vc_resource:
+		printf("resource(%p)", var->u.resource_v->data);
+		break;
+	}
+}
Index: uspace/app/sbi/src/rdata.h
===================================================================
--- uspace/app/sbi/src/rdata.h	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/rdata.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -45,4 +45,6 @@
 rdata_array_t *rdata_array_new(int rank);
 rdata_object_t *rdata_object_new(void);
+rdata_bool_t *rdata_bool_new(void);
+rdata_char_t *rdata_char_new(void);
 rdata_int_t *rdata_int_new(void);
 rdata_string_t *rdata_string_new(void);
Index: uspace/app/sbi/src/rdata_t.h
===================================================================
--- uspace/app/sbi/src/rdata_t.h	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/rdata_t.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -35,4 +35,18 @@
 #include "intmap_t.h"
 
+/** Boolean variable. */
+typedef struct {
+	bool_t value;
+} rdata_bool_t;
+
+/** Character variable.
+ *
+ * Sysel character type should be able to store arbitrarily (or at least
+ * very) large character sets.
+ */
+typedef struct {
+	bigint_t value;
+} rdata_char_t;
+
 /** Integer variable.
  *
@@ -43,5 +57,4 @@
 	bigint_t value;
 } rdata_int_t;
-
 
 /** String variable */
@@ -104,4 +117,10 @@
 
 typedef enum var_class {
+	/** Boolean */
+	vc_bool,
+
+	/** Character **/
+	vc_char,
+
 	/** Integer */
 	vc_int,
@@ -136,4 +155,6 @@
 
 	union {
+		rdata_bool_t *bool_v;
+		rdata_char_t *char_v;
 		rdata_int_t *int_v;
 		rdata_string_t *string_v;
Index: uspace/app/sbi/src/run.c
===================================================================
--- uspace/app/sbi/src/run.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/run.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -657,4 +657,5 @@
 void run_value_item_to_var(rdata_item_t *item, rdata_var_t **var)
 {
+	rdata_char_t *char_v;
 	rdata_int_t *int_v;
 	rdata_string_t *string_v;
@@ -666,4 +667,12 @@
 
 	switch (in_var->vc) {
+	case vc_char:
+		*var = rdata_var_new(vc_char);
+		char_v = rdata_char_new();
+
+		(*var)->u.char_v = char_v;
+		bigint_clone(&item->u.value->var->u.char_v->value,
+		    &char_v->value);
+		break;
 	case vc_int:
 		*var = rdata_var_new(vc_int);
Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/run_expr.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -53,4 +53,8 @@
 static void run_literal(run_t *run, stree_literal_t *literal,
     rdata_item_t **res);
+static void run_lit_bool(run_t *run, stree_lit_bool_t *lit_bool,
+    rdata_item_t **res);
+static void run_lit_char(run_t *run, stree_lit_char_t *lit_char,
+    rdata_item_t **res);
 static void run_lit_int(run_t *run, stree_lit_int_t *lit_int,
     rdata_item_t **res);
@@ -64,4 +68,8 @@
 
 static void run_binop(run_t *run, stree_binop_t *binop, rdata_item_t **res);
+static void run_binop_bool(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
+    rdata_value_t *v2, rdata_item_t **res);
+static void run_binop_char(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
+    rdata_value_t *v2, rdata_item_t **res);
 static void run_binop_int(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
     rdata_value_t *v2, rdata_item_t **res);
@@ -315,6 +323,11 @@
 	printf("Run literal.\n");
 #endif
-
 	switch (literal->ltc) {
+	case ltc_bool:
+		run_lit_bool(run, &literal->u.lit_bool, res);
+		break;
+	case ltc_char:
+		run_lit_char(run, &literal->u.lit_char, res);
+		break;
 	case ltc_int:
 		run_lit_int(run, &literal->u.lit_int, res);
@@ -326,7 +339,59 @@
 		run_lit_string(run, &literal->u.lit_string, res);
 		break;
-	default:
-		assert(b_false);
-	}
+	}
+}
+
+/** Evaluate Boolean literal. */
+static void run_lit_bool(run_t *run, stree_lit_bool_t *lit_bool,
+    rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_bool_t *bool_v;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run Boolean literal.\n");
+#endif
+	(void) run;
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_bool);
+	bool_v = rdata_bool_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.bool_v = bool_v;
+	bool_v->value = lit_bool->value;
+
+	*res = item;
+}
+
+/** Evaluate character literal. */
+static void run_lit_char(run_t *run, stree_lit_char_t *lit_char,
+    rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_char_t *char_v;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Run character literal.\n");
+#endif
+	(void) run;
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_char);
+	char_v = rdata_char_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.char_v = char_v;
+	bigint_clone(&lit_char->value, &char_v->value);
+
+	*res = item;
 }
 
@@ -486,4 +551,10 @@
 
 	switch (v1->var->vc) {
+	case vc_bool:
+		run_binop_bool(run, binop, v1, v2, res);
+		break;
+	case vc_char:
+		run_binop_char(run, binop, v1, v2, res);
+		break;
 	case vc_int:
 		run_binop_int(run, binop, v1, v2, res);
@@ -495,9 +566,127 @@
 		run_binop_ref(run, binop, v1, v2, res);
 		break;
+	case vc_deleg:
+	case vc_array:
+	case vc_object:
+	case vc_resource:
+		assert(b_false);
+	}
+}
+
+/** Evaluate binary operation on bool arguments. */
+static void run_binop_bool(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
+    rdata_value_t *v2, rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_bool_t *bool_v;
+
+	bool_t b1, b2;
+
+	(void) run;
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+	var = rdata_var_new(vc_bool);
+	bool_v = rdata_bool_new();
+
+	item->u.value = value;
+	value->var = var;
+	var->u.bool_v = bool_v;
+
+	b1 = v1->var->u.bool_v->value;
+	b2 = v2->var->u.bool_v->value;
+
+	switch (binop->bc) {
+	case bo_plus:
+	case bo_minus:
+	case bo_mult:
+		assert(b_false);
+
+	case bo_equal:
+		bool_v->value = (b1 == b2);
+		break;
+	case bo_notequal:
+		bool_v->value = (b1 != b2);
+		break;
+	case bo_lt:
+		bool_v->value = (b1 == b_false) && (b2 == b_true);
+		break;
+	case bo_gt:
+		bool_v->value = (b1 == b_true) && (b2 == b_false);
+		break;
+	case bo_lt_equal:
+		bool_v->value = (b1 == b_false) || (b2 == b_true);
+		break;
+	case bo_gt_equal:
+		bool_v->value = (b1 == b_true) || (b2 == b_false);
+		break;
+	}
+
+	*res = item;
+}
+
+/** Evaluate binary operation on char arguments. */
+static void run_binop_char(run_t *run, stree_binop_t *binop, rdata_value_t *v1,
+    rdata_value_t *v2, rdata_item_t **res)
+{
+	rdata_item_t *item;
+	rdata_value_t *value;
+	rdata_var_t *var;
+	rdata_bool_t *bool_v;
+
+	bigint_t *c1, *c2;
+	bigint_t diff;
+	bool_t zf, nf;
+
+	(void) run;
+
+	item = rdata_item_new(ic_value);
+	value = rdata_value_new();
+
+	item->u.value = value;
+
+	c1 = &v1->var->u.char_v->value;
+	c2 = &v2->var->u.char_v->value;
+
+	var = rdata_var_new(vc_bool);
+	bool_v = rdata_bool_new();
+	var->u.bool_v = bool_v;
+	value->var = var;
+
+	bigint_sub(c1, c2, &diff);
+	zf = bigint_is_zero(&diff);
+	nf = bigint_is_negative(&diff);
+
+	switch (binop->bc) {
+	case bo_plus:
+	case bo_minus:
+	case bo_mult:
+		assert(b_false);
+
+	case bo_equal:
+		bool_v->value = zf;
+		break;
+	case bo_notequal:
+		bool_v->value = !zf;
+		break;
+	case bo_lt:
+		bool_v->value = (!zf && nf);
+		break;
+	case bo_gt:
+		bool_v->value = (!zf && !nf);
+		break;
+	case bo_lt_equal:
+		bool_v->value = (zf || nf);
+		break;
+	case bo_gt_equal:
+		bool_v->value = !nf;
+		break;
 	default:
-		printf("Unimplemented: Binary operation arguments of "
-		    "type %d.\n", v1->var->vc);
-		exit(1);
-	}
+		assert(b_false);
+	}
+
+	*res = item;
 }
 
@@ -510,4 +699,5 @@
 	rdata_var_t *var;
 	rdata_int_t *int_v;
+	rdata_bool_t *bool_v;
 
 	bigint_t *i1, *i2;
@@ -520,10 +710,6 @@
 	item = rdata_item_new(ic_value);
 	value = rdata_value_new();
-	var = rdata_var_new(vc_int);
-	int_v = rdata_int_new();
 
 	item->u.value = value;
-	value->var = var;
-	var->u.int_v = int_v;
 
 	i1 = &v1->var->u.int_v->value;
@@ -534,10 +720,13 @@
 	switch (binop->bc) {
 	case bo_plus:
+		int_v = rdata_int_new();
 		bigint_add(i1, i2, &int_v->value);
 		break;
 	case bo_minus:
+		int_v = rdata_int_new();
 		bigint_sub(i1, i2, &int_v->value);
 		break;
 	case bo_mult:
+		int_v = rdata_int_new();
 		bigint_mul(i1, i2, &int_v->value);
 		break;
@@ -548,7 +737,15 @@
 
 	if (done) {
+		var = rdata_var_new(vc_int);
+		var->u.int_v = int_v;
+		value->var = var;
 		*res = item;
 		return;
 	}
+
+	var = rdata_var_new(vc_bool);
+	bool_v = rdata_bool_new();
+	var->u.bool_v = bool_v;
+	value->var = var;
 
 	/* Relational operation. */
@@ -558,23 +755,22 @@
 	nf = bigint_is_negative(&diff);
 
-	/* XXX We should have a real boolean type. */
 	switch (binop->bc) {
 	case bo_equal:
-		bigint_init(&int_v->value, zf ? 1 : 0);
+		bool_v->value = zf;
 		break;
 	case bo_notequal:
-		bigint_init(&int_v->value, !zf ? 1 : 0);
+		bool_v->value = !zf;
 		break;
 	case bo_lt:
-		bigint_init(&int_v->value, (!zf && nf) ? 1 : 0);
+		bool_v->value = (!zf && nf);
 		break;
 	case bo_gt:
-		bigint_init(&int_v->value, (!zf && !nf) ? 1 : 0);
+		bool_v->value = (!zf && !nf);
 		break;
 	case bo_lt_equal:
-		bigint_init(&int_v->value, (zf || nf) ? 1 : 0);
+		bool_v->value = (zf || nf);
 		break;
 	case bo_gt_equal:
-		bigint_init(&int_v->value, !nf ? 1 : 0);
+		bool_v->value = !nf;
 		break;
 	default:
@@ -631,5 +827,5 @@
 	rdata_value_t *value;
 	rdata_var_t *var;
-	rdata_int_t *int_v;
+	rdata_bool_t *bool_v;
 
 	rdata_var_t *ref1, *ref2;
@@ -639,10 +835,10 @@
 	item = rdata_item_new(ic_value);
 	value = rdata_value_new();
-	var = rdata_var_new(vc_int);
-	int_v = rdata_int_new();
+	var = rdata_var_new(vc_bool);
+	bool_v = rdata_bool_new();
 
 	item->u.value = value;
 	value->var = var;
-	var->u.int_v = int_v;
+	var->u.bool_v = bool_v;
 
 	ref1 = v1->var->u.ref_v->vref;
@@ -650,10 +846,9 @@
 
 	switch (binop->bc) {
-	/* XXX We should have a real boolean type. */
 	case bo_equal:
-		bigint_init(&int_v->value, (ref1 == ref2) ? 1 : 0);
+		bool_v->value = (ref1 == ref2);
 		break;
 	case bo_notequal:
-		bigint_init(&int_v->value, (ref1 != ref2) ? 1 : 0);
+		bool_v->value = (ref1 != ref2);
 		break;
 	default:
@@ -980,11 +1175,6 @@
 	    access->member_name);
 
-	if (member == NULL) {
-		printf("Error: CSI '");
-		symbol_print_fqn(deleg_v->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
@@ -1475,7 +1665,12 @@
 
 	if (rc1 != EOK || rc2 != EOK) {
+#ifdef DEBUG_RUN_TRACE
 		printf("Error: String index (value: %d) is out of range.\n",
 		    arg_val);
-		exit(1);
+#endif
+		/* Raise Error.OutOfBounds */
+		run_raise_exc(run, run->program->builtin->error_outofbounds);
+		*res = run_recovery_item(run);
+		return;
 	}
 
@@ -1485,7 +1680,7 @@
 	ritem->u.value = value;
 
-	cvar = rdata_var_new(vc_int);
-	cvar->u.int_v = rdata_int_new();
-	bigint_init(&cvar->u.int_v->value, cval);
+	cvar = rdata_var_new(vc_char);
+	cvar->u.char_v = rdata_char_new();
+	bigint_init(&cvar->u.char_v->value, cval);
 	value->var = cvar;
 
@@ -1651,6 +1846,4 @@
  * Tries to interpret @a item as a boolean value. If it is not a boolean
  * value, this generates an error.
- *
- * XXX Currently int supplants the role of a true boolean type.
  */
 bool_t run_item_boolean_value(run_t *run, rdata_item_t *item)
@@ -1665,9 +1858,5 @@
 	var = vitem->u.value->var;
 
-	if (var->vc != vc_int) {
-		printf("Error: Boolean (int) expression expected.\n");
-		exit(1);
-	}
-
-	return !bigint_is_zero(&var->u.int_v->value);
-}
+	assert(var->vc == vc_bool);
+	return var->u.bool_v->value;
+}
Index: uspace/app/sbi/src/run_texpr.c
===================================================================
--- uspace/app/sbi/src/run_texpr.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/run_texpr.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -33,4 +33,5 @@
 #include "list.h"
 #include "mytypes.h"
+#include "strtab.h"
 #include "symbol.h"
 #include "tdata.h"
@@ -46,4 +47,6 @@
 static void run_tnameref(stree_program_t *prog, stree_csi_t *ctx,
     stree_tnameref_t *tnameref, tdata_item_t **res);
+static void run_tapply(stree_program_t *prog, stree_csi_t *ctx,
+    stree_tapply_t *tapply, tdata_item_t **res);
 
 void run_texpr(stree_program_t *prog, stree_csi_t *ctx, stree_texpr_t *texpr,
@@ -64,7 +67,6 @@
 		break;
 	case tc_tapply:
-		printf("Unimplemented: Evaluate type expression type %d.\n",
-		    texpr->tc);
-		exit(1);
+		run_tapply(prog, ctx, texpr->u.tapply, res);
+		break;
 	}
 }
@@ -85,7 +87,13 @@
 	run_texpr(prog, ctx, taccess->arg, &targ_i);
 
+	if (targ_i->tic == tic_ignore) {
+		*res = tdata_item_new(tic_ignore);
+		return;
+	}
+
 	if (targ_i->tic != tic_tobject) {
 		printf("Error: Using '.' with type which is not an object.\n");
-		exit(1);
+		*res = tdata_item_new(tic_ignore);
+		return;
 	}
 
@@ -94,7 +102,12 @@
 
 	sym = symbol_lookup_in_csi(prog, base_csi, taccess->member_name);
-
-	/* Existence should have been verified in type checking phase. */
-	assert(sym != NULL);
+	if (sym == NULL) {
+		printf("Error: CSI '");
+		symbol_print_fqn(csi_to_symbol(base_csi));
+		printf("' has no member named '%s'.\n",
+		    strtab_get_str(taccess->member_name->sid));
+		*res = tdata_item_new(tic_ignore);
+		return;
+	}
 
 	if (sym->sc != sc_csi) {
@@ -102,5 +115,6 @@
 		symbol_print_fqn(sym);
 		printf("' is not a CSI.\n");
-		exit(1);
+		*res = tdata_item_new(tic_ignore);
+		return;
 	}
 
@@ -130,4 +144,9 @@
 	/* Evaluate base type. */
 	run_texpr(prog, ctx, tindex->base_type, &base_ti);
+
+	if (base_ti->tic == tic_ignore) {
+		*res = tdata_item_new(tic_ignore);
+		return;
+	}
 
 	/* Construct type item. */
@@ -167,4 +186,6 @@
 
 	switch (tliteral->tlc) {
+	case tlc_bool: tpc = tpc_bool; break;
+	case tlc_char: tpc = tpc_char; break;
 	case tlc_int: tpc = tpc_int; break;
 	case tlc_string: tpc = tpc_string; break;
@@ -191,7 +212,10 @@
 #endif
 	sym = symbol_lookup_in_csi(prog, ctx, tnameref->name);
-
-	/* Existence should have been verified in type-checking phase. */
-	assert(sym);
+	if (sym == NULL) {
+		printf("Error: Symbol '%s' not found.\n",
+		    strtab_get_str(tnameref->name->sid));
+		*res = tdata_item_new(tic_ignore);
+		return;
+	}
 
 	if (sym->sc != sc_csi) {
@@ -199,5 +223,6 @@
 		symbol_print_fqn(sym);
 		printf("' is not a CSI.\n");
-		exit(1);
+		*res = tdata_item_new(tic_ignore);
+		return;
 	}
 
@@ -212,2 +237,54 @@
 	*res = titem;
 }
+
+static void run_tapply(stree_program_t *prog, stree_csi_t *ctx,
+    stree_tapply_t *tapply, tdata_item_t **res)
+{
+	tdata_item_t *base_ti;
+	tdata_item_t *arg_ti;
+	tdata_item_t *titem;
+	tdata_object_t *tobject;
+
+	list_node_t *arg_n;
+	stree_texpr_t *arg;
+
+#ifdef DEBUG_RUN_TRACE
+	printf("Evaluating type apply operation.\n");
+#endif
+	/* Construct type item. */
+	titem = tdata_item_new(tic_tobject);
+	tobject = tdata_object_new();
+	titem->u.tobject = tobject;
+
+	/* Evaluate base (generic) type. */
+	run_texpr(prog, ctx, tapply->gtype, &base_ti);
+
+	if (base_ti->tic != tic_tobject) {
+		printf("Error: Base type of generic application is not "
+		    "a CSI.\n");
+		*res = tdata_item_new(tic_ignore);
+		return;
+	}
+
+	tobject->static_ref = b_false;
+	tobject->csi = base_ti->u.tobject->csi;
+	list_init(&tobject->targs);
+
+	/* Evaluate type arguments. */
+	arg_n = list_first(&tapply->targs);
+	while (arg_n != NULL) {
+		arg = list_node_data(arg_n, stree_texpr_t *);
+		run_texpr(prog, ctx, arg, &arg_ti);
+
+		if (arg_ti->tic == tic_ignore) {
+			*res = tdata_item_new(tic_ignore);
+			return;
+		}
+
+		list_append(&tobject->targs, arg_ti);
+
+		arg_n = list_next(&tapply->targs, arg_n);
+	}
+
+	*res = titem;
+}
Index: uspace/app/sbi/src/stree_t.h
===================================================================
--- uspace/app/sbi/src/stree_t.h	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/stree_t.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -54,4 +54,15 @@
 } stree_self_ref_t;
 
+/** Boolean literal */
+typedef struct {
+	bool_t value;
+} stree_lit_bool_t;
+
+/** Character literal */
+typedef struct {
+	bigint_t value;
+} stree_lit_char_t;
+
+/** Integer literal */
 typedef struct {
 	bigint_t value;
@@ -62,4 +73,5 @@
 } stree_lit_ref_t;
 
+/** String literal */
 typedef struct {
 	char *value;
@@ -67,4 +79,6 @@
 
 typedef enum {
+	ltc_bool,
+	ltc_char,
 	ltc_int,
 	ltc_ref,
@@ -76,4 +90,6 @@
 	literal_class_t ltc;
 	union {
+		stree_lit_bool_t lit_bool;
+		stree_lit_char_t lit_char;
 		stree_lit_int_t lit_int;
 		stree_lit_ref_t lit_ref;
@@ -214,4 +230,6 @@
 /** Type literal class */
 typedef enum {
+	tlc_bool,
+	tlc_char,
 	tlc_int,
 	tlc_resource,
@@ -239,6 +257,9 @@
 /** Type application operation */
 typedef struct {
-	/** Arguments */
-	struct stree_texpr *gtype, *targ;
+	/* Base type */
+	struct stree_texpr *gtype;
+
+	/** (Formal) type arguments */
+	list_t targs; /* of stree_texpr_t */
 } stree_tapply_t;
 
@@ -496,4 +517,7 @@
 	stree_ident_t *name;
 
+	/** List of type argument names */
+	list_t targ_names; /* of stree_ident_t */
+
 	/** Symbol for this CSI */
 	struct stree_symbol *symbol;
Index: uspace/app/sbi/src/stype.c
===================================================================
--- uspace/app/sbi/src/stype.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/stype.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -64,6 +64,4 @@
 static void stype_wef(stype_t *stype, stree_wef_t *wef_s);
 
-static tdata_item_t *stype_boolean_titem(stype_t *stype);
-
 /** Type module */
 void stype_module(stype_t *stype, stree_module_t *module)
@@ -189,6 +187,16 @@
 static void stype_var(stype_t *stype, stree_var_t *var)
 {
+	tdata_item_t *titem;
+
 	(void) stype;
 	(void) var;
+
+	run_texpr(stype->program, stype->current_csi, var->type,
+	    &titem);
+	if (titem->tic == tic_ignore) {
+		/* An error occured. */
+		stype_note_error(stype);
+		return;
+	}
 }
 
@@ -283,4 +291,5 @@
 	stype_block_vr_t *block_vr;
 	stree_vdecl_t *old_vdecl;
+	tdata_item_t *titem;
 
 #ifdef DEBUG_TYPE_TRACE
@@ -297,6 +306,13 @@
 	}
 
+	run_texpr(stype->program, stype->current_csi, vdecl_s->type,
+	    &titem);
+	if (titem->tic == tic_ignore) {
+		/* An error occured. */
+		stype_note_error(stype);
+		return;
+	}
+
 	intmap_set(&block_vr->vdecls, vdecl_s->name->sid, vdecl_s);
-
 }
 
@@ -524,5 +540,5 @@
 			goto failure;
 		break;
-	default:
+	case tic_tfun:
 		printf("Error: Unimplemented: Converting '");
 		tdata_item_print(src);
@@ -531,4 +547,7 @@
 		printf("'.\n");
 		stype_note_error(stype);
+		break;
+	case tic_ignore:
+		assert(b_false);
 	}
 
@@ -547,5 +566,5 @@
 
 /** Return a boolean type item */
-static tdata_item_t *stype_boolean_titem(stype_t *stype)
+tdata_item_t *stype_boolean_titem(stype_t *stype)
 {
 	tdata_item_t *titem;
@@ -554,7 +573,6 @@
 	(void) stype;
 
-	/* XXX Use a true boolean type */
 	titem = tdata_item_new(tic_tprimitive);
-	tprimitive = tdata_primitive_new(tpc_int);
+	tprimitive = tdata_primitive_new(tpc_bool);
 	titem->u.tprimitive = tprimitive;
 
Index: uspace/app/sbi/src/stype.h
===================================================================
--- uspace/app/sbi/src/stype.h	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/stype.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -41,4 +41,6 @@
     tdata_item_t *dest);
 
+tdata_item_t *stype_boolean_titem(stype_t *stype);
+
 stree_vdecl_t *stype_local_vars_lookup(stype_t *stype, sid_t name);
 stree_proc_arg_t *stype_proc_args_lookup(stype_t *stype, sid_t name);
Index: uspace/app/sbi/src/stype_expr.c
===================================================================
--- uspace/app/sbi/src/stype_expr.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/stype_expr.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -53,6 +53,20 @@
 static void stype_binop(stype_t *stype, stree_binop_t *binop,
     tdata_item_t **rtitem);
+
 static void stype_binop_tprimitive(stype_t *stype, stree_binop_t *binop,
     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem);
+static void stype_binop_bool(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem);
+static void stype_binop_char(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem);
+static void stype_binop_int(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem);
+static void stype_binop_nil(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem);
+static void stype_binop_string(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem);
+static void stype_binop_resource(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem);
+
 static void stype_binop_tobject(stype_t *stype, stree_binop_t *binop,
     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem);
@@ -73,6 +87,4 @@
 static void stype_access_tarray(stype_t *stype, stree_access_t *access,
     tdata_item_t *arg_ti, tdata_item_t **rtitem);
-static void stype_access_tgeneric(stype_t *stype, stree_access_t *access,
-    tdata_item_t *arg_ti, tdata_item_t **rtitem);
 
 static void stype_call(stype_t *stype, stree_call_t *call,
@@ -86,6 +98,4 @@
     tdata_item_t *base_ti, tdata_item_t **rtitem);
 static void stype_index_tarray(stype_t *stype, stree_index_t *index,
-    tdata_item_t *base_ti, tdata_item_t **rtitem);
-static void stype_index_tgeneric(stype_t *stype, stree_index_t *index,
     tdata_item_t *base_ti, tdata_item_t **rtitem);
 
@@ -248,4 +258,6 @@
 
 	switch (literal->ltc) {
+	case ltc_bool: tpc = tpc_bool; break;
+	case ltc_char: tpc = tpc_char; break;
 	case ltc_int: tpc = tpc_int; break;
 	case ltc_ref: tpc = tpc_nil; break;
@@ -333,37 +345,59 @@
 }
 
-/** Type a binary operation arguments of primitive type. */
+/** Type a binary operation with arguments of primitive type. */
 static void stype_binop_tprimitive(stype_t *stype, stree_binop_t *binop,
     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem)
 {
+	assert(ta->tic == tic_tprimitive);
+	assert(tb->tic == tic_tprimitive);
+
+	switch (ta->u.tprimitive->tpc) {
+	case tpc_bool:
+		stype_binop_bool(stype, binop, rtitem);
+		break;
+	case tpc_char:
+		stype_binop_char(stype, binop, rtitem);
+		break;
+	case tpc_int:
+		stype_binop_int(stype, binop, rtitem);
+		break;
+	case tpc_nil:
+		stype_binop_nil(stype, binop, rtitem);
+		break;
+	case tpc_string:
+		stype_binop_string(stype, binop, rtitem);
+		break;
+	case tpc_resource:
+		stype_binop_resource(stype, binop, rtitem);
+		break;
+	}
+}
+
+/** Type a binary operation with bool arguments. */
+static void stype_binop_bool(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem)
+{
 	tprimitive_class_t rtpc;
 	tdata_item_t *res_ti;
 
-	(void) stype;
-
-	assert(ta->tic == tic_tprimitive);
-	assert(tb->tic == tic_tprimitive);
-
-	switch (ta->u.tprimitive->tpc) {
-	case tpc_int:
-		rtpc = tpc_int;
-		break;
-	case tpc_nil:
-		printf("Unimplemented; Binary operation on nil.\n");
-		stype_note_error(stype);
-		rtpc = tpc_nil;
-		break;
-	case tpc_string:
-		if (binop->bc != bo_plus) {
-			printf("Unimplemented: Binary operation(%d) "
-			    "on strings.\n", binop->bc);
-			stype_note_error(stype);
-		}
-		rtpc = tpc_string;
-		break;
-	case tpc_resource:
-		printf("Error: Cannot apply operator to resource type.\n");
-		stype_note_error(stype);
-		rtpc = tpc_resource;
+	switch (binop->bc) {
+	case bo_equal:
+	case bo_notequal:
+	case bo_lt:
+	case bo_gt:
+	case bo_lt_equal:
+	case bo_gt_equal:
+		/* Comparison -> boolean type */
+		rtpc = tpc_bool;
+		break;
+	case bo_plus:
+	case bo_minus:
+	case bo_mult:
+		/* Arithmetic -> error */
+		printf("Error: Binary operation (%d) on booleans.\n",
+		    binop->bc);
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
 	}
 
@@ -374,5 +408,127 @@
 }
 
-/** Type a binary operation arguments of an object type. */
+/** Type a binary operation with char arguments. */
+static void stype_binop_char(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem)
+{
+	tprimitive_class_t rtpc;
+	tdata_item_t *res_ti;
+
+	(void) stype;
+
+	switch (binop->bc) {
+	case bo_equal:
+	case bo_notequal:
+	case bo_lt:
+	case bo_gt:
+	case bo_lt_equal:
+	case bo_gt_equal:
+		/* Comparison -> boolean type */
+		rtpc = tpc_bool;
+		break;
+	case bo_plus:
+	case bo_minus:
+	case bo_mult:
+		/* Arithmetic -> error */
+		printf("Error: Binary operation (%d) on characters.\n",
+		    binop->bc);
+		stype_note_error(stype);
+		rtpc = tpc_char;
+		break;
+	}
+
+	res_ti = tdata_item_new(tic_tprimitive);
+	res_ti->u.tprimitive = tdata_primitive_new(rtpc);
+
+	*rtitem = res_ti;
+}
+
+/** Type a binary operation with int arguments. */
+static void stype_binop_int(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem)
+{
+	tprimitive_class_t rtpc;
+	tdata_item_t *res_ti;
+
+	(void) stype;
+
+	switch (binop->bc) {
+	case bo_equal:
+	case bo_notequal:
+	case bo_lt:
+	case bo_gt:
+	case bo_lt_equal:
+	case bo_gt_equal:
+		/* Comparison -> boolean type */
+		rtpc = tpc_bool;
+		break;
+	case bo_plus:
+	case bo_minus:
+	case bo_mult:
+		/* Arithmetic -> int type */
+		rtpc = tpc_int;
+		break;
+	}
+
+	res_ti = tdata_item_new(tic_tprimitive);
+	res_ti->u.tprimitive = tdata_primitive_new(rtpc);
+
+	*rtitem = res_ti;
+}
+
+/** Type a binary operation with nil arguments. */
+static void stype_binop_nil(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem)
+{
+	(void) binop;
+
+	printf("Unimplemented; Binary operation on nil.\n");
+	stype_note_error(stype);
+	*rtitem = stype_recovery_titem(stype);
+}
+
+/** Type a binary operation with string arguments. */
+static void stype_binop_string(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem)
+{
+	tprimitive_class_t rtpc;
+	tdata_item_t *res_ti;
+
+	if (binop->bc != bo_plus) {
+		printf("Unimplemented: Binary operation(%d) "
+		    "on strings.\n", binop->bc);
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
+		return;
+	}
+
+	rtpc = tpc_string;
+
+	res_ti = tdata_item_new(tic_tprimitive);
+	res_ti->u.tprimitive = tdata_primitive_new(rtpc);
+
+	*rtitem = res_ti;
+}
+
+/** Type a binary operation with resource arguments. */
+static void stype_binop_resource(stype_t *stype, stree_binop_t *binop,
+    tdata_item_t **rtitem)
+{
+	tprimitive_class_t rtpc;
+	tdata_item_t *res_ti;
+
+	(void) binop;
+
+	printf("Error: Cannot apply operator to resource type.\n");
+	stype_note_error(stype);
+	rtpc = tpc_resource;
+
+	res_ti = tdata_item_new(tic_tprimitive);
+	res_ti->u.tprimitive = tdata_primitive_new(rtpc);
+
+	*rtitem = res_ti;
+}
+
+/** Type a binary operation with arguments of an object type. */
 static void stype_binop_tobject(stype_t *stype, stree_binop_t *binop,
     tdata_item_t *ta, tdata_item_t *tb, tdata_item_t **rtitem)
@@ -390,12 +546,12 @@
 	case bo_equal:
 	case bo_notequal:
-		/* Comparing objects -> boolean (XXX int for now) type */
-		res_ti = tdata_item_new(tic_tprimitive);
-		res_ti->u.tprimitive = tdata_primitive_new(tpc_int);
+		/* Comparing objects -> boolean type */
+		res_ti = stype_boolean_titem(stype);
 		break;
 	default:
 		printf("Error: Binary operation (%d) on objects.\n",
 		    binop->bc);
-		res_ti = NULL;
+		stype_note_error(stype);
+		*rtitem = stype_recovery_titem(stype);
 		return;
 	}
@@ -451,4 +607,7 @@
 
 	switch (ta->u.tprimitive->tpc) {
+	case tpc_bool:
+		rtpc = tpc_bool;
+		break;
 	case tpc_int:
 		rtpc = tpc_int;
@@ -480,4 +639,9 @@
 	 */
 	run_texpr(stype->program, stype->current_csi, new_op->texpr, rtitem);
+
+	if ((*rtitem)->tic == tic_ignore) {
+		/* An error occured when evaluating the type expression. */
+		stype_note_error(stype);
+	}
 }
 
@@ -510,7 +674,4 @@
 	case tic_tarray:
 		stype_access_tarray(stype, access, arg_ti, rtitem);
-		break;
-	case tic_tgeneric:
-		stype_access_tgeneric(stype, access, arg_ti, rtitem);
 		break;
 	case tic_tfun:
@@ -566,4 +727,5 @@
 		printf("' has no member named '%s'.\n",
 		    strtab_get_str(access->member_name->sid));
+		stype_note_error(stype);
 		*rtitem = stype_recovery_titem(stype);
 		return;
@@ -615,19 +777,4 @@
 
 	printf("Error: Unimplemented: Accessing array type '");
-	tdata_item_print(arg_ti);
-	printf("'.\n");
-	stype_note_error(stype);
-	*rtitem = stype_recovery_titem(stype);
-}
-
-/** Type a generic access operation. */
-static void stype_access_tgeneric(stype_t *stype, stree_access_t *access,
-    tdata_item_t *arg_ti, tdata_item_t **rtitem)
-{
-	(void) stype;
-	(void) access;
-	(void) rtitem;
-
-	printf("Error: Unimplemented: Accessing generic type '");
 	tdata_item_print(arg_ti);
 	printf("'.\n");
@@ -792,7 +939,4 @@
 		stype_index_tarray(stype, index, base_ti, rtitem);
 		break;
-	case tic_tgeneric:
-		stype_index_tgeneric(stype, index, base_ti, rtitem);
-		break;
 	case tic_tfun:
 		printf("Error: Indexing a function.\n");
@@ -821,5 +965,5 @@
 	if (tprimitive->tpc == tpc_string) {
 		titem = tdata_item_new(tic_tprimitive);
-		titem->u.tprimitive = tdata_primitive_new(tpc_int);
+		titem->u.tprimitive = tdata_primitive_new(tpc_char);
 		*rtitem = titem;
 		return;
@@ -914,19 +1058,4 @@
 }
 
-/** Type a generic indexing operation. */
-static void stype_index_tgeneric(stype_t *stype, stree_index_t *index,
-    tdata_item_t *base_ti, tdata_item_t **rtitem)
-{
-	(void) stype;
-	(void) index;
-	(void) rtitem;
-
-	printf("Error: Unimplemented: Indexing generic type '");
-	tdata_item_print(base_ti);
-	printf("'.\n");
-	stype_note_error(stype);
-	*rtitem = stype_recovery_titem(stype);
-}
-
 /** Type an assignment. */
 static void stype_assign(stype_t *stype, stree_assign_t *assign,
Index: uspace/app/sbi/src/symbol.c
===================================================================
--- uspace/app/sbi/src/symbol.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/symbol.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -68,6 +68,6 @@
 		return b;
 	case tc_tapply:
-		printf("Internal error: Generic types not implemented.\n");
-		exit(1);
+		return symbol_xlookup_in_csi(prog, scope,
+		    texpr->u.tapply->gtype);
 	default:
 		assert(b_false);
Index: uspace/app/sbi/src/tdata.c
===================================================================
--- uspace/app/sbi/src/tdata.c	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/tdata.c	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -31,4 +31,5 @@
 #include <stdlib.h>
 #include <assert.h>
+#include "list.h"
 #include "mytypes.h"
 #include "stree.h"
@@ -40,5 +41,4 @@
 static void tdata_tobject_print(tdata_object_t *tobject);
 static void tdata_tarray_print(tdata_array_t *tarray);
-static void tdata_tgeneric_print(tdata_generic_t *tgeneric);
 static void tdata_tfun_print(tdata_fun_t *tfun);
 
@@ -142,7 +142,4 @@
 		tdata_tarray_print(titem->u.tarray);
 		break;
-	case tic_tgeneric:
-		tdata_tgeneric_print(titem->u.tgeneric);
-		break;
 	case tic_tfun:
 		tdata_tfun_print(titem->u.tfun);
@@ -157,4 +154,6 @@
 {
 	switch (tprimitive->tpc) {
+	case tpc_bool: printf("bool"); break;
+	case tpc_char: printf("char"); break;
 	case tpc_int: printf("int"); break;
 	case tpc_nil: printf("nil"); break;
@@ -167,8 +166,18 @@
 {
 	stree_symbol_t *csi_sym;
+	list_node_t *arg_n;
+	tdata_item_t *arg;
 
 	csi_sym = csi_to_symbol(tobject->csi);
 	assert(csi_sym != NULL);
 	symbol_print_fqn(csi_sym);
+
+	arg_n = list_first(&tobject->targs);
+	while (arg_n != NULL) {
+		arg = list_node_data(arg_n, tdata_item_t *);
+		putchar('/');
+		tdata_item_print(arg);
+		arg_n = list_next(&tobject->targs, arg_n);
+	}
 }
 
@@ -185,10 +194,4 @@
 }
 
-static void tdata_tgeneric_print(tdata_generic_t *tgeneric)
-{
-	(void) tgeneric;
-	printf("unimplemented(generic)");
-}
-
 static void tdata_tfun_print(tdata_fun_t *tfun)
 {
Index: uspace/app/sbi/src/tdata_t.h
===================================================================
--- uspace/app/sbi/src/tdata_t.h	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/app/sbi/src/tdata_t.h	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -34,4 +34,8 @@
 /** Class of primitive type. */
 typedef enum {
+	/** Boolean type */
+	tpc_bool,
+	/** Character type */
+	tpc_char,
 	/** Integer type */
 	tpc_int,
@@ -57,4 +61,7 @@
 	/** CSI definition */
 	struct stree_csi *csi;
+
+	/** (Real) type arguments */
+	list_t targs; /* of tdata_item_t */
 } tdata_object_t;
 
@@ -70,8 +77,4 @@
 	list_t extents; /* of stree_expr_t */
 } tdata_array_t;
-
-/** Generic type. */
-typedef struct {
-} tdata_generic_t;
 
 /** Functional type. */
@@ -90,6 +93,4 @@
 	/** Array type item */
 	tic_tarray,
-	/** Generic type item */
-	tic_tgeneric,
 	/** Function type item */
 	tic_tfun,
@@ -106,5 +107,4 @@
 		tdata_object_t *tobject;
 		tdata_array_t *tarray;
-		tdata_generic_t *tgeneric;
 		tdata_fun_t *tfun;
 	} u;
Index: uspace/dist/src/sysel/demos/list.sy
===================================================================
--- uspace/dist/src/sysel/demos/list.sy	(revision 2721a75a80b078ca942208aff692e091cec7496b)
+++ uspace/dist/src/sysel/demos/list.sy	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -27,109 +27,18 @@
 --
 
--- Doubly-linked list implementation.
-class List is
-	var head : ListNode;
-
-	-- Initialize list.
-	fun Init() is
-		head = new ListNode();
-		head.prev = head;
-		head.next = head;
-	end
-
-	-- Append new entry at the end of the list.
-	fun Append(data : int) is
-		var n : ListNode;
-		var ntl : ListNode;
-
-		ntl = head.prev;
-
-		n = new ListNode();
-		n.value = data;
-
-		n.prev = ntl;
-		n.next = head;
-		n.head = head;
-
-		ntl.next = n;
-		head.prev = n;
-	end
-
-	-- Return first node in the list or @c nil if there is none.
-	prop First : ListNode is
-		get is
-		    return get_first();
-		end
-	end
-
-	-- Return first node in the list or @c nil if there is none.
-	fun get_first() : ListNode is
-		if head.next == head then
-			return nil;
-		else
-			return head.next;
-		end
-	end
-end
-
-class ListNode is
-	var value : int;
-
-	var prev : ListNode;
-	var next : ListNode;
-	var head : ListNode;
-
-	-- Value stored in this node.
-	prop Value : int is
-		get is
-			return value;
-		end
-	end
-
-	-- Previous node in list.
-	prop Prev : ListNode is
-		get is
-			return get_prev();
-		end
-	end
-
-	-- Next node in list.
-	prop Next : ListNode is
-		get is
-			return get_next();
-		end
-	end
-
-	-- Get next node.
-	fun get_next() : ListNode is
-		if next != head then
-			return next;
-		else
-			return nil;
-		end
-	end
-
-	-- Get previous node.
-	fun get_prev() : ListNode is
-		if prev != head then
-			return next;
-		else
-			return nil;
-		end
-	end
-
-end
-
+-- Using the List class from the library.
 class ListDemo is
 	fun Main() is
 		var list : List;
+		var i : Int;
 
 		list = new List();
 		list.Init();
 
-		list.Append(5);
-		list.Append(6);
-		list.Append(7);
-		list.Append(8);
+		-- We need autoboxing or generics to get rid of this mess.
+		i = new Int(); i.Value = 5; list.Append(i);
+		i = new Int(); i.Value = 6; list.Append(i);
+		i = new Int(); i.Value = 7; list.Append(i);
+		i = new Int(); i.Value = 8; list.Append(i);
 
 		var n : ListNode;
@@ -137,5 +46,5 @@
 		n = list.First;
 		while n != nil do
-			Builtin.WriteLine(n.value);
+			Builtin.WriteLine((n.value as Int).Value);
 			n = n.Next;
 		end
Index: uspace/dist/src/sysel/lib/arith.sy
===================================================================
--- uspace/dist/src/sysel/lib/arith.sy	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
+++ uspace/dist/src/sysel/lib/arith.sy	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -0,0 +1,45 @@
+--
+-- 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 Arith is
+	-- Return factorial of n.
+	fun Factorial(n : int) : int is
+		var i : int;
+		var val : int;
+
+		i = 1;
+		val = 1;
+
+		while i <= n do
+			val = val * i;
+			i = i + 1;
+		end
+
+		return val;
+	end
+end
Index: uspace/dist/src/sysel/lib/boxed.sy
===================================================================
--- uspace/dist/src/sysel/lib/boxed.sy	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
+++ uspace/dist/src/sysel/lib/boxed.sy	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -0,0 +1,47 @@
+--
+-- 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.
+--
+
+--
+-- Declarations for boxed variants of primitive types.
+--
+
+class Bool is
+	var Value : bool;
+end
+
+class Char is
+	var Value : char;
+end
+
+class Int is
+	var Value : int;
+end
+
+class String is
+	var Value : string;
+end
Index: uspace/dist/src/sysel/lib/libflist
===================================================================
--- uspace/dist/src/sysel/lib/libflist	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
+++ uspace/dist/src/sysel/lib/libflist	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -0,0 +1,3 @@
+arith.sy
+boxed.sy
+list.sy
Index: uspace/dist/src/sysel/lib/list.sy
===================================================================
--- uspace/dist/src/sysel/lib/list.sy	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
+++ uspace/dist/src/sysel/lib/list.sy	(revision 1ef0fc3af9d3036d613efbe2d4cfb0ce271abed0)
@@ -0,0 +1,121 @@
+--
+-- 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.
+--
+
+-- Doubly-linked non-generic list.
+class List is
+	var head : ListNode;
+
+	-- Initialize list.
+	fun Init() is
+		head = new ListNode();
+		head.prev = head;
+		head.next = head;
+	end
+
+	-- Append new entry at the end of the list.
+	fun Append(data : Object) is
+		var n : ListNode;
+		var ntl : ListNode;
+
+		ntl = head.prev;
+
+		n = new ListNode();
+		n.value = data;
+
+		n.prev = ntl;
+		n.next = head;
+		n.head = head;
+
+		ntl.next = n;
+		head.prev = n;
+	end
+
+	-- Return first node in the list or @c nil if there is none.
+	prop First : ListNode is
+		get is
+		    return get_first();
+		end
+	end
+
+	-- Return first node in the list or @c nil if there is none.
+	fun get_first() : ListNode is
+		if head.next == head then
+			return nil;
+		else
+			return head.next;
+		end
+	end
+end
+
+class ListNode is
+	var value : Object;
+
+	var prev : ListNode;
+	var next : ListNode;
+	var head : ListNode;
+
+	-- Value stored in this node.
+	prop Value : Object is
+		get is
+			return value;
+		end
+	end
+
+	-- Previous node in list.
+	prop Prev : ListNode is
+		get is
+			return get_prev();
+		end
+	end
+
+	-- Next node in list.
+	prop Next : ListNode is
+		get is
+			return get_next();
+		end
+	end
+
+	-- Get next node.
+	fun get_next() : ListNode is
+		if next != head then
+			return next;
+		else
+			return nil;
+		end
+	end
+
+	-- Get previous node.
+	fun get_prev() : ListNode is
+		if prev != head then
+			return next;
+		else
+			return nil;
+		end
+	end
+
+end
