global store_bottom = 0;
global store_eop = 0;
global store_top = 0;

constant VN_NEXT = 0;
constant VN_TYPE = 1;
constant VN_VALUE = 2;
constant VN__SIZE = (3*2);

global store_firstvar = 0;

! Initialise the program store.

[ store_init bottom top;
	store_bottom = bottom;
	store_top = top;
	store_bottom->0 = 0;
	store_eop = store_bottom;
	string_init();
];

! --- Heap management -------------------------------------------------------

! Heap reinitialisation; all heap pointers are invalidated.

[ store_heapclean;
	store_firstvar = 0;
];

! Create a new variable.

[ store_newvar varname type value  node;
	node = mem_alloc(VN__SIZE + strlen(varname) + 1);
	node-->VN_NEXT = store_firstvar;
	node-->VN_TYPE = type;
	node-->VN_VALUE = value;
	strcpy(node+VN__SIZE, varname);
	store_firstvar = node;
];

! Look for an old variable.

[ store_searchvar varname  node;
	node = store_firstvar;
	while (node)
	{
		if (strcmp(varname, node+VN__SIZE) == 0)
			return node;
		node = node-->VN_NEXT;
	}
	return 0;
];

! Assign a value to a variable.

[ store_assign varname type value  node;
	node = store_searchvar(varname);
	if (node)
	{
		node-->VN_TYPE = type;
		node-->VN_VALUE = value;
		return;
	}
	store_newvar(varname, type, value);
];

! Get the contents of a variable.

[ store_lookup varname  node val;
	node = store_searchvar(varname);
	if (node)
	{
		val = mem_alloc(4);
		val-->0 = node-->VN_TYPE;
		val-->1 = node-->VN_VALUE;
		return val;
	}
	return 0;
];

! List all variables.

[ store_listvars  var count;
	var = store_firstvar;
	count = 0;
	print "Variables:^";
	while (var)
	{
		print "  ", (astring) var+VN__SIZE;
		switch (var-->VN_TYPE)
		{
			TYPE_INT:
				print " integer ", var-->VN_VALUE;
				break;

			TYPE_STRING:
				print " string ~";
				string_print(var-->VN_VALUE);
				print "~";
				break;

			default:
				print " unknown type";
		}
		print "^";
				
		var = var-->VN_NEXT;
		count++;
	}
	print "Total: ", count, "^";
];

! --- Program storage -------------------------------------------------------

! List the current program.

[ store_listprogram  line linelen;
	line = store_bottom;
	while (linelen = line->0)
	{
		print " ", (line+1)-->0;
		detokenise_stream(line+3);
		line = line + linelen;
	}
];

[ store_listprogramhex  line linelen;
	line = store_bottom;
	while (linelen = line->0)
	{
		print " ", (line+1)-->0;
		detokenise_stream(line+3);
		print "-> ";
		hexdump(line, linelen);
		line = line + linelen;
	}
];

! Add a line to the program.

[ store_addline linenum cmd linelen  line i;
	line = store_bottom;
	while (line->0)
	{
		if ((line+1)-->0 >= linenum)
			break;
		line = line + line->0;
	}

	! Do we need to append this line to the end of the program?

	if (line->0 == 0)
	{
		! Yes.

		line = store_eop;
		store_eop->(linelen+3) = 0;
		store_eop = store_eop + linelen + 3;
	}
	else
	{
		! Do we need to remove an existing line first?

		if ((line+1)-->0 == linenum)
		{
			i = line->0;
			memcpy(line, line+i, store_eop-line-i);
			store_eop = store_eop - i;
			store_eop->0 = 0;
		}

		! If there's no actual data in the new line, give up.

		if (linelen == 1)
			return 0;

		! Open up space for the new line.

		memcpy(line+linelen+3, line, store_eop-line);
		store_eop = store_eop + linelen + 3;
		store_eop->0 = 0;
	}

	! Copy the line in.

	line->0 = linelen+3;
	(line+1)-->0 = linenum;
	memcpy(line+3, cmd, linelen);

	return 0;
];

! Find a line, by number.

[ store_findline lineno  line;
	line = store_bottom;
	while (line->0 && ((line+1)-->0 ~= lineno))
		line = line + line->0;
	if (line->0 == 0)
		return 0;
	return line;
];

