Added for-loop support

Sun, 12 Aug 2012 03:23:33 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Sun, 12 Aug 2012 03:23:33 +0300
changeset 43
1b35c9985989
parent 42
5cd91fd1526c
child 44
6bbaebc472b5

Added for-loop support

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
scriptreader.h file | annotate | diff | comparison | revisions
--- a/databuffer.h	Sun Aug 12 01:52:42 2012 +0300
+++ b/databuffer.h	Sun Aug 12 03:23:33 2012 +0300
@@ -254,6 +254,22 @@
 		for (unsigned int x = 0; x < writesize; x++)
 			printf ("%d. [%d]\n", x, *(buffer+x));
 	}
+	
+	// Count the amount of marks
+	unsigned int CountMarks () {
+		unsigned int count = 0;
+		for (unsigned int u = 0; u < MAX_MARKS; u++)
+			count += !!marks[u];
+		return count;
+	}
+	
+	// Count the amount of refs
+	unsigned int CountReferences () {
+		unsigned int count = 0;
+		for (unsigned int u = 0; u < MAX_MARKS; u++)
+			count += !!refs[u];
+		return count;
+	}
 };
 
 #endif // __DATABUFFER_H__
\ No newline at end of file
--- a/main.cxx	Sun Aug 12 01:52:42 2012 +0300
+++ b/main.cxx	Sun Aug 12 03:23:33 2012 +0300
@@ -57,14 +57,15 @@
 #include "botcommands.h"
 
 const char* g_Keywords[] = {
-	"state",
 	"event",
+	"for",
+	"goto",
+	"if",
 	"mainloop",
 	"onenter",
 	"onexit",
-	"var",
-	"goto",
-	"if",
+	"state",
+	"var"
 	"while",
 	
 	// These ones aren't implemented yet but I plan to do so, thus they are
@@ -76,7 +77,6 @@
 	"do",
 	"else",
 	"enum", // Would enum actually be useful? I think so.
-	"for",
 	"func", // Would function support need external support from zandronum?
 	"return",
 	"switch",
@@ -169,7 +169,11 @@
 	
 	// Parse done, print statistics and write to file
 	unsigned int globalcount = CountGlobalVars ();
+	int NumMarks = w->MainBuffer->CountMarks ();
+	int NumRefs = w->MainBuffer->CountReferences ();
 	printf ("%u / %u global variable%s\n", globalcount, MAX_SCRIPT_VARIABLES, PLURAL (globalcount));
+	printf ("%d / %d mark%s used\n", NumMarks, MAX_MARKS, PLURAL (NumMarks));
+	printf ("%d / %d ref%s used\n", NumRefs, MAX_MARKS, PLURAL (NumRefs));
 	printf ("%d state%s written\n", g_NumStates, PLURAL (g_NumStates));
 	printf ("%d event%s written\n", g_NumEvents, PLURAL (g_NumEvents));
 	w->WriteToFile ();
--- a/objwriter.cxx	Sun Aug 12 01:52:42 2012 +0300
+++ b/objwriter.cxx	Sun Aug 12 03:23:33 2012 +0300
@@ -56,6 +56,7 @@
 	MainLoopBuffer = new DataBuffer;
 	OnEnterBuffer = new DataBuffer;
 	numWrittenBytes = 0;
+	numWrittenReferences = 0;
 	filepath = path;
 }
 
@@ -121,6 +122,7 @@
 		error ("size of unsigned char isn't 1, but %d!\n", sizeof (unsigned char));
 	
 	// First, resolve references
+	numWrittenReferences = 0;
 	for (unsigned int u = 0; u < MAX_MARKS; u++) {
 		ScriptMarkReference* ref = MainBuffer->refs[u];
 		if (!ref)
@@ -131,6 +133,8 @@
 			uni.val = static_cast<word> (MainBuffer->marks[ref->num]->pos);
 			memset (MainBuffer->buffer + ref->pos + v, uni.b[v], 1);
 		}
+		
+		numWrittenReferences++;
 	}
 	
 	// Then, dump the main buffer to the file
--- a/objwriter.h	Sun Aug 12 01:52:42 2012 +0300
+++ b/objwriter.h	Sun Aug 12 03:23:33 2012 +0300
@@ -60,6 +60,7 @@
 	DataBuffer* OnEnterBuffer;
 	DataBuffer* MainLoopBuffer;
 	unsigned int numWrittenBytes;
+	unsigned int numWrittenReferences;
 	
 	// ====================================================================
 	// METHODS
