G

G Programming Language
git clone http://git.omkov.net/G
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2024-01-30 07:33:09
Commit753057649be967f0151bea80de863738a9d6879f
Parentce98c7aaef741ab5cda0560f446e77a34f718822

Remove all trailing whitespace

Diffstat

M README.md | 2 +-
M doc/g.ebnf | 14 +++++++-------
M examples/io.g | 4 ++--
M examples/loop.g | 2 +-
M examples/map.g.theoretical | 20 ++++++++++----------
M src/analyse.c | 52 +++++++++++++++++++++++++---------------------------
M src/init.c | 16 ++++++++--------
M src/lex.c | 65 ++++++++++++++++++++++++++++++++---------------------------------
M src/lex.h | 10 +++++-----
M src/llvm.c | 144 ++++++++++++++++++++++++++++++++++++++++----------------------------------------
M src/llvm/attr.c | 2 +-
M src/log.c | 6 +++---
M src/main.c | 11 -----------
M src/parse.c | 164 ++++++++++++++++++++++++++++++++++++++++----------------------------------------
M src/parse.h | 18 +++++++++---------
M src/symbol.c | 48 ++++++++++++++++++++++++------------------------
M src/type.c | 25 +------------------------
M src/type.h | 22 +++++++++++-----------
M src/util/optget.c | 20 ++++++++++----------

19 files changed, 304 insertions, 341 deletions

diff --git a/README.md b/README.md
index 2c8da9c..bd98461 100644
--- a/README.md
+++ b/README.md
@@ -96,5 +96,5 @@ command. The second command will output an executable file, *a.out* by default.
 
 ## Meta
 
-Copyright (C) 2021, Jakob Wakeling  
+Copyright (C) 2024, Jakob Wakeling  
 All rights reserved.
diff --git a/doc/g.ebnf b/doc/g.ebnf
index 7d9397b..9a5d36a 100644
--- a/doc/g.ebnf
+++ b/doc/g.ebnf
@@ -23,7 +23,7 @@ stmt_for    = "for", "(", expr, [ ";", expr ], [ ";", expr ], ")", stmt ;
 (* Expressions *)
 expr = iden | literal
      | expr_proc
-     
+
      | "(", expr, ")"
      | type, "(", expr, ")" (* Type cast *)
      | iden, "(", [ expr, { ",", expr } ], ")" (* Procedure call *)
@@ -31,21 +31,21 @@ expr = iden | literal
      | "#", iden, [ "(", [ expr, { ",", expr } ], ")" ] (* Hash expression *)
      | "+", expr | "-", expr (* Unary POS and NEG *)
      | "!", expr | "~", expr (* Logical and bitwise NOT *)
-     
+
      | expr, "*", expr | expr, "/",  expr | expr, "%",  expr
      | expr, "&", expr | expr, "<<", expr | expr, ">>", expr
-     
+
      | expr, "+", expr | expr, "-", expr (* Binary ADD and SUB *)
      | expr, "|", expr | expr, "^", expr (* Bitwise OR and XOR *)
-     
+
      | expr, "==", expr | expr, "!=", expr (* EQ and NEQ *)
      | expr, "<",  expr | expr, "<=", expr (* LT and LTE *)
      | expr, ">",  expr | expr, ">=", expr (* GT and GTE *)
-     
+
      | expr, "&&", expr | expr, "||", expr (* Logical AND and OR *)
-     
+
      | expr, "?", expr, ":", expr (* Ternary operator *)
-     
+
      | iden, "=",   expr | iden, "+="  expr | iden, "-=" expr
      | iden, "*=",  expr | iden, "/="  expr | iden, "%=" expr
      | iden, "&=",  expr | iden, "|="  expr | iden, "^=" expr
diff --git a/examples/io.g b/examples/io.g
index 6bbac3e..dd75f13 100644
--- a/examples/io.g
+++ b/examples/io.g
@@ -1,11 +1,11 @@
 main :: proc() sint {
 	file : string = "g.txt";
 	body : string = "Output\n";
-	
+
 	/* Open file with O_WRONLY and O_CREAT flags */
 	fd : sint = #syscall(uint(2), cstring(file), s32(0b1000010), u16(0o644));
 	r : sint = #syscall(uint(1), fd, cstring(body), len(body));
 	#syscall(uint(3), fd);
-	
+
 	return r;
 }
diff --git a/examples/loop.g b/examples/loop.g
index c679822..6071de1 100644
--- a/examples/loop.g
+++ b/examples/loop.g
@@ -4,6 +4,6 @@ main :: proc() u8 {
 		#syscall(uint(1), uint(1), &c, uint(1));
 		#syscall(uint(1), uint(1), &nl, uint(1));
 	}
-	
+
 	return 0;
 }
diff --git a/examples/map.g.theoretical b/examples/map.g.theoretical
index 1a8b1ea..47081f4 100644
--- a/examples/map.g.theoretical
+++ b/examples/map.g.theoretical
@@ -18,7 +18,7 @@ define LOAD_FACTOR 0.75;
 	Hashmap struct where K is the key type, V is the value type, a is the array
 	of key-value pairs, al is the number of items in the array, and ac is the
 	array capacity.
-	
+
 	The hashmap will resize itself when a load factor of 0.75 is reached. It
 	*will* also shadow values when a duplicate key is used. Entries *will* be
 	inserted using a robin hood hashing technique.
