diff parser.c @ 0:76568becd6d6

Rhope Alpha 2a source import
author Mike Pavone <pavone@retrodev.com>
date Tue, 28 Apr 2009 23:06:07 +0000
parents
children 9749109b3198
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parser.c	Tue Apr 28 23:06:07 2009 +0000
@@ -0,0 +1,1633 @@
+#include "structs.h"
+#include "visuality.h"
+#include "debugmacros.h"
+#ifdef WIN32
+	#include "windows.h"
+#endif
+#include <stdio.h>
+#include "interp.h"
+#include "parser.h"
+#include <string.h>
+#include <stdlib.h>
+
+extern int num_workers;
+extern int num_wires;
+
+/*#ifdef SEGA
+#define NUM_WORKERS_START	40
+#define NUM_WIRES_START		80
+#else
+#define NUM_WORKERS_START	1024
+#define NUM_WIRES_START		2048
+#endif*/
+#define NUM_WORKERS_START 	20
+#define NUM_WIRES_START		40
+//TODO: Figure out why setting those defines to 16 and 32 respectively causes problems
+
+BOOL is_whitespace(char c)
+{
+	if(c == ' ' || c == '\t' || c == '\n' || c == '\r')
+		return TRUE;
+	return FALSE;
+}
+
+company * create_company(program * prog, char * name, int num_workers, int num_rooms, BOOL buildable)
+{
+	company * this_comp = &(prog->companylist[prog->num_companies]);
+	DEBUGPRINTF("create_company %s with %d workers and %d rooms\n", name, num_workers, num_rooms);
+	this_comp->type_id = prog->num_companies++;
+	strncpy(this_comp->name, name, 256);
+	this_comp->name[255] = '\0';
+	if(num_workers)
+		this_comp->methodlist = MALLOC(sizeof(worker_def *) * num_workers, "company methodlist");
+	else
+		this_comp->methodlist = NULL;
+	this_comp->num_methods = 0;//num_workers;
+	this_comp->method_storage = num_workers;
+	if(num_rooms)
+	{
+		this_comp->room_list = MALLOC(sizeof(company_room) * num_rooms, "company roomlist");
+		DEBUGPRINTF("Allocated %d bytes at %X for room_list\n", sizeof(company_room) * num_rooms, this_comp->room_list);
+	}
+	else
+		this_comp->room_list = NULL;
+	this_comp->num_rooms = 0;//num_rooms;
+	this_comp->room_storage = num_rooms;
+	if(buildable)
+		this_comp->build_size = 0;
+	else
+		this_comp->build_size = -1;
+	VIS_InitializeCriticalSection(this_comp->lock);
+	return this_comp;
+}
+
+int add_method(company * this_comp, worker_def * def)
+{
+	worker_def ** temp;
+	int i;
+	DEBUGPUTS("add_method: ");
+	DEBUGPRINTF("%s\n", def->name);
+	VIS_EnterCriticalSection(this_comp->lock);
+	if(this_comp->method_storage - this_comp->num_methods <= 0)
+	{
+		if(this_comp->method_storage < 2)
+			this_comp->method_storage = 4;
+		else
+			this_comp->method_storage = this_comp->method_storage + ((this_comp->method_storage) >> 1);
+		temp = MALLOC(sizeof(worker_def *) * this_comp->method_storage, "company method storage");
+		for(i = 0; i < this_comp->num_methods; ++i)
+			temp[i] = this_comp->methodlist[i];
+		VIS_FREE(this_comp->methodlist, "company methodlist");
+		this_comp->methodlist = temp;
+	}
+	i = this_comp->num_methods;
+	this_comp->methodlist[this_comp->num_methods++] = def;
+	DEBUGPRINTF("%s now has %d methods\n", this_comp->name, this_comp->num_methods);
+	VIS_LeaveCriticalSection(this_comp->lock);
+	return i;
+}
+int room_build_sizes[] = {0, sizeof(char), sizeof(short), sizeof(long), sizeof(float), sizeof(double), -1, -1, -1, -1, -1, sizeof(datum *), 0};
+int add_comp_room(company * this_comp, char * name, int set_func, int get_func, short set_func_type, short get_func_type)
+{
+	company_room * temp;
+	int i;
+	int min_build_size;
+	VIS_EnterCriticalSection(this_comp->lock);
+	DEBUGPRINTF("add_comp_room: %s", name);
+	DEBUGPRINTF(", num_rooms: %d, room_storage: %d\n", this_comp->num_rooms, this_comp->room_storage);
+	if(this_comp->room_storage - this_comp->num_rooms <= 0)
+	{
+		if(this_comp->room_storage < 2)
+			this_comp->room_storage = 4;
+		else
+			this_comp->room_storage = this_comp->room_storage + ((this_comp->room_storage) >> 1);
+		temp = MALLOC(sizeof(company_room) * this_comp->room_storage, "company room storage");
+		memcpy(temp, this_comp->room_list, sizeof(company_room)*this_comp->num_rooms);
+		VIS_FREE(this_comp->room_list, "company room list");
+		this_comp->room_list = temp;
+	}
+	if(this_comp->build_size >= 0)
+	{
+		DEBUGPRINTF("get_func_type: %d, room_build_sizes[%d] = %d\n", get_func_type, get_func_type, room_build_sizes[get_func_type]);
+		if(get_func_type && get_func_type != ROOM_WORKER && get_func == -1)
+			get_func = this_comp->build_size;
+		if(set_func_type && set_func_type != ROOM_WORKER && set_func == -1)
+			set_func = this_comp->build_size;
+		if(room_build_sizes[set_func_type])
+			if(room_build_sizes[set_func_type] > room_build_sizes[get_func_type])
+				min_build_size = room_build_sizes[set_func_type] + set_func;
+			else
+				min_build_size = room_build_sizes[get_func_type] + get_func;
+		else if(room_build_sizes[get_func_type])
+			min_build_size = room_build_sizes[get_func_type] + get_func;
+		if(min_build_size > this_comp->build_size)
+			this_comp->build_size = min_build_size;	
+	}
+	i = this_comp->num_rooms;
+	DEBUGPUTS("Copying name\n");
+	this_comp->room_list[this_comp->num_rooms++].name = MALLOC(strlen(name) + 1, "company room name");
+	strcpy(this_comp->room_list[i].name, name);
+	DEBUGPUTS("Setting func types\n");
+	this_comp->room_list[i].set_func_type = set_func_type;
+	this_comp->room_list[i].get_func_type = get_func_type;
+	DEBUGPRINTF("Setting funcs: get = %d, set = %d\n", get_func, set_func);
+	//TODO: Change the signature of this function so that get_func and set_func are void * so we can safely pass in pointers for future get_func types
+	this_comp->room_list[i].get_func = (void *)get_func;
+	this_comp->room_list[i].set_func = (void *)set_func;
+	DEBUGPRINTF("Build size is now: %d\n", this_comp->build_size);
+	DEBUGPUTS("before return\n");
+	VIS_LeaveCriticalSection(this_comp->lock);
+	return i;
+}
+
+worker_def * create_worker(program * prog, char * name, int num_inputs, int num_outputs, short type)
+{
+	custom_worker * aworker;
+	int i, j;
+	int thisdef;
+	worker_def * deflist;
+	DEBUGPRINTF("create_worker: %s with %d inputs and %d outputs\n", name, num_inputs, num_outputs);
+	if(!strcmp(name, "Main"))
+	{
+		thisdef = 0;
+		deflist = prog->defs->deflist;
+	}
+	else
+	{
+		if(prog->current->num_defs >= prog->current->defs_storage) {
+			prog->current->next = MALLOC(sizeof(defchunk) + (START_DEF_STORAGE - 1) * sizeof(worker_def), "worker def storage");
+			prog->current = prog->current->next;
+			prog->current->defs_storage = START_DEF_STORAGE;
+			prog->current->num_defs = 0;
+			prog->current->next = NULL;
+		}
+		if(prog->current == prog->defs && prog->current->num_defs == 0)
+			prog->current->num_defs = 1;
+		thisdef = prog->current->num_defs;
+		deflist = prog->current->deflist;
+	}
+	DEBUGPRINTF("new deflist index: %d\n", thisdef);
+	if(type & USER_FLAG && (type & TYPE_MASK) == WORKER_TYPE)
+	{
+		//puts("Creating custom worker.");
+		aworker = MALLOC(sizeof(custom_worker), "custom worker implementation");
+		aworker->num_workers = 0;
+		aworker->num_wires = 0;
+		aworker->workerlist = MALLOC(sizeof(worker)*NUM_WORKERS_START, "custom worker workerlist");
+		aworker->worker_storage = NUM_WORKERS_START;
+		aworker->wirelist = MALLOC(sizeof(wire)*NUM_WIRES_START, "custom worker wirelist");
+		aworker->wire_storage = NUM_WIRES_START;
+		aworker->workers_to_wires_up = MALLOC(sizeof(int)*(NUM_WIRES_START+1),"custom worker workers to wires up");
+		aworker->workers_to_wires_down = MALLOC(sizeof(int)*(NUM_WIRES_START+1),"custom worker workers to wires down");
+		aworker->dirty = TRUE;
+		VIS_InitializeCriticalSection(aworker->lock);
+		deflist[thisdef].implement_func = aworker;
+	}
+	DEBUGPUTS("Setting properties\n");
+	deflist[thisdef].num_inputs = num_inputs;
+	deflist[thisdef].num_outputs = num_outputs;
+	deflist[thisdef].type = type;
+	DEBUGPUTS("Calling malloc\n");
+	deflist[thisdef].name = MALLOC(strlen(name)+1, "worker def name");
+	DEBUGPRINTF("malloc return: %X, calling strcpy\n", deflist[thisdef].name);
+	strcpy(deflist[thisdef].name, name);
+	DEBUGPUTS("strcpy done\n");
+	
+	if(num_inputs)
+		deflist[thisdef].input_types = MALLOC(sizeof(short) * num_inputs, "worker def input types");
+	else
+		deflist[thisdef].input_types = NULL;
+	if(num_outputs)
+		deflist[thisdef].output_types = MALLOC(sizeof(short) * num_outputs, "worker def output types");
+	else
+		deflist[thisdef].output_types = NULL;
+	for(i = 0; i < num_inputs; ++i)
+		deflist[thisdef].input_types[i] = ANY_TYPE;
+	deflist[thisdef].num_stores = 0;
+	deflist[thisdef].uses_stores = NULL;
+	deflist[thisdef].transaction_flags = TRANSACTION_RETRY;
+	if(thisdef >= prog->current->num_defs)
+		prog->current->num_defs = thisdef+1;
+	for(i = 0; name[i] != '\0'; ++i)
+	{
+		if(name[i] == '@')
+		{
+			DEBUGPRINTF("Name ends in %s\n", name+i);
+			for(j = 0; j < prog->num_companies; ++j)
+			{
+				if(!strcmp(name+i+1, prog->companylist[j].name))
+				{
+					DEBUGPRINTF("Worker is a method of company %d, ", j);
+					DEBUGPRINTF("%s\n", prog->companylist[j].name);
+					add_method(prog->companylist+j, deflist+thisdef);
+					break;
+				}
+			}
+			break;
+		}
+	}
+	deflist[thisdef].program = prog;
+	return deflist + thisdef;
+}
+
+int find_worker(char * name, int * num_inputs, int * num_outputs, program * prog, worker_def ** def)
+{
+	int i;
+	int term;
+	int len;
+	defchunk * current;
+	worker_def * temp;
+	DEBUGPRINTF("Calling strlen on name: %X\n", name);
+	len = strlen(name);
+	DEBUGPRINTF("find_worker: %s\n", name);
+	if(len >= 2 && !strcmp(name+len-2, ">>"))
+	{
+		DEBUGPUTS("Get property\n");
+		term = len-2;
+		for(i = term-1; i > 0; --i)
+		{
+			if(name[i] == ' ')
+				term = i;
+			else
+				break;
+		}
+		DEBUGPRINTF("term: %d\n", term);
+		name[term] = '\0';
+		DEBUGPRINTF("name: %s\n", name);
+		if(num_inputs);
+			*num_inputs = 1;
+		if(num_outputs)
+			*num_outputs = 1;
+		return -1;
+	}
+	if(len >= 2 && !strcmp(name+len-2, "<<"))
+	{
+		DEBUGPUTS("Set property\n");
+		term = len-2;
+		for(i = term-1; i > 0; --i)
+		{
+			if(name[i] == ' ')
+				term = i;
+			else
+				break;
+		}
+		DEBUGPRINTF("term: %d\n", term);
+		name[term] = '\0';
+		DEBUGPRINTF("name: %s\n", name);
+		if(num_inputs);
+			*num_inputs = 2;
+		if(num_outputs)
+			*num_outputs = 1;
+		return -2;
+	}
+	current = prog->defs;
+	while(current)
+	{
+		for(i = 0; i < current->num_defs; ++i)
+		{
+			if(current->deflist[i].name && !strcmp(current->deflist[i].name, name))
+			{
+				DEBUGPRINTF("Found worker #%d\n", i);
+				if(num_inputs)
+					*num_inputs = current->deflist[i].num_inputs;
+				if(num_outputs)
+					*num_outputs = current->deflist[i].num_outputs;
+				if(def)
+					*def = current->deflist + i;
+				return i;
+			}
+		}
+		current = current->next;
+	}
+	if(num_inputs && num_outputs)
+	{
+		for(i = 1; i < prog->num_companies; ++i)
+		{
+			temp = find_method(i, name, *num_inputs, prog);
+			if(temp && temp->num_outputs >= *num_outputs)
+			{
+				*def = create_worker(prog, name, temp->num_inputs, temp->num_outputs, MAGIC_TYPE);
+				return 1;
+			}
+		}
+	}
+	else
+	{
+		for(i = 1; i < prog->num_companies; ++i)
+		{
+			temp = find_method_noinputcheck(i, name, prog);
+			if(temp)
+			{
+				*def = create_worker(prog, name, temp->num_inputs, temp->num_outputs, MAGIC_TYPE);
+				return 1;
+			}
+		}
+	}
+	DEBUGPUTS("Could not find worker\n");
+	return -3;
+}
+
+int generic_add_to_def(worker_def * parent, char * name,int display_type, int type, int num_inputs, int num_outputs, double xpos, double ypos)
+{
+	int returnval;
+	worker * temp;
+	VIS_EnterCriticalSection(parent->implement_func->lock);
+		if(parent->implement_func->num_workers >= parent->implement_func->worker_storage) {
+			parent->implement_func->worker_storage = parent->implement_func->num_workers + (parent->implement_func->num_workers >> 1);
+			parent->implement_func->workerlist = realloc(parent->implement_func->workerlist, parent->implement_func->worker_storage * sizeof(worker));
+		}
+		strcpy(parent->implement_func->workerlist[parent->implement_func->num_workers].name, name);
+		parent->implement_func->workerlist[parent->implement_func->num_workers].type=type;
+		parent->implement_func->workerlist[parent->implement_func->num_workers].num_inputs = num_inputs;
+		parent->implement_func->workerlist[parent->implement_func->num_workers].num_outputs = num_outputs;
+		parent->implement_func->workerlist[parent->implement_func->num_workers].null_input = FALSE;
+		parent->implement_func->workerlist[parent->implement_func->num_workers].magic_cache_implement = NULL;
+		parent->implement_func->workerlist[parent->implement_func->num_workers].magic_cache_type = 0;
+		VIS_InitializeCriticalSection(parent->implement_func->workerlist[parent->implement_func->num_workers].lock);
+		parent->implement_func->dirty = TRUE;
+		//puts("end generic_add_to_def");
+		DEBUGPRINTF("generic_add_to_def: %s with type %d and num_inputs %d and num_outputs %d returned %d\n", name, type, num_inputs, num_outputs, parent->implement_func->num_workers);
+		returnval =  parent->implement_func->num_workers++;
+	VIS_LeaveCriticalSection(parent->implement_func->lock);
+	return returnval;
+}
+
+int add_worker_to_def(worker_def * parent, worker_def * worker, double xpos, double ypos)
+{
+	int list_index;
+	list_index = generic_add_to_def(parent, worker->name, TRAPEZOID, WORKER, worker->num_inputs, worker->num_outputs, xpos, ypos);
+
+	parent->implement_func->workerlist[list_index].value_index = worker;
+	return list_index;
+}
+
+int add_get_comp_room(worker_def * parent, char * name, double xpos, double ypos)
+{
+	return generic_add_to_def(parent, name, RECTANGLE, GET_COMP, 1, 2, xpos, ypos);
+}
+
+int add_set_comp_room(worker_def * parent, char * name, double xpos, double ypos)
+{
+	return generic_add_to_def(parent, name, RECTANGLE, SET_COMP, 2, 1, xpos, ypos);
+}
+
+int add_global(worker_def * parent, char * name, double xpos, double ypos, int type)
+{
+	int i,j;
+	int thisdef;
+	int num_in, num_out;
+	if(type == SET_GLOBAL)
+	{
+		num_in = 1;
+		num_out = 0;
+		parent->transaction_flags |= TRANSACTION_WRITE;
+	}
+	else
+	{
+		num_in = 0;
+		num_out = 1;
+	}
+	thisdef = generic_add_to_def(parent, name, RECTANGLE, type, num_in, num_out, xpos, ypos);
+	for(i = 0; name[i+1] != '\0'; ++i)
+	{
+		if(name[i] == ':' && name[i+1] == ':')
+		{
+			parent->implement_func->workerlist[thisdef].value_index = (void *)-1;
+			if(i > 0)
+			{
+				for(j = 0; j < parent->num_stores; ++j)
+				{
+					if(strlen(parent->uses_stores[j]) == i && !memcmp(parent->uses_stores[j], name, i))
+					{
+						parent->implement_func->workerlist[thisdef].value_index = (void *)j;
+						break;
+					}
+				}
+				if(parent->implement_func->workerlist[thisdef].value_index < 0)
+				{
+					name[i] = '\0';
+					printf("Error: Worker %s is not declared to use global store %s but references it.\n", parent->name, name);
+					exit(-1);
+				} 
+			}
+			else if(type == SET_GLOBAL)
+				parent->implement_func->workerlist[thisdef].value_index = 0;
+			parent->implement_func->workerlist[thisdef].io_num = i+2;
+			break;
+		}
+	}
+	return thisdef;
+}
+
+int add_global_get(worker_def * parent, char * name, double xpos, double ypos)
+{
+	return add_global(parent, name, xpos, ypos, GET_GLOBAL);
+}
+
+int add_global_set(worker_def * parent, char * name, double xpos, double ypos)
+{
+	return add_global(parent, name, xpos, ypos, SET_GLOBAL);
+}
+
+int find_object(worker_def * def, char * name, int type)
+{
+	int i;
+	for(i = 0; i < def->implement_func->num_workers; ++i)
+		if(!strcmp(def->implement_func->workerlist[i].name, name) && def->implement_func->workerlist[i].type == 1)
+			break;
+	if(i < def->implement_func->num_workers)
+		return i;
+	return -1;
+}
+
+int create_find_room(worker_def * def, char * name, double xpos, double ypos)
+{
+	int found = find_object(def, name, ROOM);
+	if(found >= 0)
+		return found;
+	return generic_add_to_def(def, name, RECTANGLE, ROOM, 1, 1, xpos, ypos);
+}
+
+int add_constant(worker_def * def, char * value, double xpos, double ypos)
+{
+	int index = generic_add_to_def(def, value, RECTANGLE, CONSTANT, 0, 1, xpos, ypos);
+	def->implement_func->workerlist[index].value_index = get_constant(value, -1, def->program);
+	return index;
+}
+
+int add_input_num(worker_def * def, char * name, int input_num, double xpos, double ypos)
+{
+	int i;
+	unsigned short * temp_types;
+	int found;
+	if(def->num_inputs <= input_num)
+	{
+		temp_types = def->input_types;
+		def->input_types = MALLOC(sizeof(short)*(input_num+1), "worker def input types");
+		if(temp_types) {
+			memcpy(def->input_types, temp_types, sizeof(short)*def->num_inputs);
+			VIS_FREE(temp_types, "temp types?");
+		}
+		for(i = def->num_inputs; i <= input_num; ++i)
+			def->input_types[i] = ANY_TYPE;
+		def->num_inputs = input_num+1;
+	}
+	found = generic_add_to_def(def, name, RECTANGLE, INPUT, 0, 1, xpos, ypos);
+	def->implement_func->workerlist[found].io_num = input_num;
+	return found;
+}
+int add_input(worker_def * def, char * name, double xpos, double ypos)
+{
+	
+	int input_num;
+	int i;
+	for(i = 0; name[i] != 0; ++i)
+		if(name[i] == '(')
+		{
+			input_num = atol(name+i+1);
+			break;
+		}
+	return add_input_num(def, name, input_num, xpos, ypos);
+}
+
+int add_output_num(worker_def * def, char * name, int output_num, double xpos, double ypos)
+{
+	int i;
+	unsigned short * temp_types;
+	int found;
+	if(def->num_outputs <= output_num)
+	{
+		temp_types = def->output_types;
+		def->output_types = MALLOC(sizeof(short)*(output_num+1), "worker def output types");
+		if(temp_types)
+		{
+			memcpy(def->output_types, temp_types, sizeof(short)*def->num_outputs);
+			VIS_FREE(temp_types, "temp types?");
+		}
+		for(i = def->num_outputs; i <= output_num; ++i)
+			def->output_types[i] = ANY_TYPE;
+		def->num_outputs = output_num+1;
+	}
+	found = generic_add_to_def(def, name, RECTANGLE, OUTPUT, 1, 0, xpos, ypos);
+	def->implement_func->workerlist[found].io_num = output_num;
+	return found;
+}
+int add_output(worker_def * def, char * name, double xpos, double ypos)
+{
+	int output_num;
+	int i;
+	
+	for(i = 0; name[i] != 0; ++i)
+		if(name[i] == '(')
+		{
+			output_num = atol(name+i+1);
+			break;
+		}
+	return add_output_num(def, name, output_num, xpos, ypos);
+}
+
+int create_find_output(worker_def * def, char * name, double xpos, double ypos)
+{
+	int output_num;
+	int i;
+	unsigned short * temp_types;
+	int found = find_object(def, name, OUTPUT);
+	if(found >= 0)
+		return found;
+	return add_output(def, name, xpos, ypos);
+}
+
+void add_wire(worker_def * def, int start, int output_num, int end, int input_num)
+{
+	VIS_EnterCriticalSection(def->implement_func->lock);
+		if(def->implement_func->num_wires >= def->implement_func->wire_storage) {
+			def->implement_func->wire_storage = def->implement_func->num_wires + (def->implement_func->num_wires >> 1);
+			def->implement_func->wirelist = realloc(def->implement_func->wirelist, def->implement_func->wire_storage * sizeof(wire));
+			def->implement_func->workers_to_wires_up = realloc(def->implement_func->workers_to_wires_up, (def->implement_func->wire_storage+1) * sizeof(int));
+			def->implement_func->workers_to_wires_down = realloc(def->implement_func->workers_to_wires_down, (def->implement_func->wire_storage+1) * sizeof(int));
+		}
+		def->implement_func->wirelist[def->implement_func->num_wires].start_worker = start;
+		def->implement_func->wirelist[def->implement_func->num_wires].end_worker = end;
+		def->implement_func->wirelist[def->implement_func->num_wires].output_num = output_num;
+		def->implement_func->wirelist[def->implement_func->num_wires].input_num = input_num;
+		def->implement_func->dirty = TRUE;
+		++def->implement_func->num_wires;
+		if(input_num == -1)
+		{
+			def->implement_func->workerlist[end].null_input = TRUE;
+		}
+	VIS_LeaveCriticalSection(def->implement_func->lock);
+}
+
+int process_expression(worker_def * def, int num_outputs, char ** outvars, int num_inputs, char ** inputs, char * workername, BOOL worker_expr, int block_depth, int * block_workers, int * block_output, int last_worker)
+{
+	int i,j;
+	int current;
+	int this_worker;// = ++return_worker;
+	int expected_in, expected_out;
+	int input_num=-1;
+	int worker_num;
+	worker_def * call_def;
+	BOOL block_attach=FALSE;
+	BOOL room = FALSE;
+	BOOL global_flag;
+	if(worker_expr)
+	{
+		DEBUGPUTS("calling find_worker\n");
+		expected_in = num_inputs;
+		expected_out = num_outputs;
+		worker_num = find_worker(workername, &expected_in, &expected_out, def->program, &call_def);
+		DEBUGPRINTF("\nWorker %s with %d inputs and %d outputs expects %d inputs and %d outputs\n", workername, num_inputs, num_outputs, expected_in, expected_out);
+		if(worker_num >= 0)
+			this_worker = add_worker_to_def(def, call_def, 1.0, 1.0);
+		else if(worker_num == -1)
+			this_worker = add_get_comp_room(def, workername, 1.0, 1.0);
+		else if(worker_num == -2)
+			this_worker = add_set_comp_room(def, workername, 1.0, 1.0);
+		else
+		{
+			ERRORPRINTF("Could not find a worker named %s or a method of the same name with %d inputs and at least %d outputs\n", workername, num_inputs, num_outputs);
+			for(i = 0; i < num_inputs; ++i)
+			{
+				ERRORPRINTF("Input %d was %s\n", i, inputs[i]);
+			}
+			exit(-1);
+		}
+	}
+	else
+	{
+		if(workername[0] == '{' || workername[0] == '"' || (workername[0] >= '0' && workername[0] <= '9') || strcmp(workername, "Yes") == 0 || strcmp(workername, "No") == 0)
+		{
+			//Constant expression
+			this_worker = add_constant(def, workername, 1.0, 1.0);
+		}
+		/*else if(workername[0] == '"')
+		{
+			//printf("\nString %s\n", workername);
+			workername[strlen(workername)-1] = '\0';
+			this_worker = add_constant(def, workername+1, 1.0, 1.0);
+		}
+		else if(workername[0] >= '0' && workername[0] <= '9')
+		{
+			//printf("\nNumber %s\n", workername);
+			this_worker = add_constant(def, workername, 1.0, 1.0);
+		}
+		else if(strcmp(workername, "Yes") == 0 || strcmp(workername, "No") == 0)
+		{
+			this_worker = add_constant(def, workername, 1.0, 1.0);
+		}*/
+		else
+		{
+			for(i = 0; workername[i] != 0; ++i)
+				if(workername[i] == '(')
+				{
+					input_num = atol(workername + i+1);
+					break;
+				}
+			if(input_num >= 0)
+			{
+				//printf("\nInput %d %s\n", input_num, workername);
+				this_worker = add_input(def, workername, 1.0, 1.0);
+			}
+			else
+			{
+				room = TRUE;
+				//printf("\nRoom %s\n", workername);
+				for(i = 0; i < strlen(workername)-1; ++i)
+				{
+					if(workername[i] == ':' && workername[i+1] == ':')
+					{
+						room = FALSE;
+						break;
+					}
+				}
+				if(room)
+					this_worker = create_find_room(def, workername, 1.0, 1.0);
+				else
+					this_worker = add_global_get(def, workername, 1.0, 1.0);
+				
+			}
+		}
+	}
+	for(i = 0; i < num_inputs; ++i)
+		if(inputs[i])
+		{
+			if(!strcmp(inputs[i], "~")) 
+			{
+				//printf("Input %d = ~ (parent block)\n", i);
+				if(!block_depth)
+				{
+					printf("Error: Reference to parent block (~) for input %d of worker %s, but block depth is 0", i, workername);
+					exit(-2);
+				}
+				add_wire(def, block_workers[block_depth-1], block_output[block_depth-1], this_worker, i);
+				block_attach = TRUE;
+			}
+			else
+			{
+				DEBUGPRINTF("Processing input %d (%s)\n", i, inputs[i]);
+				if(block_depth)
+					current = parse_body(def, inputs[i], strlen(inputs[i]), block_depth, block_output, block_workers);
+				else
+					current = parse_body(def, inputs[i], strlen(inputs[i]), 0, NULL, NULL);
+				add_wire(def, current, 0, this_worker, i);
+			}
+		}
+		else
+		{
+			//printf("Input %d = last_worker(%d)\n", i, last_worker);
+			add_wire(def, last_worker, 0, this_worker, i);
+		}
+	for(i = 0; i < num_outputs; ++i)
+	{
+		global_flag = FALSE;
+		//printf("Output %d = %s\n", i, outvars[i]);
+		for(j = 0; outvars[i][j] != '\0'; ++j)
+			if(outvars[i][j] == '(')
+				break;
+			else if(outvars[i][j] == ':' && outvars[i][j+1] == ':')
+				break;				
+		if(outvars[i][j] == '\0')
+			current = create_find_room(def, outvars[i], 2.0, 2.0);
+		else if(outvars[i][j] == ':')
+			current = add_global_set(def, outvars[i], 2.0, 2.0);
+		else
+			current = create_find_output(def, outvars[i], 2.0, 2.0);
+		add_wire(def, this_worker, i, current, 0);
+	}
+	
+	//printf("Current blockdepth: %d\n", block_depth);
+	if(block_depth > 0)
+	{
+		//printf("Block Worker: %d\nBlock Output: %d\n", block_workers[block_depth-1], block_output[block_depth-1]);
+		if(worker_expr && num_inputs < expected_in)
+		{
+			if(block_attach)
+				printf("Warning: Worker %s is attached to block both explicityly and implicity (i.e. at least one input was stated as ~, but there are still unsatisfied inputs)\n", workername);
+			if(expected_in - num_inputs > 1)
+				printf("Warning: More than one input of worker %s implicitly tied to block (%d inputs implicitly tied)", workername, expected_in - num_inputs);
+			for(i = num_inputs; i < expected_in; ++i)
+				add_wire(def, block_workers[block_depth-1], block_output[block_depth-1], this_worker, i);
+				
+		}
+		else if(!block_attach && !room)
+		{
+			add_wire(def, block_workers[block_depth-1], block_output[block_depth-1], this_worker, -1);
+			//def->implement_func->workerlist[this_worker].null_input = TRUE;
+		}
+	} 
+	else  if(worker_expr && num_inputs < expected_in)
+	{
+		ERRORPRINTF("Error: Worker %s expects %d input(s), but was only given %d input(s)\n", workername, expected_in, num_inputs);
+		exit(-1);
+	}
+	//printf("Returning %d\n\n", this_worker);
+	return this_worker;
+}
+typedef enum {NULL_STATE, OUT_STATE, BETWEEN_OUT, BEFORE_WORK, PRE_IN_STATE, BETWEEN_PRE_IN, WORK_STATE, IN_STATE, BETWEEN_IN, AFTER_IN, BLOCK_FIND, LINE_COMMENT_STATE} parse_state;
+char state_txt[12][20] = {"Null","Out","Between Out","Before Work","Pre Input","Between Pre-Input","Worker","Input","Between Input","After Input","Block Find"};
+int parse_body(worker_def * def, char * code, int len, int prev_block_depth, int * prev_block_output, int * prev_block_workers)
+{
+	char * outputs[32];
+	char * inputs[32];
+	char * worker;
+	short saw_line=0;
+	int num_inputs=0, num_outputs=0;
+	int left_bracket=0;
+	int left_curly=0;
+	int block_depth = 0;
+	int block_workers[32];
+	int block_output[32];
+	int last_worker = 0;
+	BOOL worker_expr = FALSE;
+	BOOL in_string = FALSE;
+	BOOL literal = FALSE;
+	BOOL do_curly = FALSE;
+	BOOL saw_newline = FALSE;
+	int i,j;
+	int start;
+	int line_comment_start;
+	parse_state state = NULL_STATE;
+	parse_state old_state;
+	DEBUGPRINTF("code: %X\n", code);
+	//printf("prev_block_depth: %d\n", prev_block_depth);
+	for(i=0; i < len; ++i)
+	{
+		//printf("i: %d, code[i]: '%c', state: %s(%d)\n", i, code[i], state_txt[state],state);
+		DEBUGPRINTF("i: %d, code[i]: '%c', state: %s(%d), left_bracket: %d, num_inputs: %d\n", i, code[i], state_txt[state],state, left_bracket, num_inputs);
+		if(!in_string)
+		{
+			if(state != LINE_COMMENT_STATE)
+			{
+				if(code[i] == '/' && code[i+1] == '/')
+				{
+					old_state = state;
+					state = LINE_COMMENT_STATE;
+					line_comment_start = i;
+					i += 2;
+				}
+				else if(code[i] == '[')
+					++left_bracket;
+				else if(code[i] == ']')
+					--left_bracket;
+				else if(code[i] == '{')
+					do_curly = TRUE;
+				else if(code[i] == '}')
+					--left_curly;
+				else if(code[i] == '"')
+				{
+					in_string = TRUE;
+					//continue;
+				}
+			}
+			if(left_curly == 0)
+			{
+				switch(state)
+				{
+				case NULL_STATE:
+					
+					if(code[i] == '[')
+					{
+						//puts("worker_expr = TRUE");
+						worker_expr = TRUE;
+						state = BETWEEN_PRE_IN;
+					}
+					else if(code[i] == ':' && code[i+1] == '|')
+					{
+						++i;
+						state = BLOCK_FIND;
+					}
+					else if(code[i] == '|' && code[i+1] == ':')
+					{
+						block_workers[block_depth] = last_worker;
+						block_output[block_depth++] = 0;
+						//puts("Found |: increasing block depth");
+						++i;
+					}
+					else if(!is_whitespace(code[i]))
+					{
+						start = i;
+						for(j = i; j < len-1; ++j)
+							if(code[j] == '<' && code[j+1] == '-')
+							{
+								state = OUT_STATE;
+								--i;
+								break;
+							}
+							else if(code[j] == '[' || code[j] == '\n' || (code[j] == '|' && code[j+1] == ':') || code[j] == '#' || code[j] == '"')
+							{
+								state = WORK_STATE;
+								break;
+							}
+						if(state == NULL_STATE)
+							state = WORK_STATE;
+					}
+					break;
+				case OUT_STATE:
+					if(code[i] == ',' || (code[i] == '<' && code[i+1] == '-'))
+					{
+						outputs[num_outputs++] = code + start;
+						for(j = i-1; j > start; --j)
+							if(!is_whitespace(code[j]))
+								break;
+						if(code[i] == ',')
+							state = BETWEEN_OUT;
+						else
+						{
+							state = BEFORE_WORK;
+							++i;
+						}
+						code[j+1] = '\0';
+					}
+					break;
+				case BETWEEN_OUT:
+					if(!is_whitespace(code[i]))
+					{
+						start = i;
+						state = OUT_STATE;
+						--i;
+					}
+					break;
+				case BEFORE_WORK:
+					if(code[i] == '[')
+					{
+						//puts("worker_expr = TRUE");
+						worker_expr = TRUE;
+						state = BETWEEN_PRE_IN;
+					}
+					else if(code[i] == ':' && code[i+1] == '|')
+					{
+						start = i;
+						while(i < len && (code[i] != '\n' || saw_line < 5))
+						{
+							if(code[i] == '\n')
+								++saw_line;
+							++i;
+						}
+						code[i] = '\0';
+						ERRORPRINTF("Error: Expected a worker name, but found a closing bracket (:|) instead at:\n%s", code + start);
+						exit(-1);
+					}
+					else if(!is_whitespace(code[i]))
+					{
+						start = i;
+						state = WORK_STATE;
+					}
+					break;
+				case PRE_IN_STATE:
+					if((code[i] == ',' && left_bracket == 1) || (code[i] == ']' && left_bracket == 0) )
+					{
+						inputs[num_inputs++] = code + start;
+						for(j = i-1; j > start; --j)
+							if(!is_whitespace(code[j]))
+								break;
+						if(code[i] == ',')
+							state = BETWEEN_PRE_IN;
+						else
+							state = BEFORE_WORK;
+						code[j+1] = '\0';
+					}
+					break;
+				case BETWEEN_PRE_IN:
+					if(code[i] == ']')
+					{
+						state = BEFORE_WORK;
+					}
+					else if(!is_whitespace(code[i]))
+					{
+						start = i;
+						state = PRE_IN_STATE;
+					}
+					break;
+				case WORK_STATE:
+					if(code[i] == '[' || code[i] == '#' || (code[i] == '|' && code[i+1] == ':') || (code[i] == ':' && code[i+1] == '|') || code[i] == '\n')
+					{
+						for(j = i-1; j > start; --j)
+							if(!is_whitespace(code[j]))
+								break;
+						
+						worker = code+start;
+			
+						if(code[i] == '[')
+						{
+							code[j+1] = '\0';
+						//	puts("Worker to Between Input");
+						//	puts("worker_expr = TRUE;");
+							worker_expr = TRUE;
+							state = BETWEEN_IN;
+						}
+						else if(code[i] == '#' || code[i] == '\n')
+						{
+							code[j+1] = '\0';
+						//	puts("Worker to Null State(#)");
+							//printf("worker_expr: %d\n", worker_expr);
+							if(block_depth)
+								last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker);
+							else
+								last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker);
+							num_inputs = 0;
+							num_outputs = 0;
+							worker_expr = FALSE;
+							state = NULL_STATE;
+						}
+						else if(code[i] == ':')
+						{
+							code[j+1] = '\0';
+							if(block_depth)
+								last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker);
+							else
+								last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker);
+							num_inputs = 0;
+							num_outputs = 0;
+							worker_expr = FALSE;
+							state = BLOCK_FIND;
+							++i;
+						}
+						else
+						{
+							//puts("Worker to Null State(else)");
+							code[j+1] = '\0';
+							if(block_depth)
+								last_worker = block_workers[block_depth] = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker);
+							else
+								last_worker = block_workers[block_depth] = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker);
+							block_output[block_depth++] = 0;
+							//puts("Found |:, increasinb block depth");
+							num_inputs = 0;
+							num_outputs = 0;
+							worker_expr = FALSE;
+							state = NULL_STATE;
+							++i;
+						}
+						
+					}
+					break;
+				case BETWEEN_IN:
+					if(code[i] == ']')
+					{
+						state = AFTER_IN;
+					}
+					else if(!is_whitespace(code[i]))
+					{
+						start = i;
+						state = IN_STATE;
+					}
+					break;
+				case IN_STATE:
+					if((code[i] == ',' && left_bracket == 1) || (code[i] == ']' && left_bracket == 0) )
+					{
+						inputs[num_inputs++] = code + start;
+						for(j = i-1; j > start; --j)
+							if(!is_whitespace(code[j]))
+								break;
+						
+						if(code[i] == ',')
+							state = BETWEEN_IN;
+						else
+							state = AFTER_IN;
+						code[j+1] = '\0';
+					}
+					break;
+				case AFTER_IN:
+					//puts("AFTER_IN test");
+					if(code[i] == '\n')
+						saw_newline = TRUE;
+					if(code[i] == '|' && code[i+1] == ':')
+					{
+						if(block_depth)
+							last_worker = block_workers[block_depth] = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker);
+						else
+							last_worker = block_workers[block_depth] = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker);
+						block_output[block_depth++] = 0;
+						//puts("Found |: increasing block depth");
+						state = NULL_STATE;
+						num_inputs = 0;
+						num_outputs = 0;
+						worker_expr = FALSE;
+						++i;
+					}
+					else if(code[i] == '#')
+					{
+						if(block_depth)
+							last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker);
+						else
+							last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker);
+						state = NULL_STATE;
+						num_inputs = 0;
+						num_outputs = 0;
+						worker_expr = FALSE;
+					}
+					else if(code[i] == '[')
+					{
+						if(saw_newline)
+						{
+							if(block_depth)
+								last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker);
+							else
+								last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker);
+							saw_newline = FALSE;
+							state = NULL_STATE;
+							num_inputs = 0;
+							num_outputs = 0;
+							worker_expr = FALSE;
+							--left_bracket;
+							--i;
+						}
+						else
+						{
+							puts("Error: Too many input blocks at");
+							code[i+1] = '\0';
+							for(j = i-1; j > 0; --j)
+							if(code[j] == '\n')
+							{
+								++j;
+								break;
+							}
+							puts(code + j);
+							exit(-1);
+						}
+					}
+					else if(!is_whitespace(code[i]))
+					{
+						if(block_depth)
+							last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker);
+						else
+							last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker);
+						if(saw_newline)
+						{
+							saw_newline = FALSE;
+							num_inputs = 0;
+						}
+						else
+						{
+							num_inputs = 1;
+							inputs[0] = NULL;
+						}
+						state = NULL_STATE;
+						
+						num_outputs = 0;
+						worker_expr = FALSE;
+						--i;
+					}
+					break;
+				case BLOCK_FIND:
+					if(code[i] == '|' && code[i+1] == ':')
+					{
+						//puts("Found |: increasing output number (not block depth)");
+						++block_output[block_depth-1];
+						++i;
+						state = NULL_STATE;
+					}
+					else if(!is_whitespace(code[i]))
+					{
+						//puts("Found :| without another |: following; decreasing block depth");
+						--block_depth;
+						if(code[i] == '[')
+							--left_bracket;
+						--i;
+						num_inputs = 0;
+						state = NULL_STATE;
+						
+					}
+					break;
+				case LINE_COMMENT_STATE:
+					if(code[i+1] == '\n')
+					{
+						for(;line_comment_start <= i; ++line_comment_start)
+							code[line_comment_start] = ' ';
+						state = old_state;
+					}
+					break;
+				}
+			}
+			if(do_curly)
+			{
+				++left_curly;
+				do_curly = FALSE;
+			}
+		}
+		else if(literal)
+			literal = FALSE;
+		else if(code[i] == '"')
+			in_string = FALSE;
+		else if(code[i] == '\\')
+			literal = TRUE;
+	}
+	//printf("State at end of code chunk: %s(%d)\n", state_txt[state], state);
+	if((state != BLOCK_FIND && block_depth != 0) || (state == BLOCK_FIND && block_depth > 1))
+	{
+		ERRORPRINTF("Syntax Error: Missing %d block close symbol(s) (:|)\n", block_depth);
+		exit(-1);
+	}
+	else
+	{
+		switch(state)
+		{
+			case WORK_STATE:
+				for(j = i-1; j > start; --j)
+					if(!is_whitespace(code[j]))
+						break;
+					
+				worker = code+start;
+				code[j+1] = '\0';
+			case AFTER_IN:
+				if(block_depth)
+					last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, block_depth, block_workers, block_output, last_worker);
+				else
+					last_worker = process_expression(def, num_outputs, outputs, num_inputs, inputs, worker, worker_expr, prev_block_depth, prev_block_workers, prev_block_output, last_worker);
+				break;
+			case BLOCK_FIND:
+			case NULL_STATE:
+				break;
+			default:
+				printf("Syntax Error: State is %s but there are no more characters left to process.\n", state_txt[state]);
+				puts(code + start);
+				exit(-1);
+		}
+	}
+	return last_worker;
+}
+typedef struct parse_worker
+{
+	char * worker_name;
+	int num_inputs;
+	int num_outputs;
+	worker_def * def;
+	char * block;
+	int block_len;
+	struct parse_worker * next;
+} parse_worker;
+
+void parse_company(char * name, char * code, int len, program * prog)
+{
+	char * type_name;
+	char * field_name;
+	int i;
+	int part_start;
+	int part_end;
+	int type;
+	company * comp;
+	BOOL saw_newline;
+	field_name = type_name = NULL;
+	comp = create_company(prog, name, 0, 0, TRUE);
+	i = 0;
+	while(i < len)
+	{
+		saw_newline = FALSE;
+		part_start = -1;
+		for(; i < len; ++i)
+		{
+			DEBUGPRINTF("i: %d, code[i]: %c ", i, code[i]);
+			if(part_start < 0)
+			{
+				if(!is_whitespace(code[i]))
+					part_end = part_start = i;
+			}
+			else if(code[i] == ':' && code[i-1] == ':')
+			{
+				type_name = code + part_start;
+				type_name[part_end - part_start-1] = '\0';
+				part_start = -1;
+				++i;
+				break;
+			}
+			else if(!is_whitespace(code[i]))
+			{
+				DEBUGPUTS("Not whitespace\n");
+				if(saw_newline)
+				{
+					code[part_end] = '\0';
+					add_comp_room(comp, code + part_start, -1, -1, ROOM_VIS_REF, ROOM_VIS_REF);
+					--i;
+					part_start = -1;
+					saw_newline = FALSE;
+				}
+				else
+					part_end = i+1;
+			}
+				
+			else if(code[i] == '\n')
+			{
+				DEBUGPUTS("saw newline\n");
+				saw_newline = TRUE;
+			}
+		}
+		if(i >= len && part_start >= 0 && part_end > part_start)
+		{
+			code[part_end] = '\0';
+			add_comp_room(comp, code + part_start, -1, -1, ROOM_VIS_REF, ROOM_VIS_REF);
+			part_start = -1;
+		}
+		for(; i < len; ++i)
+		{
+			DEBUGPRINTF("i: %d, code[i]: %c ", i, code[i]);
+			if(part_start < 0)
+			{
+				if(!is_whitespace(code[i]))
+					part_end = part_start = i;
+				DEBUGPRINTF("part_start: %d\n", part_start);
+			}
+			else if(!is_whitespace(code[i]))
+			{
+				DEBUGPRINTF("part_end: %d\n", part_end);
+				part_end = i+1;
+			}
+			else if(code[i] == '\n')
+			{
+				DEBUGPRINTF("saw newline, type name: %s\n", type_name);
+				if(!strcmp("Byte", type_name))
+					type = ROOM_BYTE;
+				else if(!strcmp("Word", type_name))
+					type = ROOM_SHORT;
+				else if(!strcmp("Long", type_name))
+					type = ROOM_LONG;
+				else
+					type = ROOM_VIS_REF;
+				code[part_end] = '\0';
+				add_comp_room(comp, code + part_start, -1, -1, type, type);
+				break;
+			}
+		}
+	}
+	if(part_start >= 0 && part_end > part_start)
+	{
+		if(!strcmp("Byte", type_name))
+			type = ROOM_BYTE;
+		else if(!strcmp("Word", type_name))
+			type = ROOM_SHORT;
+		else if(!strcmp("Long", type_name))
+			type = ROOM_LONG;
+		else
+			type = ROOM_VIS_REF;
+		code[part_end] = '\0';
+		add_comp_room(comp, code + part_start, -1, -1, type, type);
+	}
+}
+
+void import(char * filename, program * prog)
+{
+	int size;
+	char * code;
+	FILE * imp;
+	imp = fopen(filename, "rb");
+	if(imp)
+	{
+		fseek(imp, 0, SEEK_END);
+		size = ftell(imp);
+		fseek(imp, 0, SEEK_SET);
+		code = MALLOC(size, "code from imported file");
+		fread(code, 1, size, imp);
+		DEBUGPRINTF("Read %d bytes\n", size);
+		parse(code, size, prog);
+		DEBUGPUTS("Finished parsing import file\n");
+		VIS_FREE(code, "code buffer");
+		fclose(imp);
+	}
+	else
+	{
+		ERRORPRINTF("Warning: Could not open import file: %s\n", filename);
+	}
+}
+
+typedef enum {NULL_PARSE, WORKER_STATE, BLOCK_STATE, STRING_STATE, LITERAL_STATE, LIST_STATE, LIST_STRING, LIST_LITERAL, LINE_COMMENT} super_state;
+char super_state_txt[9][30] = {"Null", "Worker", "Block", "String", "String Literal", "List", "String in List", "String Literal in List", "Single Line Comment"};
+void parse(char * code, int len, program * prog)
+{
+	parse_worker *list=NULL, *current=NULL, *temp;
+	short saw_line = 0;
+	int i,j,k;
+	int block_count = 0;
+	int start;
+	int end;
+	int num_inputs;
+	int num_outputs;
+	int company_len, import_len;
+	char * worker_name;
+	int left_curly=0;
+	int block_done = -1;
+	int comp_start, comp_end;
+	char * company_name;
+	char * comp_block;
+	int comp_block_len;
+	int num_uses;
+	char * importfiles[32];
+	int num_imported = 0;
+	super_state old_state;
+	char ** uses_names = NULL;
+	BOOL lastwasspace = FALSE;
+	super_state state = NULL_PARSE;
+	company_len = strlen("Company");
+	import_len = strlen("Import");
+	for(i = 0; i < len; ++i)
+	{
+		DEBUGPRINTF("i: %d, code[i]: %c, state: %s(%d)\n", i, code[i], super_state_txt[state], state);
+		if(code[i] == '/' && code[i+1] == '/' && state != STRING_STATE && state != LIST_STRING)
+		{
+			old_state = state;
+			state = LINE_COMMENT;
+			i += 2;
+		}
+		switch(state)
+		{
+			case NULL_PARSE:
+				if(len - i >= import_len && !memcmp("Import", code + i, import_len))
+				{
+					start = end = -1;
+					for(j = i+import_len; j < len && code[j] != '\n'; ++j)
+					{
+						if(start < 0)
+						{
+							if(!is_whitespace(code[j]))
+								start = j; 
+						}
+						else
+						{
+							if(!is_whitespace(code[j]))
+								end = j;
+						}
+					}
+					if(end < 0)
+					{
+						puts("Error: Import statement with no file name");
+						exit(-1);
+					}
+					++end;
+					code[end] = '\0';
+					i = end;
+					if(num_imported < 32)
+						importfiles[num_imported++] = code+start;
+					else
+					{
+						puts("Error: You cannot have more than 32 import statements in the same file");
+						exit(-1);
+					}
+				}
+				else if(code[i] == ':' && code[i+1] == '|')
+				{
+					start = i;
+					while((code[i] != '\n' || saw_line < 5) && i < len)
+					{
+						if(code[i] == '\n')
+							++saw_line;
+						++i;
+					}
+					code[i] = '\0';
+					ERRORPRINTF("Error: Unexpected closing bracket (:|) found:\n%s", code + start);
+					exit(-1);
+				}
+				else if(!is_whitespace(code[i]))
+				{
+					start = i;
+					state = WORKER_STATE;
+				}
+				break;
+			case WORKER_STATE:
+				if(is_whitespace(code[i]))
+					lastwasspace = TRUE;
+				else if(code[i] == '|' && code[i+1] == ':')
+				{
+					if(!strncmp(code+start, "Company",company_len) && is_whitespace(code[start+company_len]))
+					{
+						comp_start = -1;
+						comp_end = 0;
+						for(j = start+company_len+1; j < len-1; ++j)
+						{
+							if(comp_start >= 0)
+							{
+								if(code[j] == '|' && code[j+1] == ':')
+									break;
+								else if(!is_whitespace(code[j]))
+									comp_end = j+1;
+							}
+							else
+							{
+								if(!is_whitespace(code[j]))
+									comp_start = j;
+							}
+						}
+						if(comp_start >= 0 && comp_end > comp_start)
+						{
+							company_name = code + comp_start;
+							code[comp_end] = '\0';
+							comp_start = -1;
+							for(j = comp_end+1; j < len-1; ++j)
+							{
+								if(comp_start < 0)
+								{
+									if(code[j] == '|' && code[j+1] == ':')
+										comp_start = j+2;
+								}
+								else
+								{
+									if(code[j] == ':' && code[j+1] == '|')
+									{
+										comp_end = j;
+										break;
+									}
+								}
+							}
+							if(comp_start > 0)
+							{
+								comp_block = code+comp_start;
+								comp_block_len = comp_end-comp_start;
+								DEBUGPRINTF("Company block start: %d, end: %d, length: %d\n", comp_start, comp_end, comp_block_len);
+								code[comp_end] = '\0';
+								i = comp_end+1;
+								parse_company(company_name, comp_block, comp_block_len, prog);
+							}
+							else
+							{
+								printf("Error parsing Company, comp_start is %d\n", comp_start);
+							}
+							
+						}
+						else
+						{
+							puts("Error parsing Company\n");
+						}
+						state = NULL_STATE;
+						
+					}
+					else
+					{
+						for(j = i-1; j > start; --j)
+							if(code[j] != ' ' && code[j] != '\t' && code[j] != '\n' && code[j] != '\r')
+								break;
+						for(k = start; k <= j; ++k)
+							if(code[k] == '(')
+							{
+								code[k] = '\0';
+								num_inputs = atol(code + k + 1);
+							}
+							else if(code[k] == ',')
+								num_outputs = atol(code + k + 1);
+						worker_name = code + start;
+						//printf("Found worker def: %s with %d outputs and %d inputs\n", worker_name, num_outputs, num_inputs);
+						start = i+2;
+						++i;
+						num_uses = 0;
+						state = BLOCK_STATE;
+					}
+				}
+				else if(lastwasspace && !strncmp(code+i, "uses", 4))
+				{
+					for(j = i-1; j > start; --j)
+						if(code[j] != ' ' && code[j] != '\t' && code[j] != '\n' && code[j] != '\r')
+							break;
+					for(k = start; k <= j; ++k)
+						if(code[k] == '(')
+						{
+							code[k] = '\0';
+							num_inputs = atol(code + k + 1);
+						}
+						else if(code[k] == ',')
+							num_outputs = atol(code + k + 1);
+					worker_name = code + start;
+					num_uses = 1;
+					for(j = i + strlen("uses"); code[j] != '|' && j < len; ++j)
+						if(code[j] == ',')
+							++num_uses;
+					DEBUGPRINTF("num_uses: %d\n", num_uses);
+					i += strlen("uses");
+					uses_names = MALLOC(sizeof(char *) * num_uses, "uses stores names");
+					end = -1;
+					start = i;
+					j = 0;
+					while(code[i] != '|' && i < len)
+					{
+						if(code[i] == ',')
+						{
+							uses_names[j] = MALLOC(sizeof(char) * (end-start+1), "global store name for uses stores");
+							memcpy(uses_names[j], code+start, end-start);
+							uses_names[j][end-start] = '\0';
+							DEBUGPRINTF("uses: %s\n", uses_names[j]);
+							end = -1;
+							++j;
+						}
+						else if(code[i] != ' ' && code[i] != '\t' && code[i] != '\r' && code[i] != '\n')
+							end = i+1;
+						else if(end < 0)
+							start = i+1;
+						++i;
+					}
+					if(end >= 0)
+					{
+						uses_names[j] = MALLOC(sizeof(char) * (end-start+1), "global store name for uses stores");
+						memcpy(uses_names[j], code+start, end-start);
+						uses_names[j][end-start] = '\0';
+						DEBUGPRINTF("uses: %s\n", uses_names[j]);
+						end = -1;
+						++j;
+					}
+					start = i+2;
+					++i;
+					state = BLOCK_STATE;
+					
+				}
+				break;
+			case BLOCK_STATE:
+				//printf("Block count: %d\n", block_count);
+				if((i-block_done)>1 && code[i] == ':' && code[i-1] == '|')
+				{
+					++block_count;
+				}
+				else if(code[i] == '"') {
+					state = STRING_STATE;
+				}
+				else if(code[i] == '{') {
+					state = LIST_STATE;
+				}
+				else if(code[i] == '|' && code[i-1] == ':')
+				{
+					if(block_count == 0)
+					{
+						if(current)
+						{
+							current->next = MALLOC(sizeof(parse_worker),"parse worker");
+							current = current->next;
+						}
+						else
+						{
+							list = current = MALLOC(sizeof(parse_worker),"parse worker");
+						}
+						current->num_inputs = num_inputs;
+						current->num_outputs = num_outputs;
+						current->worker_name = worker_name;
+						current->block = code + start;
+						current->block_len = i-start-1;
+						current->next = NULL;
+						current->def = create_worker(prog, current->worker_name, current->num_inputs, current->num_outputs, USER_FLAG | WORKER_TYPE);
+						current->def->uses_stores = uses_names;
+						current->def->num_stores = num_uses;
+						uses_names = NULL;
+						num_uses = 0;
+						state = NULL_PARSE;
+						block_done = -1;
+					}
+					else
+					{
+						block_done = i;
+						--block_count;
+					}
+				}
+				break;
+			case STRING_STATE:
+				if(code[i] == '\\')
+					state = LITERAL_STATE;
+				else if(code[i] == '"')
+					state = BLOCK_STATE;
+				break;
+			case LITERAL_STATE:
+				state = STRING_STATE;
+				break;
+			case LIST_STATE:
+				if(code[i] == '{')
+					++left_curly;
+				else if(code[i] == '}')
+					if(left_curly)
+						--left_curly;
+					else
+						state = BLOCK_STATE;
+				else if(code[i] == '"')
+					state = LIST_STRING;
+				break;
+			case LIST_STRING:
+				if(code[i] == '\\')
+					state = LIST_LITERAL;
+				else if(code[i] == '"')
+					state = LIST_STATE;
+				break;
+			case LIST_LITERAL:
+				state = LIST_STRING;
+				break;
+			case LINE_COMMENT:
+				if(code[i+1] == '\n')
+					state = old_state;
+				break;
+		}
+	}
+	if(state != NULL_PARSE)
+	{
+		printf("Error: Current parse state is %s(%d) in first pass but there are no more characters to parse.\n", super_state_txt[state], state);
+		if(state == BLOCK_STATE)
+		{
+			printf("Worker %s appears to be missing a closing bracket (:|)\n", worker_name);
+		}
+		exit(-3);
+	}
+	for(i = 0; i < num_imported; ++i)
+	{
+		import(importfiles[i], prog);
+	}
+	current = list;
+	while(current)
+	{
+		DEBUGPRINTF("Processing worker %s with %d inputs and %d outputs\n\n", current->worker_name, current->num_inputs, current->num_outputs);
+		parse_body(current->def, current->block, current->block_len, 0, NULL, NULL);
+		temp = current;
+		current = current->next;
+		free(temp);
+	}
+}
+
+