FINALLY, marks and references work smoothly without hacks. if and while work properly.

Sun, 12 Aug 2012 01:52:42 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sun, 12 Aug 2012 01:52:42 +0300
changeset 42
5cd91fd1526c
parent 41
47e686c96d8f
child 43
1b35c9985989

FINALLY, marks and references work smoothly without hacks. if and while work properly.

common.h file | annotate | diff | comparison | revisions
databuffer.h file | annotate | diff | comparison | revisions
main.cxx file | annotate | diff | comparison | revisions
objwriter.cxx file | annotate | diff | comparison | revisions
objwriter.h file | annotate | diff | comparison | revisions
parser.cxx file | annotate | diff | comparison | revisions
--- a/common.h	Sat Aug 11 19:35:47 2012 +0300
+++ b/common.h	Sun Aug 12 01:52:42 2012 +0300
@@ -43,7 +43,8 @@
 
 #include <stdio.h>
 #include <stdarg.h>
-#include <typeinfo>
+#include <typeinfo> 
+#include <stdint.h>
 #include "bots.h"
 #include "str.h"
 
@@ -117,15 +118,17 @@
 }
 
 // Byte datatype
-typedef unsigned long int word;
-typedef unsigned char byte;
+// typedef unsigned long int word;
+typedef int32_t word;
+typedef uint8_t byte;
 
 // Keywords
-#define NUM_KEYWORDS 20
 #ifndef __MAIN_CXX__
 extern const char** g_Keywords;
 #endif
+
 bool IsKeyword (str s);
+unsigned int NumKeywords ();
 
 // Script mark and reference
 struct ScriptMark {
--- a/databuffer.h	Sat Aug 11 19:35:47 2012 +0300
+++ b/databuffer.h	Sun Aug 12 01:52:42 2012 +0300
@@ -97,37 +97,36 @@
 	
 	// ====================================================================
 	// Write stuff to the buffer
-	template<class T> void Write(T stuff) {
-		if (sizeof (char) != 1) {
-			error ("DataBuffer: sizeof(char) must be 1!\n");
-		}
-		
-		// Out of space, must resize
-		if (writesize + sizeof(T) >= allocsize) {
-			// First, store the old buffer temporarily
+	template<class T> void Write (T stuff) {
+		if (writesize + sizeof (T) >= allocsize) {
+			// We don't have enough space in the buffer to write
+			// the stuff - thus resize. First, store the old
+			// buffer temporarily:
 			char* copy = new char[allocsize];
 			memcpy (copy, buffer, allocsize);
 			
-			// Remake the buffer with the new size.
-			// Have a bit of leeway so we don't have to
-			// resize immediately again.
+			// Remake the buffer with the new size. Have enough space
+			// for the stuff we're going to write, as well as a bit
+			// of leeway so we don't have to resize immediately again.
 			size_t newsize = allocsize + sizeof (T) + 128;
 			delete buffer;
 			buffer = new unsigned char[newsize];
 			allocsize = newsize;
 			
-			// Now, copy the new stuff over.
+			// Now, copy the stuff back.
 			memcpy (buffer, copy, allocsize);
-			
-			// Nuke the copy now as it's no longer needed
 			delete copy;
 		}
 		
-		// Write the new stuff one byte at a time
+		// Buffer is now guaranteed to have enough space.
+		// Write the stuff one byte at a time.
+		union_t<T> uni;
+		uni.val = stuff;
 		for (unsigned int x = 0; x < sizeof (T); x++) {
-			if (writesize >= allocsize)
+			if (writesize >= allocsize) // should NEVER happen because resizing is done above
 				error ("DataBuffer: written size exceeds allocated size!\n");
-			buffer[writesize] = GetByteIndex<T> (stuff, x);
+			
+			buffer[writesize] = uni.b[x];
 			writesize++;
 		}
 	}
@@ -169,7 +168,7 @@
 	}
 	
 	// ====================================================================
-	// Adds a mark to the buffer. A mark is a reference to a particular
+	// Adds a mark to the buffer. A mark is a "pointer" to a particular
 	// position in the bytecode. The actual permanent position cannot
 	// be predicted in any way or form, thus these things will be used
 	// to "mark" a position like that for future use.
@@ -188,10 +187,13 @@
 		m->type = type;
 		m->pos = writesize;
 		marks[u] = m;
-		printf ("add mark %u at %d\n", u, m->pos);
 		return u;
 	}
 	
+	// ====================================================================
+	// A ref is another "mark" that references a mark. When the bytecode
+	// is written to file, they are changed into their marks' current
+	// positions. Marks themselves are never written to files, only refs are
 	unsigned int AddMarkReference (unsigned int marknum) {
 		unsigned int u;
 		for (u = 0; u < MAX_MARKS; u++)
@@ -204,11 +206,15 @@
 		// NOTE: Do not check if the mark actually exists here since a
 		// reference may come in the code earlier than the actual mark
 		// and the new mark number can be predicted.
+		//	11/8/12: eh? The mark is always created first.
 		ScriptMarkReference* r = new ScriptMarkReference;
 		r->num = marknum;
 		r->pos = writesize;
 		refs[u] = r;
 		
+		// Write a dummy placeholder for the reference
+		Write<word> (1234);
+		
 		return u;
 	}
 	
@@ -231,18 +237,15 @@
 	}
 	
 	// Adjusts a mark to the current position