--- a/parser.cxx	Sun Aug 12 01:52:42 2012 +0300
+++ b/parser.cxx	Sun Aug 12 03:23:33 2012 +0300
@@ -72,6 +72,7 @@
 // of necessary buffering so stuff is written in the correct order.
 void ScriptReader::BeginParse (ObjWriter* w) {
 	while (Next()) {
+		// ============================================================
 		if (!token.icompare ("state")) {
 			MUST_TOPLEVEL
 			
@@ -106,6 +107,7 @@
 			continue;
 		}
 		
+		// ============================================================
 		if (!token.icompare ("event")) {
 			MUST_TOPLEVEL
 			
@@ -126,6 +128,7 @@
 			continue;
 		}
 		
+		// ============================================================
 		if (!token.icompare ("mainloop")) {
 			MUST_TOPLEVEL
 			MustNext ("{");
@@ -136,6 +139,7 @@
 			continue;
 		}
 		
+		// ============================================================
 		if (!token.icompare ("onenter") || !token.icompare ("onexit")) {
 			MUST_TOPLEVEL
 			bool onenter = !token.compare ("onenter");
@@ -148,6 +152,7 @@
 			continue;
 		}
 		
+		// ============================================================
 		if (!token.compare ("var")) {
 			// For now, only globals are supported
 			if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
@@ -170,6 +175,7 @@
 			continue;
 		}
 		
+		// ============================================================
 		// Label
 		if (!PeekNext().compare (":")) {
 			MUST_NOT_TOPLEVEL
@@ -186,6 +192,7 @@
 			continue;
 		}
 		
+		// ============================================================
 		// Goto
 		if (!token.icompare ("goto")) {
 			MUST_NOT_TOPLEVEL
@@ -205,6 +212,7 @@
 			continue;
 		}
 		
+		// ============================================================
 		// If
 		if (!token.icompare ("if")) {
 			MUST_NOT_TOPLEVEL
@@ -236,6 +244,7 @@
 			continue;
 		}
 		
+		// ============================================================
 		// While
 		if (!token.compare ("while")) {
 			MUST_NOT_TOPLEVEL
@@ -270,6 +279,50 @@
 			continue;
 		}
 		
+		// ============================================================
+		// For loop
+		if (!token.icompare ("for")) {
+			MUST_NOT_TOPLEVEL
+			PushBlockStack ();
+			
+			// Initializer
+			MustNext ("(");
+			MustNext ();
+			DataBuffer* init = ParseStatement (w);
+			MustNext (";");
+			
+			// Condition
+			MustNext ();
+			DataBuffer* cond = ParseExpression (TYPE_INT);
+			MustNext (";");
+			
+			// Incrementor
+			MustNext ();
+			DataBuffer* incr = ParseStatement (w);
+			MustNext (")");
+			MustNext ("{");
+			
+			// First, write out the initializer
+			w->WriteBuffer (init);
+			
+			// Init two marks
+			int mark1 = w->AddMark (MARKTYPE_INTERNAL, "");
+			int mark2 = w->AddMark (MARKTYPE_INTERNAL, "");
+			
+			// Add the condition
+			w->WriteBuffer (cond);
+			w->Write<long> (DH_IFNOTGOTO);
+			w->AddReference (mark2);
+			
+			// Store the marks and incrementor
+			blockstack[g_BlockStackCursor].mark1 = mark1;
+			blockstack[g_BlockStackCursor].mark2 = mark2;
+			blockstack[g_BlockStackCursor].buffer1 = incr;
+			blockstack[g_BlockStackCursor].type = BLOCKTYPE_FOR;
+			continue;
+		}
+		
+		// ============================================================
 		if (!token.compare ("}")) {
 			// Closing brace
 			
@@ -281,6 +334,10 @@
 					// Adjust the closing mark.
 					w->MoveMark (info->mark1);
 					break;
+				case BLOCKTYPE_FOR:
+					// Write the incrementor at the end of the loop block
+					w->WriteBuffer (info->buffer1);
+					// fall-thru
 				case BLOCKTYPE_WHILE:
 					// Write down the instruction to go back to the start of the loop
 					w->Write (DH_GOTO);
@@ -314,16 +371,10 @@
 			continue;
 		}
 		
-		// If it's a variable, expect assignment.
-		if (ScriptVar* var = FindGlobalVariable (token)) {
-			DataBuffer* b = ParseAssignment (var);
-			MustNext (";");
-			w->WriteBuffer (b);
-			continue;
-		}
-		
-		// If it's not a keyword, parse it as an expression.
-		DataBuffer* b = ParseExpression (TYPE_VOID);
+		// ============================================================
+		// If nothing else, parse it as a statement (which is either
+		// assignment or expression)
+		DataBuffer* b = ParseStatement (w);
 		w->WriteBuffer (b);
 		MustNext (";");
 	}
@@ -479,8 +530,8 @@
 	MustNext ();
 	DataBuffer* rb = ParseExprValue (reqtype);
 	
+	retbuf->Merge (lb);
 	retbuf->Merge (rb);
-	retbuf->Merge (lb);
 	
 	long dh = DataHeaderByOperator (NULL, oper);
 	retbuf->Write<word> (dh);
@@ -622,4 +673,17 @@
 	info->type = 0;
 	info->mark1 = 0;
 	info->mark2 = 0;
+	info->buffer1 = NULL;
+}
+
+DataBuffer* ScriptReader::ParseStatement (ObjWriter* w) {
+	// If it's a variable, expect assignment.
+	if (ScriptVar* var = FindGlobalVariable (token)) {
+		DataBuffer* b = ParseAssignment (var);
+		return b;
+	}
+	
+	// If it's not a keyword, parse it as an expression.
+	DataBuffer* b = ParseExpression (TYPE_VOID);
+	return b;
 }
\ No newline at end of file
--- a/scriptreader.h	Sun Aug 12 01:52:42 2012 +0300
+++ b/scriptreader.h	Sun Aug 12 03:23:33 2012 +0300
@@ -57,6 +57,7 @@
 	unsigned int mark1;
 	unsigned int mark2;
 	unsigned int type;
+	DataBuffer* buffer1;
 };
 
 // ============================================================================
@@ -115,6 +116,7 @@
 	// preprocessor.cxx:
 	void PreprocessDirectives ();
 	void PreprocessMacros ();
+	DataBuffer* ParseStatement (ObjWriter* w);
 	
 private:
 	bool atnewline;
@@ -165,7 +167,8 @@
 // Block types
 enum {
 	BLOCKTYPE_IF,
-	BLOCKTYPE_WHILE
+	BLOCKTYPE_WHILE,
+	BLOCKTYPE_FOR
 };
 
 #endif // __SCRIPTREADER_H__
\ No newline at end of file

mercurial