@@ -53,42 +53,42 @@ map :: struct($K: type, $V: type) {
 /*map.*/insert :: proc(m: &map($K, $V), k: K, v: V) -> ErrorOr() {
 	if (m.ac == 0 || m.al >= (m.ac * LOAD_FACTOR)) { /* Resize the map. */ }
 	h := hash(k); index: uint = h % m.ac;
-	
+
 	/* Find the next available empty bucket */
 	for (; m.a[index] /*is unset*/; index += 1) { if (index >= m.ac) { index = 0; } }
-	
+
 	m.a[index] = { h, k, v };
-	
+
 	return ErrorOr(); /* ??? */
 }
 
 /*
-	
+
 */
 /*map.*/lookup :: proc(m: &map($K, $V), k: K) -> ErrorOr(V) {
 	index: uint = hash(k) % m.ac;
-	
+
 	for (start: uint = index; m.a[index].k != k; index += 1) {
 		if (index >= m.ac) { index = 0; }
 		/* This doesnt account for the start being at the array start */
 		if (index + 1 == start) { return Error(); /* ??? */ }
 	}
-	
+
 	return ErrorOr(m.a[index].v); /* ??? */
 }
 
 /*
-	
+
 */
 /*map.*/remove :: proc(m: &map($K, $V), k: K) -> ErrorOr() {
 	index: uint = hash(k) % m.ac;
-	
+
 	for (start: uint = index; m.a[index].k != k; index += 1) {
 		if (index >= m.ac) { index = 0; }
 		/* This doesnt account for the start being at the array start */
 		if (index + 1 == start) { return Error(); /* ??? */ }
 	}
-	
+
 	return ErrorOr(); /* ??? */
 }
 
diff --git a/src/analyse.c b/src/analyse.c
index d4789e3..80170d5 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -47,7 +47,7 @@ static void analyse_stmt(ast *a, syt *st) {
 /* Analyse a compound statement. AK_COMP has a scope. */
 static inline void analyse_stmt_comp(ast *a, syt *st) {
 	assert(A.k == AK_COMP);
-	
+
 	for (uptr i = 0; i < CL; i += 1) { analyse_stmt(C[i], &A.st); }
 }
 
@@ -55,10 +55,10 @@ static inline void analyse_stmt_comp(ast *a, syt *st) {
 static void analyse_stmt_decl(ast *a, syt *st) {
 	assert(A.c.al == 0 || A.c.al == 1);
 	if (A.c.al == 0) { assert(A.t != null); return; }
-	
+
 	analyse_expr(C[0], st);
 	type *value_type = ast_type(C[0], st);
-	
+
 	if (C[0]->k == AK_PROC) {
 		A.t = &TYPE(TY_PROC);
 		return; /* TODO */
@@ -66,7 +66,7 @@ static void analyse_stmt_decl(ast *a, syt *st) {
 	else if (is_bool(value_type)) {
 		/* If a type has not been specified, set the type based on the value */
 		if (A.t == null) { A.t = C[0]->t; }
-		
+
 		/* If the type has been specified, check that the value is compatible */
 		else {
 			/* TODO */
@@ -76,24 +76,24 @@ static void analyse_stmt_decl(ast *a, syt *st) {
 		/* If a type has not been specified, set the type based on the value */
 		if (A.t == null) {
 			A.t = C[0]->t;
-			
+
 			/* If the value type is smaller than 32 bit, upgrade it */
 			if (A.t->l < 4) {
 				if (is_sign(A.t)) { A.t = &TYPE(TY_S32); }
 				else { A.t = &TYPE(TY_U32); }
-				
+
 				/* Insert a type cast node between parent and child */
 				/* FIXME this behaviour is incorrect, should only implicitely cast for literals, not all expressions */
 				ast *cast = ast_init(AK_CAST, C[0]->ln, C[0]->cl); cast->t = A.t;
-				
+
 				ast *child = C[0];
-				
+
 				ast_displace(a, child);
 				ast_push(cast, child);
 				ast_push(a, cast);
 			}
 		}
-		
+
 		/* If the type has been specified, check that the value is compatible */
 		else {
 			/* TODO */
@@ -102,24 +102,24 @@ static void analyse_stmt_decl(ast *a, syt *st) {
 	else if (is_flt(value_type)) {
 		/* If a type has not been specified, set the type based on the value */
 		if (A.t == null) { A.t = A.c.a[0]->t; }
-		
+
 		/* If the type has been specified, check that the value is compatible */
 		else {
 			/* TODO */
 		}
 	}
 	else if (value_type->k == TY_STRING) { if (A.t == null) { A.t = C[0]->t; } return; }
-	
+
 	else { note("TODO", A.ln, A.cl, -1, "Unhandled value kind %s", ast_ks[C[0]->k]); }
 }
 
 /* Analyse a return statement. */
 static void analyse_stmt_return(ast *a, syt *st) {
 	if (A.c.al == 1) { analyse_expr(C[0], st); }
-	
+
 	type *t = A.c.al != 0 ? ast_type(C[0], st) : &TYPE(TY_VOID);
 	ast *p = A.p; for (; p->k != AK_PROC; p = p->p);
-	
+
 	if (is_equal(t, &TYPE(TY_VOID)) && !is_equal(p->t, &TYPE(TY_VOID))) {
 		note("TODO", A.ln, A.cl, 0, "Non-void procedure \"%s\" should return a value", p->p->s);
 	}
@@ -137,7 +137,7 @@ static void analyse_stmt_return(ast *a, syt *st) {
 static void analyse_stmt_if(ast *a, syt *st) {
 	assert(A.k == AK_IF);
 	assert(CL == 3 || CL == 4);
-	
+
 	if (C[0]->k != AK_VOID) { analyse_stmt(C[0], &A.st); }
 	analyse_expr(C[1], &A.st); analyse_stmt(C[2], &A.st);
 	if (CL == 4) { analyse_stmt(C[3], &A.st); }
@@ -147,7 +147,7 @@ static void analyse_stmt_if(ast *a, syt *st) {
 static void analyse_stmt_for(ast *a, syt *st) {
 	assert(A.k == AK_FOR);
 	assert(CL == 2 || CL == 4);
-	
+
 	for (uptr i = 0; i < CL; i += 1) { analyse_stmt(C[i], &A.st); }
 }
 
@@ -166,20 +166,20 @@ static void analyse_expr(ast *a, syt *st) {
 		assert(C[0]->k == AK_ID);
 		assert(C[0]->h != 0);
 		assert(C[0]->s != null);
-		
+
 		analyse_expr(C[0], st); type *t = C[0]->t;
-		
+
 		ast *sym = syt_search_h(st, C[0]->h, C[0]->s);
 		if (sym == null) { note("TODO", A.ln, A.cl, 0, "Use of undeclared identifier \"%s\"", C[0]->s); }
-		
+
 		else if (sym->k == AK_TYPE) {
 			A.k = AK_CAST; A.t = sym->t;
 			if (CL > 2) { note("TODO", A.ln, A.cl, 0, "Type casts must only have a single argument"); }
 		}
 		else if (sym->k == AK_PROC) { A.k = AK_BUILTIN; A.t = sym->t; }
-		
+
 		for (uptr i = 1; i < CL; i += 1) { analyse_expr(C[i], st); }
-		
+
 		if (is_proc(t)) {
 			register ast **av = sym->c.a[0]->c.a; register uptr ac = sym->c.a[0]->c.al;
 			for (uptr i = 0; i < ac - 1; i += 1) {
@@ -188,7 +188,7 @@ static void analyse_expr(ast *a, syt *st) {
 					if (C[i + 1]->t->l <= av[i]->t->l) {
 						ast *cast = ast_init(AK_CAST, C[i + 1]->ln, C[i + 1]->cl); cast->t = av[i]->t;
 						ast *child = C[i + 1];
-						
+
 						ast_wrap(a, child, cast);
 					}
 					else {
@@ -210,7 +210,7 @@ static void analyse_expr(ast *a, syt *st) {
 	} break;
 	case AK_SUBS: {
 		assert(CL == 2);
-		
+
 		if (!is_int(ast_type(C[1], st))) {
 			note("TODO", A.ln, A.cl, 0, "Expression must have integral type");
 		}
@@ -236,12 +236,12 @@ static void analyse_expr(ast *a, syt *st) {
 /* Analyse a procedure expression. AK_PROC has a scope. */
 static void analyse_expr_proc(ast *a, syt *st) {
 	assert(A.k == AK_PROC);
-	
+
 	/* Analyse the procedure arguments */
 	for (uptr i = 0; i < CL - 1; i += 1) {
 		/* TODO */
 	}
-	
+
 	/* Analyse the procedure body */
 	analyse_stmt_comp(C[CL - 1], &A.st);
 }
@@ -249,9 +249,9 @@ static void analyse_expr_proc(ast *a, syt *st) {
 /* Analyse a hash expression. */
 static void analyse_expr_hash(ast *a, syt *st) {
 	assert(A.k == AK_HASH);
-	
+
 	if (strcmp(A.s, "syscall") == 0) { A.k = AK_HASH_SYSCALL; A.t = &TYPE(TY_SINT); }
 	else { note("TODO", A.ln, A.cl, 0, "Unrecognised hash expression \"%s\"", A.s); }
-	
+
 	for (uptr i = 0; i < CL; i += 1) { analyse_expr(C[i], st); }
 }
diff --git a/src/init.c b/src/init.c
index a555a61..c70417b 100644
--- a/src/init.c
+++ b/src/init.c
@@ -10,14 +10,14 @@
 
 static ast kwds[] = {
 	{ AK_TYPE, 0, 0, 0, "ptr", &TYPE(TY_PTR), { 0 }, null },
-	
+
 	/* Boolean Types */
 	{ AK_TYPE, 0, 0, 0, "bool", &TYPE(TY_BOOL), { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "b8",   &TYPE(TY_B8),   { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "b16",  &TYPE(TY_B16),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "b32",  &TYPE(TY_B32),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "b64",  &TYPE(TY_B64),  { 0 }, null },
-	
+
 	/* Integer Types */
 	{ AK_TYPE, 0, 0, 0, "uint", &TYPE(TY_UINT), { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "u8",   &TYPE(TY_U8),   { 0 }, null },
@@ -25,29 +25,29 @@ static ast kwds[] = {
 	{ AK_TYPE, 0, 0, 0, "u32",  &TYPE(TY_U32),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "u64",  &TYPE(TY_U64),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "u128", &TYPE(TY_U128), { 0 }, null },
-	
+
 	{ AK_TYPE, 0, 0, 0, "sint", &TYPE(TY_SINT), { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "s8",   &TYPE(TY_S8),   { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "s16",  &TYPE(TY_S16),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "s32",  &TYPE(TY_S32),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "s64",  &TYPE(TY_S64),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "s128", &TYPE(TY_S128), { 0 }, null },
-	
+
 	/* Floating Point Types */
 	{ AK_TYPE, 0, 0, 0, "f16",  &TYPE(TY_F32),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "f32",  &TYPE(TY_F32),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "f64",  &TYPE(TY_F64),  { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "f128", &TYPE(TY_F128), { 0 }, null },
-	
+
 	/* Character and String Types */
 	{ AK_TYPE, 0, 0, 0, "char",   &TYPE(TY_CHAR),   { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "rune",   &TYPE(TY_RUNE),   { 0 }, null },
 	{ AK_TYPE, 0, 0, 0, "string", &TYPE(TY_STRING), { 0 }, null },
-	
+
 	/* Builtins */
 	{ AK_PROC, 0, 0, 0, "cstring", &(type){ TY_PTR, TF_PTR, -1, "", &TYPE(TY_U8) }, { 0 }, null },
 	{ AK_PROC, 0, 0, 0, "len", &TYPE(TY_UINT), { 0 }, null },
-	
+
 	{ AK_VOID, 0, 0, 0, null, null, { 0 }, null }
 };
 
@@ -57,7 +57,7 @@ void initialise(void) {
 		kwds[i].h = syt_hash(kwds[i].s, strlen(kwds[i].s));
 		syt_insert_h(&kwt, kwds[i].h, kwds[i].s, &kwds[i]);
 	}
-	
+
 	/* Set the size of word sized types */
 	/* TODO don't hardcode */
 	TYPE(TY_UINT).l = 8;
diff --git a/src/lex.c b/src/lex.c
index cb75290..d5af0e1 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -13,19 +13,19 @@
 
 char *tok_ks[] = {
 	"TK_VOID", "TK_EOF", "TK_ID", "TK_INT", "TK_FLT", "TK_STR",
-	
+
 	"TK_NULL", "TK_TRUE", "TK_FALSE", "TK_PROC", "TK_GOTO", "TK_RETURN",
 	"TK_IF", "TK_ELSE", "TK_FOR", "TK_BREAK", "TK_CONTINUE",
-	
+
 	"TK_LPAREN", "TK_RPAREN", "TK_LBRACK", "TK_RBRACK", "TK_LBRACE", "TK_RBRACE",
 	"TK_COLON", "TK_SCOLON", "TK_COMMA", "TK_PERIOD", "TK_QMARK", "TK_HASH",
-	
+
 	"TK_ADD", "TK_SUB", "TK_MUL", "TK_DIV", "TK_MOD",
 	"TK_EQ", "TK_NE", "TK_LT", "TK_LE", "TK_GT", "TK_GE",
-	
+
 	"TK_EMARK", "TK_LO_AND", "TK_LO_OR",
 	"TK_TILDE", "TK_BW_AND", "TK_BW_OR", "TK_BW_XOR", "TK_LSHIFT", "TK_RSHIFT",
-	
+
 	"TK_ASSIGN", "TK_AS_ADD", "TK_AS_SUB", "TK_AS_MUL", "TK_AS_DIV", "TK_AS_MOD",
 	"TK_AS_NOT", "TK_AS_AND", "TK_AS_OR", "TK_AS_XOR", "TK_AS_LSHIFT", "TK_AS_RSHIFT",
 };
@@ -57,17 +57,17 @@ tok lex_peek(lex *l) { return T; }
 tok lex_next(lex *l) {
 	reset:; if (T.k == TK_EOF) { return T; }
 	tok t = T; T = (tok){ 0 };
-	
+
 	/* Skip null characters and whitespace */
 	skip:; for (; P != Q && (!P[0] || is_space(P[0])); P += 1) switch (P[0]) {
 		case '\0': { note(l->n, l->ln, l->cl, 1, "Null character ignored"); } break;
 		case '\n': { LN += 1; CL = 0; } break;
 		default:   { CL += 1; } break;
 	}
-	
+
 	/* Return the current token immediately if EOF is reached */
 	if (P == Q) { T = (tok){ TK_EOF, LN, CL, 0 }; return t; }
-	
+
 	/* Skip single-line and (potentially nested) multi-line comments */
 	if (P[0] == '/') switch (P[1]) {
 		case '/': { for (P += 2; P != Q && P[0] != '\n'; P += 1); } goto skip;
@@ -79,16 +79,16 @@ tok lex_next(lex *l) {
 			}
 		} goto skip;
 	}
-	
+
 	T.ln = LN; T.cl = CL;
-	
+
 	/* Handle identifiers and keywords */
 	if (is_alpha(P[0]) || P[0] == '_') {
 		char *s = P; uptr sl;
-		
+
 		for (P += 1; is_alpha(P[0]) || is_digit_dec(P[0]) || P[0] == '_'; P += 1);
 		sl = P - s; CL += sl; T.h = syt_hash(s, sl);
-		
+
 		if      (strncmp(s, "null",     4) == 0) { T.k = TK_NULL;     }
 		else if (strncmp(s, "true",     4) == 0) { T.k = TK_TRUE;     }
 		else if (strncmp(s, "false",    5) == 0) { T.k = TK_FALSE;    }
@@ -102,24 +102,24 @@ tok lex_next(lex *l) {
 		else if (strncmp(s, "continue", 8) == 0) { T.k = TK_CONTINUE; }
 		else { T.k = TK_ID; if (!(T.s = strndup(s, sl))) { panic(SERR); }}
 	}
-	
+
 	/* Handle number literals */
 	else if (is_digit_dec(P[0])) {
 		T.k = TK_INT; char *start = P;
-		
+
 		for (P += 1; is_alpha(P[0]) || is_digit_dec(P[0]) || P[0] == '.'; P += 1) {
 			if (P[0] == '.') { T.k = TK_FLT; }
 			if (P[0] == 'e' || P[0] == 'E') { T.k = TK_FLT; P += P[1] == '+' || P[1] == '-'; }
 		}
-		
+
 		uptr sl = P - start; CL += sl;
 		if (!(T.s = strndup(start, sl))) { panic(SERR); }
-		
+
 		switch (T.k) {
 		case TK_INT: {
 			char *s = T.s; register u64 v = 0; u64 c;
 			register uptr b = 10; char *b_s;
-			
+
 			if (s[0] == '0') switch (s[1]) {
 			case 'b': { s += 2; b = 2;  b_s = "binary";      } break;
 			case 'o': { s += 2; b = 8;  b_s = "octal";       } break;
@@ -128,32 +128,32 @@ tok lex_next(lex *l) {
 			case 'x': { s += 2; b = 16; b_s = "hexadecimal"; } break;
 			default:  { s += 1; } break;
 			}
-			
+
 			for (; s[0]; ++s) {
 				if (s[0] >= '0' && s[0] <= '9') { c = *s - '0'; }
 				else if (s[0] >= 'A' && s[0] <= 'F') { c = *s - ('A' - 10); }
-				
+
 				if (c >= b) { note(l->n, T.ln, T.cl, 0, "Invalid digit \'%c\' in %s constant", s[0], b_s); }
 				if (v > (U64_MAX - c) / b) { note(l->n, T.ln, T.cl, 0, "Integer literal cannot be represented"); }
-				
+
 				v = v * b + c;
 			}
-			
+
 			T.v_int = v;
 		} break;
 		case TK_FLT: {
 			/* TODO reimplement */
 			char *s = T.s, *end; register f128 v = 0;
-			
+
 			v = strtold(s, &end);
 			if (*end != '\0') { note(l->n, T.ln, T.cl, 0, "Invalid digit \'%c\' in floating-point constant", *end); }
-			
+
 			T.v_flt = v;
 		} break;
 		default: { /* Unreachable */ } break;
 		}
 	}
-	
+
 	/* Handle punctuators and operators */
 	else switch (P[0]) {
 		case '(': { T.k = TK_LPAREN; P += 1; CL += 1; } break;
@@ -230,15 +230,15 @@ tok lex_next(lex *l) {
 			default:  { T.k = TK_BW_XOR; P += 1; CL += 1; } break;
 			case '=': { T.k = TK_AS_XOR; P += 2; CL += 2; } break;
 		} break;
-		
+
 		/* Handle character and string literals */
 		case '\'': case '\"': {
 			char quote = P[0], *s = P += 1; CL += 1; register char *head = s;
-			
+
 			for (; P[0] != quote && P[0] != '\n' && P != Q;) {
 				/* Non escape characters are not altered */
 				if (P[0] != '\\') { *head = P[0]; P += 1; head += 1; }
-				
+
 				/* Escape characters are processed and re-written to head */
 				else switch (P[1]) {
 				case '0':  { *head = 0x00; P += 2; head += 1; } break;
@@ -262,20 +262,20 @@ tok lex_next(lex *l) {
 				} break;
 				}
 			}
-			
+
 			uptr sl = head - s; CL += sl;
 			if (P[0] != quote) { note(l->n, T.ln, T.cl, 0, "Missing closing quote"); }
 			else if (P != Q) { P += 1; CL += 1; }
-			
+
 			if (quote == '\'') {
 				T.k = TK_INT; if (!(T.s = strndup(s, sl))) { panic(SERR); }
-				
+
 				/* Numerical value of character literals is calculated and stored in T.v_int */
 				for (uptr i = 0; i < sl; i += 1) {
 					if (T.v_int > (U32_MAX - s[i]) / 256) {
 						note(l->n, T.ln, T.cl, 0, "Character literal cannot be represented"); break;
 					}
-					
+
 					T.v_int = T.v_int * 256 + s[i];
 				}
 			}
@@ -284,11 +284,11 @@ tok lex_next(lex *l) {
 				if (!(T.s = strndup(s, sl))) { panic(SERR); }
 			}
 		} break;
-		
+
 		/* Handle unknown characters */
 		default: { note(l->n, LN, CL, 1, "Unknown character: %X '%c'", P[0], P[0]); P += 1; CL += 1; } break;
 	}
-	
+
 	return t;
 }
 
diff --git a/src/lex.h b/src/lex.h
index 98f8e56..c1ba1f4 100644
--- a/src/lex.h
+++ b/src/lex.h
@@ -9,19 +9,19 @@
 /* Remember to update tok_ks in lex.c */
 typedef enum {
 	TK_VOID, TK_EOF, TK_ID, TK_INT, TK_FLT, TK_STR,
-	
+
 	TK_NULL, TK_TRUE, TK_FALSE, TK_PROC, TK_GOTO, TK_RETURN,
 	TK_IF, TK_ELSE, TK_FOR, TK_BREAK, TK_CONTINUE,
-	
+
 	TK_LPAREN, TK_RPAREN, TK_LBRACK, TK_RBRACK, TK_LBRACE, TK_RBRACE,
 	TK_COLON, TK_SCOLON, TK_COMMA, TK_PERIOD, TK_QMARK, TK_HASH,
-	
+
 	TK_ADD, TK_SUB, TK_MUL, TK_DIV, TK_MOD,
 	TK_EQ, TK_NE, TK_LT, TK_LE, TK_GT, TK_GE,
-	
+
 	TK_EMARK, TK_LO_AND, TK_LO_OR,
 	TK_TILDE, TK_BW_AND, TK_BW_OR, TK_BW_XOR, TK_LSHIFT, TK_RSHIFT,
-	
+
 	TK_ASSIGN, TK_AS_ADD, TK_AS_SUB, TK_AS_MUL, TK_AS_DIV, TK_AS_MOD,
 	TK_AS_NOT, TK_AS_AND, TK_AS_OR, TK_AS_XOR, TK_AS_LSHIFT, TK_AS_RSHIFT,
 } tok_k;
diff --git a/src/llvm.c b/src/llvm.c
index e9245d3..153e3fa 100644
--- a/src/llvm.c
+++ b/src/llvm.c
@@ -55,48 +55,48 @@ void llvm(ast *a, char *file, llvm_action action) {
 	llvm_context = LLVMGetGlobalContext();
 	llvm_module  = LLVMModuleCreateWithName((file_name = file));
 	llvm_builder = LLVMCreateBuilder();
-	
+
 	/* Generate IR for all child nodes */
 	for (uptr i = 0; i < a->c.al; i += 1) { llvm_stmt_decl(a->c.a[i], &a->st); }
-	
+
 	char *err = null; bool failed = false;
-	
+
 	failed = LLVMVerifyModule(llvm_module, LLVMPrintMessageAction, &err);
 	LLVMDisposeMessage(err); err = null;
-	
+
 	switch (action) {
 	case llvm_obj: case llvm_asm: {
 		if (failed) { exit(2); } /* Don't compile after failure */
-		
+
 		char *triple = LLVMGetDefaultTargetTriple();
 		printf("Target: %s\n", triple);
 		LLVMSetTarget(llvm_module, triple);
-		
+
 		LLVMInitializeAllTargetInfos();
 		LLVMInitializeAllTargets();
 		LLVMInitializeAllTargetMCs();
 		LLVMInitializeAllAsmParsers();
 		LLVMInitializeAllAsmPrinters();
-		
+
 		LLVMTargetRef target = null;
-		
+
 		if (LLVMGetTargetFromTriple(triple, &target, &err)) {
 			panic("LLVMGetTargetFromTriple: %s", err);
 		}
 		if (err != null) { panic("%s", err); } LLVMDisposeMessage(err); err = null;
-		
+
 		LLVMTargetMachineRef machine = LLVMCreateTargetMachine(
 			target, triple, "generic", "", LLVMCodeGenLevelNone,
 			LLVMRelocPIC, LLVMCodeModelDefault
 		);
-		
+
 		char *outfile = action == llvm_obj ? "llvm.o" : "llvm.s";
 		int outform = action == llvm_obj ? LLVMObjectFile : LLVMAssemblyFile;
 		if (LLVMTargetMachineEmitToFile(machine, llvm_module, outfile, outform, &err)) {
 			panic("LLVMTargetMachineEmitToFile: %s", err);
 		}
 		if (err != null) { panic("%s", err); } LLVMDisposeMessage(err); err = null;
-		
+
 		LLVMDisposeTargetMachine(machine);
 	} break;
 	case llvm_ir: {
@@ -111,7 +111,7 @@ void llvm(ast *a, char *file, llvm_action action) {
 		}
 	} break;
 	}
-	
+
 	LLVMDisposeBuilder(llvm_builder);
 	LLVMDisposeModule(llvm_module);
 	LLVMShutdown();
@@ -138,21 +138,21 @@ static LLVMValueRef llvm_stmt_compound(ast *a, syt *st) {
 /* Generate IR for a declaration statement. */
 static LLVMValueRef llvm_stmt_decl(ast *a, syt *st) {
 	assert(a->k == AK_DECL);
-	
+
 	if (CL && C[0]->k == AK_PROC) /* AK_PROC has a scope */ {
 		LLVMTypeRef art[C[0]->c.al - 1];
 		for (uptr i = 0; i < C[0]->c.al - 1; i += 1) { art[i] = llvm_type(ast_type(C[0]->c.a[i], &A.st)); }
-		
+
 		LLVMTypeRef ft = LLVMFunctionType(llvm_type(C[0]->t), art, C[0]->c.al - 1, 0);
 		LLVMValueRef f = LLVMAddFunction(llvm_module, A.s, ft);
-		
+
 		LLVMBasicBlockRef bb = LLVMAppendBasicBlock(f, "");
 		LLVMPositionBuilderAtEnd(llvm_builder, bb);
-		
+
 		/* Allocate scoped procedure arguments */
 		for (uptr i = 0; i < C[0]->c.al - 1; i += 1) { C[0]->c.a[i]->llvm_v = LLVMBuildAlloca(llvm_builder, art[i], ""); }
 		for (uptr i = 0; i < C[0]->c.al - 1; i += 1) { LLVMBuildStore(llvm_builder, LLVMGetParam(f, i), C[0]->c.a[i]->llvm_v); }
-		
+
 		A.llvm_t = ft; A.llvm_v = f;
 		llvm_expr_proc(C[0], &A.st);
 	}
@@ -169,7 +169,7 @@ static LLVMValueRef llvm_stmt_decl(ast *a, syt *st) {
 			A.llvm_v = v;
 		}
 	}
-	
+
 	return null;
 }
 
@@ -183,27 +183,27 @@ static LLVMValueRef llvm_stmt_return(ast *a, syt *st) {
 static LLVMValueRef llvm_stmt_if(ast *a, syt *st) {
 	assert(A.k == AK_IF);
 	assert(CL == 3 || CL == 4);
-	
+
 	if (C[0]->k != AK_VOID) { llvm_stmt(C[0], &A.st); }
-	
+
 	ast *p = find_proc(a); assert(p->k == AK_DECL);
-	
+
 	LLVMBasicBlockRef b1 = LLVMAppendBasicBlock(p->llvm_v, ""), b2 = null;
 	if (CL == 4) { b2 = LLVMAppendBasicBlock(p->llvm_v, ""); }
 	LLVMBasicBlockRef b3 = LLVMAppendBasicBlock(p->llvm_v, "");
-	
+
 	LLVMBuildCondBr(llvm_builder, llvm_expr(C[1], &A.st, true), b1, CL == 4 ? b2 : b3);
-	
+
 	LLVMPositionBuilderAtEnd(llvm_builder, b1);
 	llvm_stmt(C[2], &A.st); LLVMBuildBr(llvm_builder, b3);
-	
+
 	if (CL == 4) {
 		LLVMPositionBuilderAtEnd(llvm_builder, b2);
 		llvm_stmt(C[3], &A.st); LLVMBuildBr(llvm_builder, b3);
 	}
-	
+
 	LLVMPositionBuilderAtEnd(llvm_builder, b3);
-	
+
 	return null;
 }
 
@@ -211,27 +211,27 @@ static LLVMValueRef llvm_stmt_if(ast *a, syt *st) {
 static LLVMValueRef llvm_stmt_for(ast *a, syt *st) {
 	assert(A.k == AK_FOR);
 	assert(CL == 2 || CL == 4);
-	
+
 	if (CL == 4) { llvm_stmt(C[0], &A.st); }
-	
+
 	ast *p = find_proc(a); assert(p->k == AK_DECL);
-	
+
 	LLVMBasicBlockRef b1 = LLVMAppendBasicBlock(p->llvm_v, "");
 	LLVMBasicBlockRef b2 = LLVMAppendBasicBlock(p->llvm_v, "");
 	LLVMBasicBlockRef b3 = LLVMAppendBasicBlock(p->llvm_v, "");
-	
+
 	LLVMBuildBr(llvm_builder, b1);
-	
+
 	LLVMPositionBuilderAtEnd(llvm_builder, b1);
 	LLVMBuildCondBr(llvm_builder, llvm_expr(CL == 4 ? C[1] : C[0], &A.st, true), b2, b3);
-	
+
 	LLVMPositionBuilderAtEnd(llvm_builder, b2);
 	llvm_stmt(CL == 4 ? C[3] : C[1], &A.st);
 	if (CL == 4) { llvm_stmt(C[2], &A.st); }
 	LLVMBuildBr(llvm_builder, b1);
-	
+
 	LLVMPositionBuilderAtEnd(llvm_builder, b3);
-	
+
 	return null;
 }
 
@@ -252,7 +252,7 @@ static LLVMValueRef llvm_expr(ast *a, syt *st, bool load) {
 		ast *sym = syt_search(st, a->s);
 		if (sym == null) { note(file_name, A.ln, A.cl, -1, "Undefined variable \"%s\"", A.s); }
 		if (!sym->llvm_v) { note(file_name, A.ln, A.cl, -1, "Variable \"%s\" follows (llvm:llvm_expr)", A.s); }
-		
+
 		if (!load || sym->t->k == TY_ARR) { return sym->llvm_v; }
 		else { return LLVMBuildLoad2(llvm_builder, llvm_type(sym->t), sym->llvm_v, ""); }
 	} break;
@@ -260,7 +260,7 @@ static LLVMValueRef llvm_expr(ast *a, syt *st, bool load) {
 		ast *sym = syt_search_h(st, C[0]->h, C[0]->s);
 		if (sym == null) { note(file_name, A.ln, A.cl, -1, "Undefined procedure \"%s\" (llvm:llvm_expr)", C[0]->s); }
 		if (!sym->llvm_v) { note(file_name, A.ln, A.cl, -1, "Procedure \"%s\" follows (llvm:llvm_expr)", C[0]->s); }
-		
+
 		LLVMValueRef args[CL - 1]; for (uptr i = 1; i < CL; i += 1) { args[i - 1] = llvm_expr(C[i], st, true); }
 		return LLVMBuildCall2(llvm_builder, sym->llvm_t, sym->llvm_v, args, CL - 1, "");
 	} break;
@@ -271,16 +271,16 @@ static LLVMValueRef llvm_expr(ast *a, syt *st, bool load) {
 		/* FIXME subscripting does not work with pointers */
 		LLVMValueRef idc[1] = { llvm_expr(C[1], st, true) };
 		LLVMValueRef vr = LLVMBuildInBoundsGEP2(llvm_builder, llvm_type(ast_type(C[0], st)), llvm_expr(C[0], st, false), idc, 1, "");
-		
+
 		if (!load) { return vr; }
 		else { return LLVMBuildLoad2(llvm_builder, llvm_type(ast_type(C[0], st)->base), vr, ""); }
 	}
-	
+
 	case AK_POS: { a = C[0]; goto reset; /* no-op */ } break;
 	case AK_NEG: {
 		type *t = ast_type(C[0], st);
 		if (t == null) { note(file_name, A.ln, A.cl, -1, "Subtree is missing a type (llvm:llvm_expr)"); }
-		
+
 		if (is_int(t)) { return LLVMBuildNeg(llvm_builder, llvm_expr(C[0], st, true), "neg"); }
 		else if (is_flt(t)) { return LLVMBuildFNeg(llvm_builder, llvm_expr(C[0], st, true), "neg"); }
 		else { note(file_name, A.ln, A.cl, -1, "Expression cannot be made negative (llvm:llvm_expr)"); }
@@ -290,11 +290,11 @@ static LLVMValueRef llvm_expr(ast *a, syt *st, bool load) {
 		type *t = ast_type(C[0], st);
 		if (t == null) { note(file_name, A.ln, A.cl, -1, "Child is missing a type (llvm:llvm_expr)"); }
 		if (t->base == null) { note(file_name, A.ln, A.cl, -1, "Cannot be dereferenced (llvm:llvm_expr)"); }
-		
+
 		if (!load) { return llvm_expr(C[0], st, true); }
 		else { return LLVMBuildLoad2(llvm_builder, llvm_type(t->base), llvm_expr(C[0], st, true), ""); }
 	}
-	
+
 	case AK_ADD: {
 		if      (is_int(ast_type(C[0], st))) { return LLVMBuildAdd(llvm_builder, llvm_expr(C[0], st, true), llvm_expr(C[1], st, true), ""); }
 		else if (is_flt(ast_type(C[0], st))) { return LLVMBuildFAdd(llvm_builder, llvm_expr(C[0], st, true), llvm_expr(C[1], st, true), ""); }
@@ -323,7 +323,7 @@ static LLVMValueRef llvm_expr(ast *a, syt *st, bool load) {
 		}
 		else if (is_flt(t)) { return LLVMBuildFRem(llvm_builder, llvm_expr(C[0], st, true), llvm_expr(C[1], st, true), ""); }
 	} break;
-	
+
 	case AK_EQ:  {
 		if      (is_int(ast_type(C[0], st))) { return BuildICmp(llvm_builder, LLVMIntEQ,   C[0], C[1], st); }
 		else if (is_flt(ast_type(C[0], st))) { return BuildFCmp(llvm_builder, LLVMRealOEQ, C[0], C[1], st); }
@@ -360,15 +360,15 @@ static LLVMValueRef llvm_expr(ast *a, syt *st, bool load) {
 		}
 		else if (is_flt(ast_type(C[0], st))) { return BuildFCmp(llvm_builder, LLVMRealOGE, C[0], C[1], st); }
 	} break;
-	
+
 	case AK_LO_NOT: { return LLVMBuildNot(llvm_builder, llvm_expr(C[0], st, true), ""); } break;
 	case AK_LO_AND: { return LLVMBuildAnd(llvm_builder, llvm_expr(C[0], st, true), llvm_expr(C[1], st, true), ""); } break;
 	case AK_LO_OR:  { return LLVMBuildOr(llvm_builder, llvm_expr(C[0], st, true), llvm_expr(C[1], st, true), "");  } break;
-	
+
 	case AK_BW_NOT: {
 		type *t = ast_type(C[0], st);
 		if (t == null) { note(file_name, A.ln, A.cl, -1, "Subtree is missing a type (llvm:llvm_expr)"); }
-		
+
 		if (is_int(t)) {
 			return LLVMBuildXor(llvm_builder, llvm_expr(C[0], st, true), LLVMConstInt(llvm_type(t), -1, false), "");
 		}
@@ -380,7 +380,7 @@ static LLVMValueRef llvm_expr(ast *a, syt *st, bool load) {
 		}
 		else { note(file_name, A.ln, A.cl, -1, "Expression cannot be inverted (llvm:llvm_expr)"); }
 	} break;
-	
+
 	case AK_ASSIGN: {
 		return LLVMBuildStore(llvm_builder, llvm_expr(C[1], st, true), llvm_expr(C[0], st, false));
 	} break;
@@ -420,10 +420,10 @@ static LLVMValueRef llvm_expr(ast *a, syt *st, bool load) {
 		else if (is_flt(t)) { v = LLVMBuildFRem(llvm_builder, llvm_expr(C[0], st, true), llvm_expr(C[1], st, true), ""); }
 		return LLVMBuildStore(llvm_builder, v, llvm_expr(C[0], st, false));
 	} break;
-	
+
 	default: { panic("Unhandled AST kind \"%s\" (llvm:llvm_expr)", ast_ks[a->k]); } break;
 	}
-	
+
 	return null;
 }
 
@@ -436,10 +436,10 @@ static LLVMValueRef llvm_expr_proc(ast *a, syt *st) {
 static LLVMValueRef llvm_expr_cast(ast *a, syt *st) {
 	assert(A.t != null);
 	assert(CL == 1 || CL == 2);
-	
+
 	ast *c = CL == 1 ? C[0] : C[1];
 	type *expr_type = ast_type(c, st);
-	
+
 	if (is_ptr(expr_type)) {
 		if (is_int(a->t)) { return LLVMBuildPtrToInt(llvm_builder, llvm_expr(c, st, true), llvm_type(a->t), ""); }
 	}
@@ -468,23 +468,23 @@ static LLVMValueRef llvm_expr_cast(ast *a, syt *st) {
 			return LLVMBuildBitCast(llvm_builder, llvm_expr(c, st, true), llvm_type(a->t), "");
 		}
 	}
-	
+
 	panic("Unhandled cast \"%s\" -> \"%s\" (llvm:llvm_expr_cast)", expr_type->s, A.t->s);
-	
+
 	return null;
 }
 
 /* Generate IR for a builtin. */
 static LLVMValueRef llvm_expr_builtin(ast *a, syt *st) {
 	assert(A.k == AK_BUILTIN);
-	
+
 	ast *sym = syt_search_h(st, C[0]->h, C[0]->s);
 	if (sym == null) { note(file_name, A.ln, A.cl, -1, "Undefined builtin \"%s\" (llvm:llvm_expr_builtin)", C[0]->s); }
-	
+
 	if (strncmp(sym->s, "cstring", 7) == 0) {
 		assert(CL == 2);
 		if (ast_type(C[1], st)->k != TY_STRING) { panic("cstring builtin only takes strings, not \"%s\"s", ast_type(C[1], st)->s); }
-		
+
 		LLVMValueRef idc[2] = { LLVMConstInt(LLVMIntType(32), 0, false), LLVMConstInt(LLVMIntType(32), 0, false) };
 		LLVMValueRef v = LLVMBuildInBoundsGEP2(llvm_builder, llvm_type(ast_type(C[1], st)), llvm_expr(C[1], st, false), idc, 2, "");
 		return LLVMBuildLoad2(llvm_builder, LLVMPointerType(LLVMIntType(8), 0), v, "");
@@ -492,67 +492,67 @@ static LLVMValueRef llvm_expr_builtin(ast *a, syt *st) {
 	else if (strncmp(sym->s, "len", 3) == 0) {
 		assert(CL == 2);
 		if (ast_type(C[1], st)->k != TY_STRING) { panic("len builtin only takes strings, not \"%s\"s", ast_type(C[1], st)->s); }
-		
+
 		LLVMValueRef idc[2] = { LLVMConstInt(LLVMIntType(32), 0, false), LLVMConstInt(LLVMIntType(32), 1, false) };
 		LLVMValueRef v = LLVMBuildInBoundsGEP2(llvm_builder, llvm_type(ast_type(C[1], st)), llvm_expr(C[1], st, false), idc, 2, "");
 		return LLVMBuildLoad2(llvm_builder, LLVMIntType(64), v, "");
 	}
-	
+
 	return null;
 }
 
 /* Generate IR for a hash procedure. */
 static LLVMValueRef llvm_expr_hash(ast *a, syt *st) {
 	assert(A.k == AK_HASH_SYSCALL);
-	
+
 	LLVMValueRef args[CL]; LLVMTypeRef argt[CL];
 	for (uptr i = 0; i < CL; i += 1) {
 		args[i] = llvm_expr(C[i], st, true);
 		argt[i] = llvm_type(ast_type(C[i], st));
 	}
-	
+
 	LLVMTypeRef func_type = LLVMFunctionType(llvm_type(&TYPE(TY_SINT)), argt, CL, false);
 	LLVMValueRef inline_asm = null;
-	
+
 	/* TODO check architecture */
 	/* x86-64 */ {
 		assert(CL <= 7);
-		
+
 		char constraints[128] = "={rax}";
-		
+
 		char const *registers[] = { "rax", "rdi", "rsi", "rdx", "r10", "r8", "r9" };
 		for (uptr i = 0; i < CL; i += 1) {
 			strcat(constraints, ",{");
 			strcat(constraints, registers[i]);
 			strcat(constraints, "}");
 		}
-		
+
 		strcat(constraints, ",~{rcx},~{r11},~{memory}");
-		
+
 		inline_asm = LLVMGetInlineAsm(
 			func_type, "syscall", 7, constraints, strlen(constraints), true, false, LLVMInlineAsmDialectATT, false
 		);
 	}
-	
+
 	return LLVMBuildCall2(llvm_builder, func_type, inline_asm, args, CL, "");
 }
 
 /* Generate IR for a string constant. */
 static LLVMValueRef llvm_str(ast *a, syt *st, bool load) {
 	assert(A.k == AK_STR);
-	
+
 	LLVMValueRef va[2] = {
 		LLVMBuildGlobalString(llvm_builder, A.s, "string"),
 		LLVMConstInt(LLVMIntType(64), strlen(A.s), false)
 	};
-	
+
 	LLVMValueRef vs = LLVMAddGlobal(llvm_module, llvm_type(&TYPE(TY_STRING)), "string");
 	LLVMSetInitializer(vs, LLVMConstNamedStruct(llvm_type(&TYPE(TY_STRING)), va, 2));
 	LLVMSetGlobalConstant(vs, true);
 	LLVMSetLinkage(vs, LLVMPrivateLinkage);
 	LLVMSetUnnamedAddress(vs, LLVMGlobalUnnamedAddr);
 	LLVMSetAlignment(vs, 8);
-	
+
 	if (!load) { return vs; }
 	else { return LLVMBuildLoad2(llvm_builder, llvm_type(&TYPE(TY_STRING)), vs, ""); }
 }
@@ -560,11 +560,11 @@ static LLVMValueRef llvm_str(ast *a, syt *st, bool load) {
 /* Generate IR for an array. */
 static LLVMValueRef llvm_arr(ast *a, syt *st) {
 	assert(A.k == AK_ARR);
-	
+
 	LLVMValueRef *va = calloc(CL, sizeof (LLVMValueRef));
-	
+
 	for (uptr i = 0; i < CL; i += 1) { va[i] = llvm_expr(C[i], st, true); }
-	
+
 	return LLVMConstArray(llvm_type(C[0]->t), va, CL);
 }
 
@@ -634,7 +634,7 @@ static LLVMValueRef llvm_ival(type *t) {
 				LLVMBuildGlobalString(llvm_builder, "", ""),
 				LLVMConstInt(LLVMIntType(64), 0, false)
 			};
-			
+
 			vs = LLVMAddGlobal(llvm_module, llvm_type(&TYPE(TY_STRING)), "");
 			LLVMSetInitializer(vs, LLVMConstNamedStruct(llvm_type(&TYPE(TY_STRING)), va, 2));
 			LLVMSetGlobalConstant(vs, true);
diff --git a/src/llvm/attr.c b/src/llvm/attr.c
index 2e9a72d..8deaf52 100644
--- a/src/llvm/attr.c
+++ b/src/llvm/attr.c
@@ -20,7 +20,7 @@ static char *llvm_func_attr_s[] = {
 int LLVMAddFuncAttr(LLVMContextRef C, LLVMValueRef F, llvm_func_attr attr, unsigned index) {
 	u32 ak = LLVMGetEnumAttributeKindForName(llvm_func_attr_s[attr], strlen(llvm_func_attr_s[attr]));
 	if (ak == 0) { dprint(null, 0, 0, "Attribute \"%s\" does not exist", llvm_func_attr_s[attr]); return -1; }
-	
+
 	LLVMAttributeRef ar = LLVMCreateEnumAttribute(C, ak, 0);
 	LLVMAddAttributeAtIndex(F, index, ar); return 0;
 }
diff --git a/src/log.c b/src/log.c
index 67232e5..bd7bfa6 100644
--- a/src/log.c
+++ b/src/log.c
@@ -17,16 +17,16 @@ static sptr log_count = 0;
 /* Log a compiler fatal (-1), error (0), warning (1-3), or note (4). */
 void note(const char *file, uptr ln, uptr cl, sptr level, const char *format, ...) {
 	if (file) { fprintf(stderr, "%s:%lu:%lu: ", file, ln + 1, cl + 1); }
-	
+
 	if (level <= -1) { fprintf(stderr, "fatal: "); }
 	else if (level == 9) { fprintf(stderr, "debug: "); }
 	else if (level == 0) { fprintf(stderr, "error: "); }
 	else if (level <= 3) { fprintf(stderr, "warning: "); }
 	else if (level >= 4) { fprintf(stderr, "note: "); }
-	
+
 	va_list va; va_start(va, format); vfprintf(stderr, format, va); va_end(va);
 	fputc('\n', stderr); if (level <= -1) { exit(1); }
-	
+
 	if (level == 0 && (log_count += 1) == log_limit) { fprintf(stderr, "fatal: error limit reached"); exit(1); }
 }
 
diff --git a/src/main.c b/src/main.c
index 2de3fd6..dfe098d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -39,7 +39,7 @@ int main(int ac, char *av[]) { A0 = av[0];
 		{ "version", ARG_NUL, 257 },
 		{ null, 0, 0 }
 	};
-	
+
 	for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) {
 	case 'b': { args.bflag = true; } break; /* Output LLVM IR files */
 	case 'B': { args.Bflag = true; } break; /* Output LLVM bitcode files */
@@ -58,45 +58,45 @@ int main(int ac, char *av[]) { A0 = av[0];
 	case 257: { fputs(version, stdout); } return 0;
 	default: {} return 1;
 	}
-	
+
 	if (opt.ind == ac) { error(1, "Missing operand"); }
 	else for (char **p = &av[opt.ind]; *p; ++p) { compile_file(*p); }
-	
+
 	return 0;
 }
 
 static void compile(const char * file, char *src, uptr len) {
 	initialise();
-	
+
 	lex l = lex_init(file, src, len);
 	if (args.Eflag) { lex_debug(&l); goto end; }
-	
+
 	ast *a = parse(&l);
 	if (args.pflag) { if (!args.qflag) { ast_print(a, 0); } goto end; }
 	if (has_error()) { exit(1); }
-	
+
 	assert(a->k == AK_PROG); analyse(a);
 	if (args.Pflag) { if (!args.qflag) { ast_print(a, 0); } goto end; }
 	if (has_error()) { exit(1); }
-	
+
 	if (args.bflag) { llvm(a, strdup(file), llvm_ir); }
 	else if (args.Bflag) { llvm(a, strdup(file), llvm_bc); }
 	else if (args.Sflag) { llvm(a, strdup(file), llvm_asm); }
 	else { llvm(a, strdup(file), llvm_obj); }
 	if (has_error()) { exit(1); }
-	
+
 	end:; return;
 }
 
 static void compile_file(const char *file) {
 	FILE *fi; char *fb; size_t fl;
-	
+
 	if (!(fi = fopen(file, "r"))) { error(1, "%s: %s", file, SERR); }
 	fseek(fi, 0, SEEK_END); fl = ftell(fi); rewind(fi);
-	
+
 	fb = malloc((fl + 1) * sizeof (*fb));
 	fread(fb, 1, fl, fi); fb[fl] = 0; fclose(fi);
-	
+
 	compile(file, fb, fl); free(fb); return;
 }
 
diff --git a/src/parse.c b/src/parse.c
index 3e71095..82c36f5 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -18,23 +18,23 @@ typedef struct { type *t; ast *a; } ta_pair;
 
 char *ast_ks[] = {
 	"AK_VOID", "AK_PROG", "AK_ID", "AK_BOOL", "AK_INT", "AK_FLT", "AK_STR",
-	
+
 	"AK_PROC", "AK_TYPE", "AK_CAST",
-	
+
 	"AK_COMP", "AK_DECL", "AK_RETURN", "AK_IF", "AK_FOR",
-	
+
 	"AK_OP_POS", "AK_OP_NEG", "AK_OP_ADO", "AK_OP_DRF",
 	"AK_OP_ADD", "AK_OP_SUB", "AK_OP_MUL", "AK_OP_DIV", "AK_OP_MOD",
-	
+
 	"AK_EQ", "AK_NE", "AK_LT", "AK_LE", "AK_GT", "AK_GE",
-	
+
 	"AK_LO_NOT", "AK_LO_AND", "AK_LO_OR",
 	"AK_BW_NOT", "AK_BW_AND", "AK_BW_OR",  "AK_BW_XOR", "AK_BW_SHL", "AK_BW_SHR",
-	
+
 	"AK_ASSIGN", "AK_AS_ADD", "AK_AS_SUB", "AK_AS_MUL", "AK_AS_DIV", "AK_AS_MOD",
-	
+
 	"AK_CALL", "AK_ARR", "AK_SUBS",
-	
+
 	"AK_HASH", "AK_HASH_SYSCALL", "AK_BUILTIN"
 };
 
@@ -77,10 +77,10 @@ inline void ast_free(ast **a) {
 /* Push a child AST node to an AST node. */
 void ast_push(ast *a, ast *c) {
 	assert(a != null); assert(c != null);
-	
+
 	ast **ca = realloc(a->c.a, (a->c.al += 1) * sizeof (ast *));
 	if (!ca) { panic(SERR); } else { a->c.a = ca; ca = null; }
-	
+
 	/* Store pointer from parent to child and vice versa */
 	assert(c->p == null);
 	c->p = a; a->c.a[a->c.al - 1] = c;
@@ -89,17 +89,17 @@ void ast_push(ast *a, ast *c) {
 /* Displace a child AST node from a parent AST node. */
 void ast_displace(ast *a, ast *c) {
 	ast **oa = a->c.a; uptr ol = a->c.al; bool found = false;
-	
+
 	for (uptr i = 0; i < ol; i += 1) { if (oa[i] == c) { found = true; break; }}
 	if (!found) { return; }
-	
+
 	ast **ca = calloc((a->c.al -= 1), sizeof (ast *));
 	if (!ca) { panic(SERR); } else { a->c.a = ca; ca = null; }
-	
+
 	for (uptr i = 0, j = 0; i < ol && j < a->c.al; i += 1) {
 		if (oa[i] == c) { continue; } a->c.a[j] = oa[i]; j += 1;
 	}
-	
+
 	c->p = null; free(oa);
 }
 
@@ -107,10 +107,10 @@ void ast_displace(ast *a, ast *c) {
 void ast_wrap(ast *const a, ast *const c, ast *const w) {
 	assert(a != null); assert(c != null); assert(w != null);
 	ast **oa = a->c.a; uptr ol = a->c.al, ifound; bool found = false;
-	
+
 	for (uptr i = 0; i < ol; i += 1) { if (oa[i] == c) { found = true; ifound = i; break; }}
 	if (!found) { panic("ast_wrap called with an unrelated parent and child"); }
-	
+
 	w->p = a; a->c.a[ifound] = w; c->p = null; ast_push(w, c);
 }
 
@@ -118,7 +118,7 @@ void ast_wrap(ast *const a, ast *const c, ast *const w) {
 type *ast_type(ast *a, syt *st) {
 	/* If the given node has a type, then return that */
 	if (a->t && !is_proc(a->t)) { return a->t; }
-	
+
 	/* Search the symbol table for a type first */
 	if (a->s) {
 		ast *sym = syt_search(st, a->s);
@@ -127,14 +127,14 @@ type *ast_type(ast *a, syt *st) {
 			else { return sym->t; }
 		}
 	}
-	
+
 	/* Otherwise recurse down the first child */
 	if (a->c.al) {
 		type *rt = ast_type(a->c.a[0], st);
 		if (a->k == AK_SUBS) { return rt->base; }
 		else { return rt; }
 	}
-	
+
 	/* If no type is found, return null */
 	return null;
 }
@@ -157,13 +157,13 @@ ast *ast_a_pop(ast_a *aa) {
 /* Parse a program. */
 ast *parse(lex *l) {
 	ast *a = ast_init(AK_PROG, 0, 0);
-	
+
 	/* Parse and append all child nodes */
 	for (ast *c; T.k != TK_EOF;) {
 		if ((c = parse_stmt_decl(l, &a->st, true)) != null) { ast_push(a, c); }
 		else { note(l->n, T.ln, T.cl, -1, "null AST (parse:parse_stmt_decl)"); }
 	}
-	
+
 	return a;
 }
 
@@ -201,9 +201,9 @@ static ast *parse_stmt_init(lex *l, syt *st) {
 static ast *parse_stmt_compound(lex *l, syt *st) {
 	ast *a = ast_init(AK_COMP, T.ln, T.cl);
 	lex_kind(l, TK_LBRACE); a->st.pt = st;
-	
+
 	for (; T.k != TK_EOF && T.k != TK_RBRACE;) { ast_push(a, parse_stmt(l, &a->st)); }
-	
+
 	lex_kind(l, TK_RBRACE); return a;
 }
 
@@ -211,20 +211,20 @@ static ast *parse_stmt_compound(lex *l, syt *st) {
 static ast *parse_stmt_decl(lex *l, syt *st, bool scolon) {
 	ast *a = ast_init(AK_DECL, T.ln, T.cl); a->h = T.h; a->s = T.s;
 	lex_kind(l, TK_ID); lex_kind(l, TK_COLON);
-	
+
 	/* Store the declaration's type if one is specified */
 	if (T.k == TK_ID || T.k == TK_MUL || T.k == TK_LBRACK) {
 		ta_pair ta = parse_type(l, st);
 		a->t = ta.t; /* TODO keep the AST component */
 	}
-	
+
 	/* Assign a constant or variable value if one is specified */
 	if (T.k == TK_COLON || T.k == TK_ASSIGN) { lex_next(l); ast_push(a, parse_expr(l, st, 0)); }
-	
+
 	/* Ensure that a type is known and consume a semicolon if one is required */
 	if (a->t == null && CL(a) == 0) { note(l->n, T.ln, T.cl, 0, "A declaration without a type is invalid"); }
 	if (scolon && (CL(a) < 1 || C(a)[0]->k != AK_PROC)) { lex_kind(l, TK_SCOLON); }
-	
+
 	/* Insert the new symbol and return */
 	syt_insert_h(st, a->h, a->s, a); return a;
 }
@@ -238,23 +238,23 @@ static ast *parse_stmt_expr(lex *l, syt *st) {
 /* Parse a return statement. */
 static ast *parse_stmt_return(lex *l, syt *st) {
 	assert(T.k == TK_RETURN);
-	
+
 	ast *a = ast_init(AK_RETURN, T.ln, T.cl); lex_next(l);
 	if (T.k != TK_SCOLON) { ast_push(a, parse_expr(l, st, 0)); }
-	
+
 	lex_kind(l, TK_SCOLON); return a;
 }
 
 /* Parse an if statement. AK_IF has a scope. */
 static ast *parse_stmt_if(lex *l, syt *st) {
 	assert(T.k == TK_IF);
-	
+
 	ast *a = ast_init(AK_IF, T.ln, T.cl);
 	lex_next(l); lex_kind(l, TK_LPAREN); a->st.pt = st;
-	
+
 	if (T.k != TK_RPAREN) {
 		register ast *c1 = parse_stmt_init(l, &a->st);
-		
+
 		if (T.k == TK_SCOLON) {
 			lex_next(l); ast_push(a, c1);
 			ast_push(a, parse_expr(l, &a->st, 0));
@@ -265,32 +265,32 @@ static ast *parse_stmt_if(lex *l, syt *st) {
 		}
 	}
 	else { note(l->n, T.ln, T.cl, 0, "Expected an expression"); }
-	
+
 	lex_kind(l, TK_RPAREN);
-	
+
 	/* Parse the if statement body */
 	ast_push(a, parse_stmt(l, &a->st));
-	
+
 	/* Parse an else statement if present */
 	if (T.k == TK_ELSE) { lex_next(l); ast_push(a, parse_stmt(l, &a->st)); }
-	
+
 	return a;
 }
 
 /* Parse a for statement. AK_FOR has a scope. */
 static ast *parse_stmt_for(lex *l, syt *st) {
 	assert(T.k == TK_FOR);
-	
+
 	ast *a = ast_init(AK_FOR, T.ln, T.cl);
 	lex_next(l); lex_kind(l, TK_LPAREN); a->st.pt = st;
-	
+
 	if (T.k != TK_RPAREN) {
 		register ast *c1 = parse_stmt_init(l, &a->st);
-		
+
 		if (T.k == TK_SCOLON) {
 			lex_next(l); ast_push(a, c1);
 			ast_push(a, parse_expr(l, &a->st, 0));
-			
+
 			lex_kind(l, TK_SCOLON);
 			ast_push(a, parse_expr(l, &a->st, 0));
 		}
@@ -300,12 +300,12 @@ static ast *parse_stmt_for(lex *l, syt *st) {
 		}
 	}
 	else { note(l->n, T.ln, T.cl, 0, "Expected an expression"); }
-	
+
 	lex_kind(l, TK_RPAREN);
-	
+
 	/* Parse the for statement body */
 	ast_push(a, parse_stmt(l, &a->st));
-	
+
 	return a;
 }
 
@@ -346,27 +346,27 @@ static ast *parse_expr(lex *l, syt *st, s32 o) {
 	prefix: { lex_next(l); ast_push(left, parse_expr(l, st, ast_precedence(left->k))); } break;
 	default: { note(l->n, T.ln, T.cl, 0, "Unexpected \"%s\", was expecting an expression", tok_ks[T.k]); } break;
 	}
-	
+
 	/* Parse an infix expression if one is present */
 	for (ast *a = null; tok_precedence(T.k) > o; left = a) switch (T.k) {
 	case TK_LPAREN: {
 		if (left->k == AK_HASH) { a = left; }
 		else { a = ast_init(AK_CALL, left->ln, left->cl); ast_push(a, left); }
-		
+
 		lex_next(l);
-		
+
 		/* Parse call arguments if present */
 		if (T.k != TK_RPAREN) for (;;) {
 			ast_push(a, parse_expr(l, st, 0));
 			if (T.k == TK_COMMA) { lex_next(l); } else { break; }
 		}
-		
+
 		lex_kind(l, TK_RPAREN);
 	} break;
 	case TK_LBRACK: {
 		a = ast_init(AK_SUBS, T.ln, T.cl);
 		lex_next(l); ast_push(a, left);
-		
+
 		ast_push(a, parse_expr(l, st, 0));
 		lex_kind(l, TK_RBRACK);
 	} break;
@@ -392,54 +392,54 @@ static ast *parse_expr(lex *l, syt *st, s32 o) {
 	infix: { lex_next(l); ast_push(a, left); ast_push(a, parse_expr(l, st, ast_precedence(a->k))); } break;
 	default: { /* Ignored */ } break;
 	}
-	
+
 	return left;
 }
 
 /* Parse a compound expression (arrays, structs, etc.). */
 static ast *parse_expr_compound(lex *l, syt *st) {
 	assert(T.k == TK_LBRACE);
-	
+
 	ast *a = ast_init(AK_ARR, T.ln, T.cl); lex_next(l);
-	
+
 	if (T.k != TK_RBRACE) for (;;) {
 		ast_push(a, parse_expr(l, st, 0));
 		if (T.k == TK_COMMA) { lex_next(l); } else { break; }
 	}
-	
+
 	lex_kind(l, TK_RBRACE); return a;
 }
 
 /* Parse a procedure expression. AK_PROC has a scope. */
 static ast *parse_expr_proc(lex *l, syt *st) {
 	assert(T.k == TK_PROC);
-	
+
 	ast *a = ast_init(AK_PROC, T.ln, T.cl);
 	lex_next(l); lex_kind(l, TK_LPAREN); a->st.pt = st;
-	
+
 	/* Parse optional procedure parameter(s) */
 	if (T.k != TK_RPAREN) for (;;) {
 		ast *arg = ast_init(AK_ID, T.ln, T.cl);
 		arg->h = T.h; arg->s = strdup_or_fail(T.s);
-		
+
 		lex_kind(l, TK_ID); lex_kind(l, TK_COLON);
-		
+
 		ta_pair ta = parse_type(l, st);
 		arg->t = ta.t; /* TODO handle AST component */
-		
+
 		ast_push(a, arg); syt_insert_h(&a->st, arg->h, arg->s, arg);
 		if (T.k == TK_COMMA) { lex_next(l); } else { break; }
 	}
-	
+
 	lex_kind(l, TK_RPAREN);
-	
+
 	/* Parse optional procedure return type */
 	if (T.k == TK_ID) {
 		ta_pair ta = parse_type(l, st);
 		a->t = ta.t; /* TODO handle AST component */
 	}
 	else { a->t = &TYPE(TY_VOID); }
-	
+
 	ast_push(a, parse_stmt_compound(l, &a->st)); return a;
 }
 
@@ -447,13 +447,13 @@ static ast *parse_expr_proc(lex *l, syt *st) {
 static inline ta_pair parse_type(lex *l, syt *st) {
 	/* root, deepest child, and variable length */
 	type *r = null, *c; ast *a = null;
-	
+
 	/* Parse optional pointer and array specifiers */
 	for (register type *t = null;;) switch (T.k) {
 	case TK_MUL: { lex_next(l); t = type_ptr(null, 1); } goto store;
 	case TK_LBRACK: {
 		lex_next(l);
-		
+
 		/* TODO handle variable array length */
 		if (T.k != TK_RBRACK) {
 			assert(T.k == TK_INT);
@@ -461,56 +461,56 @@ static inline ta_pair parse_type(lex *l, syt *st) {
 			t = type_arr(null, a->v_int);
 		}
 		else { t = type_arr(null, -1); }
-		
+
 		lex_kind(l, TK_RBRACK);
 	} goto store;
 	store: { if (r == null) { r = c = t; } else { c = (c->base = t); }} break;
 	default: { goto escape; }
 	} escape:;
-	
+
 	/* Parse the base type identifier */
 	tok t = lex_kind(l, TK_ID); ast *s = syt_search_h(st, t.h, t.s);
 	if (s == null) { note(l->n, t.ln, t.cl, 0, "Use of undeclared identifier \"%s\"", t.s); }
 	else if (s->k != AK_TYPE) { note(l->n, t.ln, t.cl, 0, "Expected type identifier"); }
-	
+
 	if (r == null) { return (ta_pair){ s->t, a }; } else { c->base = s->t; return (ta_pair){ r, a }; }
 }
 
 /* Parse an integer. AK_INT is terminal. */
 static inline ast *parse_int(lex *l, syt *st) {
 	assert(T.k == TK_INT);
-	
+
 	tok t = lex_next(l);
 	ast *a = ast_init(AK_INT, t.ln, t.cl);
-	
+
 	a->s = strdup_or_fail(t.s);
 	a->v_int = t.v_int;
-	
+
 	/* Determine the minimum integer type */
 	if (a->v_int <= U8_MAX) { a->t = &TYPE(TY_U8); }
 	else if (a->v_int <= U16_MAX) { a->t = &TYPE(TY_U16); }
 	else if (a->v_int <= U32_MAX) { a->t = &TYPE(TY_U32); }
 	else if (a->v_int <= U64_MAX) { a->t = &TYPE(TY_U64); }
 	// else if (a->v_int <= U128_MAX) { a->t = &TYPE(TY_U128); }
-	
+
 	return a;
 }
 
 /* Parse a floating-point number. AK_FLT is terminal. */
 static inline ast *parse_flt(lex *l, syt *st) {
 	assert(T.k == TK_FLT);
-	
+
 	tok t = lex_next(l);
 	ast *a = ast_init(AK_FLT, t.ln, t.cl);
-	
+
 	a->s = strdup_or_fail(t.s);
 	a->v_flt = t.v_flt;
-	
+
 	/* Determine the minimum float type */
 	if (a->v_flt <= F32_MAX) { a->t = &TYPE(TY_F32); }
 	else if (a->v_flt <= F64_MAX) { a->t = &TYPE(TY_F64); }
 	else if (a->v_flt <= F128_MAX) { a->t = &TYPE(TY_F128); }
-	
+
 	return a;
 }
 
@@ -565,10 +565,10 @@ static inline char *strdup_or_fail(const char *s) {
 /* Recursively print an AST. */
 void ast_print(ast *a, uptr indent) {
 	for (uptr i = 0; i < indent; ++i) { printf("    "); }
-	
+
 	/* Print basic AST information (line:column: kind "string") */
 	printf("%zu:%zu: %s \"%s\"", a->ln + 1, a->cl + 1, ast_ks[a->k], a->s);
-	
+
 	/* Print type information if present */
 	if (a->t != null) { fputs(" -> ", stdout); }
 	for (type *t = a->t; t != null; t = t->base) switch (t->k) {
@@ -576,13 +576,13 @@ void ast_print(ast *a, uptr indent) {
 	case TY_ARR: { t->l != -1 ? printf("[%ld]", t->l) : printf("[]"); } break;
 	default:     { printf("%s", t->s); } break;
 	}
-	
+
 	/* Indicate presence of various fields */
 	fputs(" [", stdout);
 	fputc(a->h != 0 ? 'h' : '-', stdout);
 	fputc(a->st.a != null ? 's' : '-', stdout);
 	fputc(']', stdout);
-	
+
 	/* Indicate if the AST node has a value */
 	switch (a->k) {
 	case AK_BOOL: { printf(a->v_bool ? " = true" : " = false"); } break;
@@ -590,21 +590,21 @@ void ast_print(ast *a, uptr indent) {
 	case AK_FLT:  { printf(" = %Lf", a->v_flt); } break;
 	default: { /* Ignored */ } break;
 	}
-	
+
 	/* Indicate if the AST node has no parent */
 	if (a->p == null) { printf(" NO PARENT"); }
-	
+
 	fputc('\n', stdout);
-	
+
 	/* Print AST children */
 	for (uptr i = 0; i < a->c.al; i += 1) { ast_print(a->c.a[i], indent + 1); }
-	
+
 	if (a->st.a != null) {
 		printf("--- SYT for %s \"%s\"%s ---\n", ast_ks[a->k], a->s, a->st.pt == null ? " NO PARENT" : "");
 		syt_print(&a->st);
 		printf("--- SYT for %s \"%s\"%s ---\n", ast_ks[a->k], a->s, a->st.pt == null ? " NO PARENT" : "");
 	}
-	
+
 	return;
 }
 
diff --git a/src/parse.h b/src/parse.h
index bc043a7..d321d26 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -14,23 +14,23 @@
 /* Remember to update ast_ks in parse.c */
 typedef enum {
 	AK_VOID, AK_PROG, AK_ID, AK_BOOL, AK_INT, AK_FLT, AK_STR,
-	
+
 	AK_PROC, AK_TYPE, AK_CAST,
-	
+
 	AK_COMP, AK_DECL, AK_RETURN, AK_IF, AK_FOR,
-	
+
 	AK_POS, AK_NEG, AK_ADO, AK_DRF,
 	AK_ADD, AK_SUB, AK_MUL, AK_DIV, AK_MOD,
-	
+
 	AK_EQ, AK_NE, AK_LT, AK_LE, AK_GT, AK_GE,
-	
+
 	AK_LO_NOT, AK_LO_AND, AK_LO_OR,
 	AK_BW_NOT, AK_BW_AND, AK_BW_OR,  AK_BW_XOR, AK_BW_SHL, AK_BW_SHR,
-	
+
 	AK_ASSIGN, AK_AS_ADD, AK_AS_SUB, AK_AS_MUL, AK_AS_DIV, AK_AS_MOD,
-	
+
 	AK_CALL, AK_ARR, AK_SUBS,
-	
+
 	AK_HASH, AK_HASH_SYSCALL, AK_BUILTIN
 } ast_k;
 
@@ -43,7 +43,7 @@ typedef struct ast_s {
 	ast_k k; uptr ln, cl; u64 h; char *s; type *t; syt st;
 	struct ast_s *p; struct { struct ast_s **a; uptr al; } c;
 	union { bool v_bool; u64 v_int; f128 v_flt; };
-	
+
 	LLVMTypeRef llvm_t; LLVMValueRef llvm_v;
 } ast;
 
diff --git a/src/symbol.c b/src/symbol.c
index 21629c1..69bab3a 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -25,12 +25,12 @@ syt *syt_aloc(void) { return calloc(1, sizeof (syt)); }
 /* Uninitialise a symbol table. */
 void syt_free(syt *st) {
 	if (st == null || st->a == null) { return; }
-	
+
 	for (uptr i = 0; i < st->ac; i += 1) {
 		if (st->a[i].h == 0) { continue; }
 		free(st->a[i].k); /*free(s->a[i].v)*/
 	}
-	
+
 	free(st->a); *st = (syt){ null, 0, 0 };
 }
 
@@ -68,22 +68,22 @@ ast *syt_search(syt *st, char *k) {
 void syt_insert_h(syt *st, u64 h, char *k, ast *v) {
 	if (st->ac == 0 || st->al >= ((f64)st->ac * LOAD_FACTOR)) { syt_resize(st); }
 	uptr i = h % st->ac; k = strdup(k);
-	
+
 	for (uptr dist = 0;; i = (i + 1) % st->ac, dist += 1) {
 		if (st->a[i].h == 0) {
 			/* If an empty bucket is found, insert here */
 			st->a[i] = (typeof (*st->a)){ h, k, v };
 			st->al += 1; return;
 		}
-		
+
 		/* Calculate tsid, the DIB of the item at the current index */
 		uptr tsid = (i + st->ac - (st->a[i].h % st->ac)) % st->ac;
-		
+
 		if (dist > tsid) {
 			SWAP(st->a[i].h, h);
 			SWAP(st->a[i].k, k);
 			SWAP(st->a[i].v, v);
-			
+
 			dist = tsid;
 		}
 	}
@@ -92,12 +92,12 @@ void syt_insert_h(syt *st, u64 h, char *k, ast *v) {
 /* Lookup a key-value pair from a map using a precalculated hash. */
 ast *syt_lookup_h(syt *st, u64 h, char *k) {
 	if (st->a == null) { return null; }
-	
+
 	uptr i = h % st->ac;
-	
+
 	for (uptr dist = 0;; i = (i + 1) % st->ac, dist += 1) {
 		if (st->a[i].h == 0) { return null; }
-		
+
 		if (dist > DIB(i)) { return null; /* ? */ }
 		if ((st->a[i].h == h) && (strcmp(st->a[i].k, k) == 0)) {
 			return st->a[i].v;
@@ -108,27 +108,27 @@ ast *syt_lookup_h(syt *st, u64 h, char *k) {
 /* Remove a key-value pair from a map using a precalculated hash. */
 void syt_remove_h(syt *st, u64 h, char *k) {
 	if (st->a == null) { return; }
-	
+
 	uptr i = h % st->ac;
-	
+
 	for (uptr dist = 0;; i = (i + 1) % st->ac, dist += 1) {
 		if (st->a[i].h == 0) { return; }
-		
+
 		if (dist > DIB(i)) { return; }
 		if ((st->a[i].h == h) && (strcmp(st->a[i].k, k) == 0)) {
 			/* If the element to be removed is found, then deallocate it */
 			free(st->a[i].k);
 			st->a[i] = (typeof (*st->a)){ 0, null, null }; st->al -= 1;
-			
+
 			/*  */
 			for (uptr j = (i + 1) % st->ac;; i = j, j = (j + 1) % st->ac) {
 				if (st->a[j].h == 0 || DIB(j) == 0) { break; }
-				
+
 				SWAP(st->a[i].h, st->a[j].h);
 				SWAP(st->a[i].k, st->a[j].k);
 				SWAP(st->a[i].v, st->a[j].v);
 			}
-			
+
 			return;
 		}
 	}
@@ -138,12 +138,12 @@ void syt_remove_h(syt *st, u64 h, char *k) {
 ast *syt_search_h(syt *st, u64 h, char *k) {
 	ast *sm = syt_lookup_h(&kwt, h, k);
 	if (sm != null) { return sm; }
-	
+
 	for (; st != null; st = st->pt) {
 		sm = syt_lookup_h(st, h, k);
 		if (sm != null) { return sm; }
 	}
-	
+
 	return null;
 }
 
@@ -151,7 +151,7 @@ ast *syt_search_h(syt *st, u64 h, char *k) {
 void syt_print(syt *st) {
 	for (uptr i = 0; i < st->ac; i += 1) if (st->a[i].h != 0) {
 		printf("%s %s", ast_ks[st->a[i].v->k], st->a[i].k);
-		
+
 		if (st->a[i].v->k == AK_DECL && st->a[i].v->c.al > 0 && st->a[i].v->c.a[0]->k == AK_PROC) {
 			fputc('(', stdout);
 			for (uptr j = 0; j < st->a[i].v->c.al - 1; j += 1) {
@@ -159,14 +159,14 @@ void syt_print(syt *st) {
 			}
 			fputc(')', stdout);
 		}
-		
+
 		if (st->a[i].v->t != null) { fputs(" -> ", stdout); }
 		for (type *t = st->a[i].v->t; t != null; t = t->base) switch (t->k) {
 		case TY_PTR: { printf("*"); } break;
 		case TY_ARR: { t->l != -1 ? printf("[%ld]", t->l) : printf("[]"); } break;
 		default:     { printf("%s", t->s); } break;
 		}
-		
+
 		fputc('\n', stdout);
 	}
 }
@@ -189,17 +189,17 @@ static void syt_resize(syt *st) {
 		st->ac = INITIAL_CAPACITY;
 		st->a = calloc(st->ac, sizeof (*st->a)); return;
 	}
-	
+
 	/* Otherwise rehash every element into a new resized map */
 	syt old = *st; st->ac *= 2; st->al = 0;
 	st->a = calloc(st->ac, sizeof (*st->a));
-	
+
 	for (uptr i = 0; i < old.ac; i += 1) {
 		if (old.a[i].h == 0) { continue; }
-		
+
 		syt_insert(st, old.a[i].k, old.a[i].v);
 		free(old.a[i].k);
 	}
-	
+
 	free(old.a);
 }
diff --git a/src/type.c b/src/type.c
index 40c37b7..f12616d 100644
--- a/src/type.c
+++ b/src/type.c
@@ -12,42 +12,42 @@ type types[] = {
 	{ TY_ARR,  0,      -1, "arr"  },
 	{ TY_TYPE, 0,      -1, "type" },
 	{ TY_PROC, 0,      -1, "proc" },
-	
+
 	{ TY_BOOL, TF_BOOL, 1, "bool" },
 	{ TY_B8,   TF_BOOL, 1, "b8"   },
 	{ TY_B16,  TF_BOOL, 2, "b16"  },
 	{ TY_B32,  TF_BOOL, 4, "b32"  },
 	{ TY_B64,  TF_BOOL, 8, "b64"  },
-	
+
 	{ TY_UINT, TF_INT, -2, "uint" },
 	{ TY_U8,   TF_INT,  1, "u8"   },
 	{ TY_U16,  TF_INT,  2, "u16"  },
 	{ TY_U32,  TF_INT,  4, "u32"  },
 	{ TY_U64,  TF_INT,  8, "u64"  },
 	{ TY_U128, TF_INT, 16, "u128" },
-	
+
 	{ TY_SINT, TF_INT | TF_SIGN, -2, "sint" },
 	{ TY_S8,   TF_INT | TF_SIGN,  1, "s8"   },
 	{ TY_S16,  TF_INT | TF_SIGN,  2, "s16"  },
 	{ TY_S32,  TF_INT | TF_SIGN,  4, "s32"  },
 	{ TY_S64,  TF_INT | TF_SIGN,  8, "s64"  },
 	{ TY_S128, TF_INT | TF_SIGN, 16, "s128" },
-	
+
 	{ TY_F16,  TF_FLT | TF_SIGN,  2, "f16"  },
 	{ TY_F32,  TF_FLT | TF_SIGN,  4, "f32"  },
 	{ TY_F64,  TF_FLT | TF_SIGN,  8, "f64"  },
 	{ TY_F128, TF_FLT | TF_SIGN, 16, "f128" },
-	
+
 	{ TY_C32,  TF_CLX | TF_SIGN,  4, "c32"  },
 	{ TY_C64,  TF_CLX | TF_SIGN,  8, "c64"  },
 	{ TY_C128, TF_CLX | TF_SIGN, 16, "c128" },
 	{ TY_C256, TF_CLX | TF_SIGN, 32, "c256" },
-	
+
 	{ TY_Q64,  TF_QTN | TF_SIGN,  8, "q64"  },
 	{ TY_Q128, TF_QTN | TF_SIGN, 16, "q128" },
 	{ TY_Q256, TF_QTN | TF_SIGN, 32, "q256" },
 	{ TY_Q512, TF_QTN | TF_SIGN, 64, "q512" },
-	
+
 	{ TY_U16LE,  TF_INT | TF_LE,  2, "u16le"  },
 	{ TY_U32LE,  TF_INT | TF_LE,  4, "u32le"  },
 	{ TY_U64LE,  TF_INT | TF_LE,  8, "u64le"  },
@@ -56,7 +56,7 @@ type types[] = {
 	{ TY_U32BE,  TF_INT | TF_BE,  4, "u32be"  },
 	{ TY_U64BE,  TF_INT | TF_BE,  8, "u64be"  },
 	{ TY_U128BE, TF_INT | TF_BE, 16, "u128be" },
-	
+
 	{ TY_S16LE,  TF_INT | TF_SIGN | TF_LE,  2, "s16le"  },
 	{ TY_S32LE,  TF_INT | TF_SIGN | TF_LE,  4, "s32le"  },
 	{ TY_S64LE,  TF_INT | TF_SIGN | TF_LE,  8, "s64le"  },
@@ -65,7 +65,7 @@ type types[] = {
 	{ TY_S32BE,  TF_INT | TF_SIGN | TF_BE,  4, "s32be"  },
 	{ TY_S64BE,  TF_INT | TF_SIGN | TF_BE,  8, "s64be"  },
 	{ TY_S128BE, TF_INT | TF_SIGN | TF_BE, 16, "s128be" },
-	
+
 	{ TY_F16LE,  TF_FLT | TF_SIGN | TF_LE,  2, "f16le"  },
 	{ TY_F32LE,  TF_FLT | TF_SIGN | TF_LE,  4, "f32le"  },
 	{ TY_F64LE,  TF_FLT | TF_SIGN | TF_LE,  8, "f64le"  },
@@ -74,7 +74,7 @@ type types[] = {
 	{ TY_F32BE,  TF_FLT | TF_SIGN | TF_BE,  4, "f32be"  },
 	{ TY_F64BE,  TF_FLT | TF_SIGN | TF_BE,  8, "f64be"  },
 	{ TY_F128BE, TF_FLT | TF_SIGN | TF_BE, 16, "f128be" },
-	
+
 	{ TY_C32LE,  TF_CLX | TF_SIGN | TF_LE,  4, "c32le"  },
 	{ TY_C64LE,  TF_CLX | TF_SIGN | TF_LE,  8, "c64le"  },
 	{ TY_C128LE, TF_CLX | TF_SIGN | TF_LE, 16, "c128le" },
@@ -83,7 +83,7 @@ type types[] = {
 	{ TY_C64BE,  TF_CLX | TF_SIGN | TF_BE,  8, "c64be"  },
 	{ TY_C128BE, TF_CLX | TF_SIGN | TF_BE, 16, "c128be" },
 	{ TY_C256BE, TF_CLX | TF_SIGN | TF_BE, 32, "c256be" },
-	
+
 	{ TY_Q64LE,  TF_CLX | TF_SIGN | TF_LE,  8, "q64le"  },
 	{ TY_Q128LE, TF_CLX | TF_SIGN | TF_LE, 16, "q128le" },
 	{ TY_Q256LE, TF_CLX | TF_SIGN | TF_LE, 32, "q256le" },
@@ -92,7 +92,7 @@ type types[] = {
 	{ TY_Q128BE, TF_CLX | TF_SIGN | TF_BE, 16, "q128be" },
 	{ TY_Q256BE, TF_CLX | TF_SIGN | TF_BE, 32, "q256be" },
 	{ TY_Q512BE, TF_CLX | TF_SIGN | TF_BE,  4, "q512be" },
-	
+
 	{ TY_BYTE,   TF_INT,            1, "byte"   },
 	{ TY_CHAR,   TF_INT | TF_CHAR,  1, "char"   },
 	{ TY_RUNE,   TF_INT | TF_CHAR,  4, "rune"   },
@@ -107,10 +107,10 @@ static inline void types_alloc(type_a *ta, u64 min) {
 		ta->ac = 128; ta->a = malloc(ta->ac * sizeof (type));
 		if (ta->a == null) { error(1, "types: %s", SERR); }
 	}
-	
+
 	register u64 mul = 1, sp = ta->ac - ta->al;
 	for (; sp < min; mul *= 2, sp = (ta->ac * mul) - ta->al);
-	
+
 	if (mul > 1) {
 		ta->ac *= mul; ta->a = realloc(ta->a, ta->ac * sizeof (type));
 		if (ta->a == null) { error(1, "types: %s", SERR); }
@@ -126,22 +126,22 @@ static inline type *types_next(type_a *ta) {
 /* Initialise a new pointer type. */
 type *type_ptr(type *base, u64 n) {
 	types_alloc(&types_a, n); type *r = base;
-	
+
 	for (u64 i = 0; i < n; i += 1) {
 		register type *t = types_next(&types_a);
 		*t = TYPE(TY_PTR); t->base = r; r = t;
 	}
-	
+
 	return r;
 }
 
 /* Initialise a new array type. */
 type *type_arr(type *base, u64 l) {
 	types_alloc(&types_a, 1);
-	
+
 	type *t = types_next(&types_a);
 	*t = TYPE(TY_ARR); t->l = l; t->base = base;
-	
+
 	return t;
 }
 
@@ -167,21 +167,21 @@ inline bool is_sign(type *t) { return (t->f & TF_SIGN); }
 inline bool is_equal(type *t1, type *t2) {
 	if (t1 == null || t2 == null) { return false; }
 	if (t1 == t2) { return true; }
-	
+
 	if (t1->k != t2->k) { return false; }
 	if (t1->f != t2->f) { return false; }
 	if (t1->l != t2->l) { return false; }
-	
+
 	/* Check if all base types match */
 	for (type *b1 = t1->base, *b2 = t2->base;; b1 = b1->base, b2 = b2->base) {
 		if (b1 == null && b2 == null) { break; }
 		if ((b1 == null) != (b2 == null)) { return false; }
-		
+
 		if (b1->k != b2->k) { return false; }
 		if (b1->f != b2->f) { return false; }
 		if (b1->l != b2->l) { return false; }
 	}
-	
+
 	return true;
 }
 
@@ -189,9 +189,9 @@ inline bool is_equal(type *t1, type *t2) {
 inline bool is_com(type *t1, type *t2) {
 	if (t1 == null || t2 == null) { return false; }
 	if (is_equal(t1, t2)) { return true; }
-	
+
 	if (is_int(t1) && is_int(t2)) { return true; }
 	if (is_flt(t1) && is_flt(t2)) { return true; }
-	
+
 	return false;
 }
diff --git a/src/type.h b/src/type.h
index 67472a0..7f1647f 100644
--- a/src/type.h
+++ b/src/type.h
@@ -10,31 +10,31 @@
 
 typedef enum {
 	TY_VOID, TY_PTR, TY_ARR, TY_TYPE, TY_PROC,
-	
+
 	TY_BOOL, TY_B8, TY_B16, TY_B32, TY_B64,
-	
+
 	TY_UINT, TY_U8, TY_U16, TY_U32, TY_U64, TY_U128,
 	TY_SINT, TY_S8, TY_S16, TY_S32, TY_S64, TY_S128,
-	
+
 	TY_F16, TY_F32, TY_F64, TY_F128,
 	TY_C32, TY_C64, TY_C128, TY_C256,
 	TY_Q64, TY_Q128, TY_Q256, TY_Q512,
-	
+
 	TY_U16LE, TY_U32LE, TY_U64LE, TY_U128LE,
 	TY_U16BE, TY_U32BE, TY_U64BE, TY_U128BE,
-	
+
 	TY_S16LE, TY_S32LE, TY_S64LE, TY_S128LE,
 	TY_S16BE, TY_S32BE, TY_S64BE, TY_S128BE,
-	
+
 	TY_F16LE, TY_F32LE, TY_F64LE, TY_F128LE,
 	TY_F16BE, TY_F32BE, TY_F64BE, TY_F128BE,
-	
+
 	TY_C32LE, TY_C64LE, TY_C128LE, TY_C256LE,
 	TY_C32BE, TY_C64BE, TY_C128BE, TY_C256BE,
-	
+
 	TY_Q64LE, TY_Q128LE, TY_Q256LE, TY_Q512LE,
 	TY_Q64BE, TY_Q128BE, TY_Q256BE, TY_Q512BE,
-	
+
 	TY_BYTE, TY_CHAR, TY_RUNE, TY_STRING,
 } type_k;
 
@@ -43,10 +43,10 @@ typedef enum {
 	TF_BOOL = BIT(2), TF_INT  = BIT(3),
 	TF_FLT  = BIT(4), TF_CLX  = BIT(5),
 	TF_QTN  = BIT(6), TF_SIGN = BIT(7),
-	
+
 	TF_LE   = BIT(14), TF_BE     = BIT(15),
 	TF_CHAR = BIT(16), TF_STRING = BIT(17),
-	
+
 	TF_NUM = TF_INT | TF_FLT | TF_CLX,
 } type_f;
 
diff --git a/src/util/optget.c b/src/util/optget.c
index 630a556..12f103d 100644
--- a/src/util/optget.c
+++ b/src/util/optget.c
@@ -20,20 +20,20 @@ int optget(struct opt *opt, char *av[], int flags) {
 		if (!cur) { opt->ind -= opt->nop; opt->nop = 0; return -1; }
 	}
 	else if (!cur || (cur[0] != '-' || cur[1] == 0)) { return -1; }
-	
+
 	int optind = opt->ind, optret;
-	
+
 	if (cur[1] == '-') {
 		if (cur[2] == 0) { if (opt->nop) {
 				permute(av, opt->ind++, opt->nop);
 				opt->ind -= opt->nop; opt->nop = 0;
 			} else { ++opt->ind; } return -1;
 		}
-		
+
 		int optend, lop; optret = '?'; opt->opt = 0; opt->lop = cur;
 		if (!opt->lops) { goto nol; }
 		for (optend = 2; cur[optend] != '=' && cur[optend] != 0; ++optend);
-		
+
 		for (lop = 0; opt->lops[lop].str; ++lop) {
 			if (strncmp(&cur[2], opt->lops[lop].str, (size_t)optend - 2) == 0) {
 				if (!opt->lops[lop].str[optend - 2]) {
@@ -41,7 +41,7 @@ int optget(struct opt *opt, char *av[], int flags) {
 				}
 			}
 		}
-		
+
 		if (opt->lops[lop].arg > ARG_NUL) {
 			if (cur[optend]) { opt->arg = &cur[optend + 1]; }
 			else if (av[opt->ind + 1]) { opt->arg = av[++opt->ind]; }
@@ -51,13 +51,13 @@ int optget(struct opt *opt, char *av[], int flags) {
 			}
 		}
 		else { opt->arg = NULL; }
-		
+
 nol:	opt->pos = 0;
 	}
 	else {
 		optret = opt->opt = cur[opt->pos++]; opt->lop = NULL;
 		const char *optchr = strchr(opt->str, opt->opt);
-		
+
 		if (!optchr) { optret = '?'; }
 		else if (optchr[1] == ':') {
 			if (cur[opt->pos]) { opt->arg = &cur[opt->pos]; }
@@ -67,14 +67,14 @@ nol:	opt->pos = 0;
 		}
 		else { opt->arg = NULL; }
 	}
-	
+
 	if (!opt->pos || !cur[opt->pos]) {
 		++opt->ind; opt->pos = 1;
 		if (opt->nop) for (; optind < opt->ind; ++optind) {
 			permute(av, optind, opt->nop);
 		}
 	}
-	
+
 	if (optret == '?' && opt->str[0] != ':') {
 		if (opt->opt) { warn("%c: invalid option", opt->opt); }
 		else if (opt->lop) { warn("%s: invalid option", opt->lop); }
@@ -83,7 +83,7 @@ nol:	opt->pos = 0;
 		if (opt->opt) { warn("%c: option requires argument", opt->opt); }
 		else if (opt->lop) { warn("%s: option requires argument", opt->lop); }
 	}
-	
+
 	return optret;
 }