-	void MoveMark (unsigned int mark) {
+	void MoveMark (unsigned int mark, int offset = -1) {
 		if (!marks[mark])
 			return;
-		printf ("move mark %u from %d to %d\n", mark, marks[mark]->pos, writesize);
 		marks[mark]->pos = writesize;
 	}
 	
-	// Adjusts a mark to the current position
 	void OffsetMark (unsigned int mark, size_t offset) {
 		if (!marks[mark])
 			return;
-		printf ("move mark %u from %d to %d\n", mark, marks[mark]->pos, marks[mark]->pos+offset);
 		marks[mark]->pos += offset;
 	}
 	
--- a/main.cxx	Sat Aug 11 19:35:47 2012 +0300
+++ b/main.cxx	Sun Aug 12 01:52:42 2012 +0300
@@ -56,7 +56,7 @@
 #include "bots.h"
 #include "botcommands.h"
 
-const char* g_Keywords[NUM_KEYWORDS] = {
+const char* g_Keywords[] = {
 	"state",
 	"event",
 	"mainloop",
@@ -65,6 +65,7 @@
 	"var",
 	"goto",
 	"if",
+	"while",
 	
 	// These ones aren't implemented yet but I plan to do so, thus they are
 	// reserved. Also serves as a to-do list of sorts for me. >:F
@@ -79,7 +80,6 @@
 	"func", // Would function support need external support from zandronum?
 	"return",
 	"switch",
-	"while"
 };
 
 int main (int argc, char** argv) {
@@ -116,7 +116,7 @@
 	// A word should always be exactly 4 bytes. The above list command
 	// doesn't need it, but the rest of the program does.
 	if (sizeof (word) != 4)
-		error ("%s expects a word (unsigned long int) to be 4 bytes in size, is %d\n",
+		error ("%s expects a word (uint32_t) to be 4 bytes in size, is %d\n",
 			APPNAME, sizeof (word));
 	
 	str outfile;
@@ -218,8 +218,12 @@
 // ============================================================================
 // Is the given argument a reserved keyword?
 bool IsKeyword (str s) {
-	for (unsigned int u = 0; u < NUM_KEYWORDS; u++)
+	for (unsigned int u = 0; u < NumKeywords (); u++)
 		if (!s.icompare (g_Keywords[u]))
 			return true;
 	return false;
+}
+
+unsigned int NumKeywords () {
+	return sizeof (g_Keywords) / sizeof (const char*);
 }
\ No newline at end of file
--- a/objwriter.cxx	Sat Aug 11 19:35:47 2012 +0300
+++ b/objwriter.cxx	Sun Aug 12 01:52:42 2012 +0300
@@ -120,35 +120,22 @@
 	if (sizeof (unsigned char) != 1)
 		error ("size of unsigned char isn't 1, but %d!\n", sizeof (unsigned char));
 	
-	unsigned int refpos = 0;
-	for (unsigned int x = 0; x < MainBuffer->writesize; x++) {
-		// Check if this position is a reference
-		for (unsigned int r = 0; r < MAX_MARKS; r++) {
-			if (MainBuffer->refs[r] && MainBuffer->refs[r]->pos == x) {
-				word ref = static_cast<word> (MainBuffer->marks[MainBuffer->refs[r]->num]->pos);
-				printf ("insert reference to mark %d (%ld) refpos = %d\n", MainBuffer->refs[r]->num, ref, refpos);
-				WriteDataToFile<word> (ref);
-				
-				// This reference is now used up - no need to keep it anymore.
-				delete MainBuffer->refs[r];
-				MainBuffer->refs[r] = NULL;
-				
-				// All marks still ahead need their positions bumped up as the bytecode
-				// will gain 4 more bytes with the written reference. Other references
-				// do not need their positions bumped because they check against mainbuffer
-				// position (x), not written ones.
-				for (unsigned int s = 0; s < MAX_MARKS; s++)
-					if (MainBuffer->marks[s] && MainBuffer->marks[s]->pos > refpos) {
-						printf ("mark %u bumped\n", s);
-						MainBuffer->marks[s]->pos += sizeof (word);
-					}
-				refpos += sizeof (word);
-			}
+	// First, resolve references
+	for (unsigned int u = 0; u < MAX_MARKS; u++) {
+		ScriptMarkReference* ref = MainBuffer->refs[u];
+		if (!ref)
+			continue;
+		
+		for (unsigned int v = 0; v < sizeof (word); v++) {
+			union_t<word> uni;
+			uni.val = static_cast<word> (MainBuffer->marks[ref->num]->pos);
+			memset (MainBuffer->buffer + ref->pos + v, uni.b[v], 1);
 		}
-		
+	}
+	
+	// Then, dump the main buffer to the file
+	for (unsigned int x = 0; x < MainBuffer->writesize; x++)
 		WriteDataToFile<unsigned char> (*(MainBuffer->buffer+x));
-		refpos++;
-	}
 	
 	printf ("-- %u byte%s written to %s\n", numWrittenBytes, PLURAL (numWrittenBytes), filepath.chars());
 	fclose (fp);
--- a/objwriter.h	Sat Aug 11 19:35:47 2012 +0300
+++ b/objwriter.h	Sun Aug 12 01:52:42 2012 +0300
@@ -86,14 +86,17 @@
 		return;
 	}
 	
-	// Cannot use default arguments in function templates..
-	void Write (word stuff) {Write<word> (stuff);}
+	// Default to word
+	void Write (word stuff) {
+		Write<word> (stuff);
+	}
 	
 	template <class T> void WriteDataToFile (T stuff) {
 		// One byte at a time
 		for (unsigned int x = 0; x < sizeof (T); x++) {
-			unsigned char c = GetByteIndex<T> (stuff, x);
-			fwrite (&c, 1, 1, fp);
+			union_t<T> uni;
+			uni.val = stuff;
+			fwrite (&uni.b[x], 1, 1, fp);
 			numWrittenBytes++;
 		}
 	}
--- a/parser.cxx	Sat Aug 11 19:35:47 2012 +0300
+++ b/parser.cxx	Sun Aug 12 01:52:42 2012 +0300
@@ -238,7 +238,6 @@
 		
 		// While
 		if (!token.compare ("while")) {
-			printf ("begin while loop\n");
 			MUST_NOT_TOPLEVEL
 			PushBlockStack ();
 			
@@ -279,22 +278,16 @@
 				BlockInformation* info = &blockstack[g_BlockStackCursor];
 				switch (info->type) {
 				case BLOCKTYPE_IF:
-					printf ("end if\n");
 					// Adjust the closing mark.
 					w->MoveMark (info->mark1);
 					break;
 				case BLOCKTYPE_WHILE:
-					printf ("end while loop\n");
-					
 					// Write down the instruction to go back to the start of the loop
 					w->Write (DH_GOTO);
 					w->AddReference (info->mark1);
 					
 					// Move the closing mark here since we're at the end of the while loop
 					w->MoveMark (info->mark2);
-					
-					// Offset it by 4 since the parser doesn't like having marks directly afte refs
-					w->OffsetMark (info->mark2, sizeof (word)*2);
 				}
 				
 				// Descend down the stack
@@ -624,9 +617,9 @@
 }
 
 void ScriptReader::PushBlockStack () {
+	g_BlockStackCursor++;
 	BlockInformation* info = &blockstack[g_BlockStackCursor];
 	info->type = 0;
 	info->mark1 = 0;
 	info->mark2 = 0;
-	g_BlockStackCursor++;
 }
\ No newline at end of file

mercurial