diff lwasm/symbol.c @ 363:d96c30e60ddf

Added pass2 and various supporting logic including symbol lookups
author lost@starbug
date Tue, 06 Apr 2010 21:03:19 -0600
parents 7d91ab7ac7d6
children 6b33faa21a0a
line wrap: on
line diff
--- a/lwasm/symbol.c	Thu Apr 01 20:56:19 2010 -0600
+++ b/lwasm/symbol.c	Tue Apr 06 21:03:19 2010 -0600
@@ -65,7 +65,7 @@
 	}
 
 	if (islocal)
-		context = as -> context;
+		context = cl -> context;
 	
 	// first, look up symbol to see if it is already defined
 	for (se = as -> symtab.head; se; se = se -> next)
@@ -95,6 +95,10 @@
 		version++;
 	}
 	
+	// symplify the symbol expression - replaces "SET" symbols with
+	// symbol table entries
+	lwasm_reduce_expr(as, val);
+	
 	se = lw_alloc(sizeof(struct symtabe));
 	se -> next = as -> symtab.head;
 	as -> symtab.head = se;
@@ -105,7 +109,53 @@
 	return se;
 }
 
-struct symtabe * lookup_symbol(asmstate_t *as, line_t *cl, char *sym, int context, int version)
+// for "SET" symbols, always returns the LAST definition of the
+// symbol. This works because the lwasm_reduce_expr() call in 
+// register_symbol will ensure there are no lingering "var" references
+// to the set symbol anywhere in the symbol table; they will all be
+// converted to direct references
+// NOTE: this means that for a forward reference to a SET symbol,
+// the LAST definition will be the one used.
+// This arrangement also ensures that any reference to the symbol
+// itself inside a "set" definition will refer to the previous version
+// of the symbol.
+struct symtabe * lookup_symbol(asmstate_t *as, line_t *cl, char *sym)
 {
-	return NULL;
+	int local = 0;
+	struct symtabe *s, *s2;
+
+	// check if this is a local symbol
+	if (strchr(sym, '@') || strchr(sym, '?'))
+		local = 1;
+	
+	if (cl && !CURPRAGMA(cl, PRAGMA_DOLLARNOTLOCAL) && strchr(sym, '$'))
+		local = 1;
+	if (!cl && !(as -> pragmas & PRAGMA_DOLLARNOTLOCAL) && strchr(sym, '$'))
+		local = 1;
+	
+	// cannot look up local symbol in global context!!!!!
+	if (!cl && local)
+		return NULL;
+	
+	for (s = as -> symtab.head, s2 = NULL; s; s = s -> next)
+	{
+		if (!strcmp(sym, s -> symbol))
+		{
+			if (local && s -> context != cl -> context)
+				continue;
+			
+			if (s -> flags & symbol_flag_set)
+			{
+				// look for highest version of symbol
+				if (s -> version > s2 -> version)
+					s2 = s;
+				continue;
+			}
+			break;
+		}
+	}
+	if (!s && s2)
+		s = s2;
+	
+	return s;
 }