Some rework on variables

Wed, 19 Dec 2012 04:20:02 +0200

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Wed, 19 Dec 2012 04:20:02 +0200
changeset 67
0a202714eea4
parent 66
4fc1ec88aa41
child 68
588cc27e84bb

Some rework on variables

commands.cxx file | annotate | diff | comparison | revisions
common.h file | annotate | diff | comparison | revisions
main.cxx file | annotate | diff | comparison | revisions
objwriter.h file | annotate | diff | comparison | revisions
parser.cxx file | annotate | diff | comparison | revisions
scriptreader.cxx file | annotate | diff | comparison | revisions
variables.cxx file | annotate | diff | comparison | revisions
variables.h file | annotate | diff | comparison | revisions
--- a/commands.cxx	Wed Dec 19 03:27:15 2012 +0200
+++ b/commands.cxx	Wed Dec 19 04:20:02 2012 +0200
@@ -159,11 +159,11 @@
 // Get command type by name
 int GetCommandType (str t) {
 	t = t.tolower();
-	return	!t.compare ("int") ? TYPE_INT :
-		!t.compare ("float") ? TYPE_FLOAT :
-		!t.compare ("str") ? TYPE_STRING :
-		!t.compare ("void") ? TYPE_VOID :
-		!t.compare ("bool") ? TYPE_BOOL : -1;
+	return	(t == "int") ? TYPE_INT :
+			(t == "float") ? TYPE_FLOAT :
+			(t == "str") ? TYPE_STRING :
+			(t == "void") ? TYPE_VOID :
+			(t == "bool") ? TYPE_BOOL : -1;
 }
 
 // ============================================================================
--- a/common.h	Wed Dec 19 03:27:15 2012 +0200
+++ b/common.h	Wed Dec 19 04:20:02 2012 +0200
@@ -59,7 +59,7 @@
 #endif
 
 // Parser mode: where is the parser at?
-enum parsermode {
+enum parsermode_e {
 	MODE_TOPLEVEL,	// at top level
 	MODE_EVENT,		// inside event definition
 	MODE_MAINLOOP,	// inside mainloop
@@ -93,7 +93,7 @@
 // Make the parser's variables globally available
 extern int g_NumStates;
 extern int g_NumEvents;
-extern int g_CurMode;
+extern parsermode_e g_CurMode;
 extern str g_CurState;
 
 #define neurosphere if (g_Neurosphere)
@@ -102,6 +102,7 @@
 #ifndef __GNUC__
 #define __attribute__(X)
 #endif
+#define deprecated __attribute__ ((deprecated))
 
 // Power function
 template<class T> T pow (T a, unsigned int b) {
--- a/main.cxx	Wed Dec 19 03:27:15 2012 +0200
+++ b/main.cxx	Wed Dec 19 04:20:02 2012 +0200
@@ -168,7 +168,6 @@
 	
 	// Init stuff
 	InitStringTable ();
-	InitVariables ();
 	
 	// Prepare reader and writer
 	ScriptReader* r = new ScriptReader (argv[1]);
@@ -180,7 +179,7 @@
 	printf ("Script parsed successfully.\n");
 	
 	// Parse done, print statistics and write to file
-	unsigned int globalcount = CountGlobalVars ();
+	unsigned int globalcount = g_GlobalVariables.size();
 	unsigned int stringcount = CountStringTable ();
 	int NumMarks = w->MainBuffer->CountMarks ();
 	int NumRefs = w->MainBuffer->CountReferences ();
--- a/objwriter.h	Wed Dec 19 03:27:15 2012 +0200
+++ b/objwriter.h	Wed Dec 19 04:20:02 2012 +0200
@@ -48,8 +48,6 @@
 #include "databuffer.h"
 #include "str.h"
 
-extern int g_CurMode;
-
 class ObjWriter {
 public:
 	// ====================================================================
--- a/parser.cxx	Wed Dec 19 03:27:15 2012 +0200
+++ b/parser.cxx	Wed Dec 19 04:20:02 2012 +0200
@@ -61,7 +61,7 @@
 
 int g_NumStates = 0;
 int g_NumEvents = 0;
-int g_CurMode = MODE_TOPLEVEL;
+parsermode_e g_CurMode = MODE_TOPLEVEL;
 str g_CurState = "";
 bool g_stateSpawnDefined = false;
 bool g_GotMainLoop = false;
@@ -171,11 +171,16 @@
 		}
 		
 		// ============================================================
-		if (token == "var") {
+		if (token == "int" || token == "str" || token == "float" || token == "bool") {
 			// For now, only globals are supported
 			if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
 				ParserError ("variables must only be global for now");
 			
+			type_e type =	(token == "int") ? TYPE_INT :
+							(token == "str") ? TYPE_STRING :
+							(token == "float") ? TYPE_FLOAT :
+							TYPE_BOOL;
+			
 			MustNext ();
 			
 			// Var name must not be a number
@@ -183,7 +188,7 @@
 				ParserError ("variable name must not be a number");
 			
 			str varname = token;
-			ScriptVar* var = DeclareGlobalVariable (this, varname);
+			ScriptVar* var = DeclareGlobalVariable (this, type, varname);
 			
 			if (!var)
 				ParserError ("declaring %s variable %s failed",
@@ -319,16 +324,25 @@
 			MustNext ("(");
 			MustNext ();
 			DataBuffer* init = ParseStatement (w);
+			if (!init)
+				ParserError ("bad statement for initializer of for");
+			
 			MustNext (";");
 			
 			// Condition
 			MustNext ();
 			DataBuffer* cond = ParseExpression (TYPE_INT);
+			if (!cond)
+				ParserError ("bad statement for condition of for");
+			
 			MustNext (";");
 			
 			// Incrementor
 			MustNext ();
 			DataBuffer* incr = ParseStatement (w);
+			if (!incr)
+				ParserError ("bad statement for incrementor of for");
+			
 			MustNext (")");
 			MustNext ("{");
 			
@@ -507,7 +521,7 @@
 		
 		// ============================================================
 		// Label
-		if (!PeekNext().compare (":")) {
+		if (PeekNext() == ":") {
 			MUST_NOT_TOPLEVEL
 			
 			// want no conflicts..
@@ -521,7 +535,7 @@
 			// See if a mark already exists for this label
 			int mark = -1;
 			for (int i = 0; i < MAX_MARKS; i++) {
-				if (g_UndefinedLabels[i] && !g_UndefinedLabels[i]->compare (token)) {
+				if (g_UndefinedLabels[i] && *g_UndefinedLabels[i] == token) {
 					mark = i;
 					w->MoveMark (i);
 					
@@ -540,7 +554,7 @@
 		}
 		
 		// ============================================================
-		if (!token.compare ("}")) {
+		if (token == "}") {
 			// Closing brace
 			
 			// If we're in the block stack, we're descending down from it now
@@ -640,7 +654,7 @@
 			w->Write (dataheader);
 			g_CurMode = MODE_TOPLEVEL;
 			
-			if (!PeekNext().compare (";"))
+			if (PeekNext() == ";")
 				MustNext (";");
 			continue;
 		}
@@ -656,6 +670,9 @@
 		// ============================================================
 		// If nothing else, parse it as a statement
 		DataBuffer* b = ParseStatement (w);
+		if (!b)
+			ParserError ("unknown token `%s`", token.chars());
+		
 		w->WriteBuffer (b);
 		MustNext (";");
 	}
@@ -692,7 +709,7 @@
 	
 	int curarg = 0;
 	while (1) {
-		if (!token.compare (")")) {
+		if (token == ")") {
 			if (curarg < comm->numargs)
 				ParserError ("too few arguments passed to %s\n\tprototype: %s",
 					comm->name.chars(), GetCommandPrototype (comm).chars());
@@ -712,7 +729,7 @@
 			MustNext ();
 		} else if (curarg < comm->maxargs - 1) {
 			// Can continue, but can terminate as well.
-			if (!token.compare (")")) {
+			if (token == ")") {
 				curarg++;
 				break;
 			} else {
@@ -855,7 +872,7 @@
 
 // ============================================================================
 // Parses an operator string. Returns the operator number code.
-#define ISNEXT(char) !PeekNext (peek ? 1 : 0).compare (char)
+#define ISNEXT(char) (!PeekNext (peek ? 1 : 0) == char)
 int ScriptReader::ParseOperator (bool peek) {
 	str oper;
 	if (peek)
@@ -866,18 +883,18 @@
 	// Check one-char operators
 	bool equalsnext = ISNEXT ("=");
 	
-	int o =	(!oper.compare ("=") && !equalsnext) ? OPER_ASSIGN :
-		(!oper.compare (">") && !equalsnext && !ISNEXT (">")) ? OPER_GREATERTHAN :
-		(!oper.compare ("<") && !equalsnext && !ISNEXT ("<")) ? OPER_LESSTHAN :
-		(!oper.compare ("&") && !ISNEXT ("&")) ? OPER_BITWISEAND :
-		(!oper.compare ("|") && !ISNEXT ("|")) ? OPER_BITWISEOR :
-		!oper.compare ("^") ? OPER_BITWISEEOR :
-		!oper.compare ("+") ? OPER_ADD :
-		!oper.compare ("-") ? OPER_SUBTRACT :
-		!oper.compare ("*") ? OPER_MULTIPLY :
-		!oper.compare ("/") ? OPER_DIVIDE :
-		!oper.compare ("%") ? OPER_MODULUS :
-		!oper.compare ("?") ? OPER_TERNARY :
+	int o =	(oper == "=" && !equalsnext) ? OPER_ASSIGN :
+		(oper == ">" && !equalsnext && !ISNEXT (">")) ? OPER_GREATERTHAN :
+		(oper == "<" && !equalsnext && !ISNEXT ("<")) ? OPER_LESSTHAN :
+		(oper == "&" && !ISNEXT ("&")) ? OPER_BITWISEAND :
+		(oper == "|" && !ISNEXT ("|")) ? OPER_BITWISEOR :
+		(oper == "+" && !equalsnext) ? OPER_ADD :
+		(oper == "-" && !equalsnext) ? OPER_SUBTRACT :
+		(oper == "*" && !equalsnext) ? OPER_MULTIPLY :
+		(oper == "/" && !equalsnext) ? OPER_DIVIDE :
+		(oper == "%" && !equalsnext) ? OPER_MODULUS :
+		(oper == "^") ? OPER_BITWISEEOR :
+		(oper == "?") ? OPER_TERNARY :
 		-1;
 	
 	if (o != -1) {
@@ -886,21 +903,21 @@
 	
 	// Two-char operators
 	oper += PeekNext (peek ? 1 : 0);
-	equalsnext = !PeekNext (peek ? 2 : 1).compare ("=");
+	equalsnext = PeekNext (peek ? 2 : 1) == ("=");
 	
-	o =	!oper.compare ("+=") ? OPER_ASSIGNADD :
-		!oper.compare ("-=") ? OPER_ASSIGNSUB :
-		!oper.compare ("*=") ? OPER_ASSIGNMUL :
-		!oper.compare ("/=") ? OPER_ASSIGNDIV :
-		!oper.compare ("%=") ? OPER_ASSIGNMOD :
-		!oper.compare ("==") ? OPER_EQUALS :
-		!oper.compare ("!=") ? OPER_NOTEQUALS :
-		!oper.compare (">=") ? OPER_GREATERTHANEQUALS :
-		!oper.compare ("<=") ? OPER_LESSTHANEQUALS :
-		!oper.compare ("&&") ? OPER_AND :
-		!oper.compare ("||") ? OPER_OR :
-		(!oper.compare ("<<") && !equalsnext) ? OPER_LEFTSHIFT :
-		(!oper.compare (">>") && !equalsnext) ? OPER_RIGHTSHIFT :
+	o =	(oper == "+=") ? OPER_ASSIGNADD :
+		(oper == "-=") ? OPER_ASSIGNSUB :
+		(oper == "*=") ? OPER_ASSIGNMUL :
+		(oper == "/=") ? OPER_ASSIGNDIV :
+		(oper == "%=") ? OPER_ASSIGNMOD :
+		(oper == "==") ? OPER_EQUALS :
+		(oper == "!=") ? OPER_NOTEQUALS :
+		(oper == ">=") ? OPER_GREATERTHANEQUALS :
+		(oper == "<=") ? OPER_LESSTHANEQUALS :
+		(oper == "&&") ? OPER_AND :
+		(oper == "||") ? OPER_OR :
+		(oper == "<<" && !equalsnext) ? OPER_LEFTSHIFT :
+		(oper == ">>" && !equalsnext) ? OPER_RIGHTSHIFT :
 		-1;
 	
 	if (o != -1) {
@@ -910,8 +927,8 @@
 	
 	// Three-char opers
 	oper += PeekNext (peek ? 2 : 1);
-	o =	!oper.compare ("<<=") ? OPER_ASSIGNLEFTSHIFT :
-		!oper.compare (">>=") ? OPER_ASSIGNRIGHTSHIFT :
+	o =	oper == "<<=" ? OPER_ASSIGNLEFTSHIFT :
+		oper == ">>=" ? OPER_ASSIGNRIGHTSHIFT :
 		-1;
 	
 	if (o != -1) {
@@ -932,11 +949,11 @@
 	ScriptVar* g;
 	
 	// Prefixing "!" means negation.
-	bool negate = !token.compare ("!");
+	bool negate = (token == "!");
 	if (negate) // Jump past the "!"
-		MustNext ();
+		Next ();
 	
-	if (!token.compare ("(")) {
+	if (token == "(") {
 		// Expression
 		MustNext ();
 		DataBuffer* c = ParseExpression (reqtype);
@@ -949,12 +966,13 @@
 		if (reqtype && comm->returnvalue != reqtype)
 			ParserError ("%s returns an incompatible data type", comm->name.chars());
 		b = ParseCommand (comm);
-	} else if ((g = FindGlobalVariable (token)) && reqtype != TYPE_STRING) {
+	} else if ((g = FindGlobalVariable (token))) {
 		// Global variable
 		b->Write<word> (DH_PUSHGLOBALVAR);
 		b->Write<word> (g->index);
 	} else {
 		// If nothing else, check for literal
+		printf ("reqtype: %d\n", reqtype);
 		switch (reqtype) {
 		case TYPE_VOID:
 			ParserError ("unknown identifier `%s` (expected keyword, function or variable)", token.chars());
@@ -964,10 +982,10 @@
 			MustNumber (true);
 			
 			// All values are written unsigned - thus we need to write the value's
-			// absolute value, followed by an unary minus if it was negative.
+			// absolute value, followed by an unary minus for negatives.
 			b->Write<word> (DH_PUSHNUMBER);
 			
-			long v = atoi (token.chars ());
+			long v = atol (token);
 			b->Write<word> (static_cast<word> (abs (v)));
 			if (v < 0)
 				b->Write<word> (DH_UNARYMINUS);
@@ -988,7 +1006,7 @@
 			floatstring += token;
 			
 			// Go after the decimal point
-			if (!PeekNext ().compare(".")) {
+			if (PeekNext () == ".") {
 				MustNext (".");
 				MustNumber (false);
 				floatstring += ".";
@@ -1030,6 +1048,7 @@
 	// Get an operator
 	MustNext ();
 	int oper = ParseOperator ();
+	printf ("got operator %d\n", oper);
 	if (!IsAssignmentOperator (oper))
 		ParserError ("expected assignment operator");
 	
@@ -1039,7 +1058,7 @@
 	// Parse the right operand
 	MustNext ();
 	DataBuffer* retbuf = new DataBuffer;
-	DataBuffer* expr = ParseExpression (TYPE_INT);
+	DataBuffer* expr = ParseExpression (var->type);
 	
 	// <<= and >>= do not have data headers. Solution: expand them.
 	// a <<= b -> a = a << b
@@ -1086,7 +1105,6 @@
 		return b;
 	}
 	
-	ParserError ("bad statement");
 	return NULL;
 }
 
--- a/scriptreader.cxx	Wed Dec 19 03:27:15 2012 +0200
+++ b/scriptreader.cxx	Wed Dec 19 04:20:02 2012 +0200
@@ -331,7 +331,7 @@
 
 // ============================================================================
 void ScriptReader::MustThis (const char* c) {
-	if (token.compare (c) != 0)
+	if (token != c)
 		ParserError ("expected `%s`, got `%s` instead", c, token.chars());
 }
 
@@ -388,7 +388,7 @@
 		MustNext ();
 	
 	str num = token;
-	if (!num.compare ("-")) {
+	if (num == "-") {
 		MustNext ();
 		num += token;
 	}
@@ -404,7 +404,7 @@
 		
 		str check;
 		check.appendformat ("%d", atoi (num));
-		if (token.compare (check) != 0)
+		if (token != check)
 			ParserWarning ("integer too large: %s -> %s", num.chars(), check.chars());
 		
 		token = num;
--- a/variables.cxx	Wed Dec 19 03:27:15 2012 +0200
+++ b/variables.cxx	Wed Dec 19 04:20:02 2012 +0200
@@ -43,6 +43,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "common.h"
+#include "array.h"
 #include "bots.h"
 #include "botcommands.h"
 #include "objwriter.h"
@@ -50,70 +51,48 @@
 #include "variables.h"
 #include "scriptreader.h"
 
-ScriptVar* g_GlobalVariables[MAX_SCRIPT_VARIABLES];
-ScriptVar* g_LocalVariable;
-
-void InitVariables () {
-	unsigned int u;
-	ITERATE_GLOBAL_VARS (u)
-		g_GlobalVariables[u] = NULL;
-}
+array<ScriptVar> g_GlobalVariables;
+array<ScriptVar> g_LocalVariables;
 
 // ============================================================================
 // Tries to declare a new global-scope variable. Returns pointer
 // to new global variable, NULL if declaration failed.
-ScriptVar* DeclareGlobalVariable (ScriptReader* r, str name) {
-	// Check that the name is valid
+ScriptVar* DeclareGlobalVariable (ScriptReader* r, type_e type, str name) {
+	// Unfortunately the VM does not support string variables so yeah.
+	if (type == TYPE_STRING)
+		r->ParserError ("variables cannot be string\n");
+	
+	// Check that the variable is valid
 	if (FindCommand (name))
 		r->ParserError ("name of variable-to-be `%s` conflicts with that of a command", name.chars());
 	
 	if (IsKeyword (name))
 		r->ParserError ("name of variable-to-be `%s` is a keyword", name.chars());
 	
-	// Find a NULL pointer to a global variable
-	ScriptVar* g;
-	unsigned int u = 0;
-	ITERATE_GLOBAL_VARS (u) {
-		// Check that it doesn't exist already
-		if (!g_GlobalVariables[u])
-			break;
-		
-		if (!g_GlobalVariables[u]->name.icompare (name))
-			r->ParserError ("attempted redeclaration of variable `%s`", name.chars());
-	}
-	
-	if (u == MAX_SCRIPT_VARIABLES)
+	if (g_GlobalVariables.size() >= MAX_SCRIPT_VARIABLES)
 		r->ParserError ("too many global variables!");
 	
-	g = new ScriptVar;
-	g->index = u;
-	g->name = name;
-	g->statename = "";
-	g->next = NULL;
-	g->value = 0;
+	for (uint i = 0; i < g_GlobalVariables.size(); i++)
+		if (g_GlobalVariables[i].name == name)
+			r->ParserError ("attempted redeclaration of global variable `%s`", name.chars());
 	
-	g_GlobalVariables[u] = g;
-	return g;
+	ScriptVar g;
+	g.index = g_GlobalVariables.size();
+	g.name = name;
+	g.statename = "";
+	g.value = 0;
+	g.type = type;
+	
+	g_GlobalVariables << g;
+	return &g_GlobalVariables[g.index];
 }
 
-/*
-void AssignScriptVariable (ScriptReader* r, str name, str value) {
-	ScriptVar* g = FindScriptVariable (name);
-	if (!g)
-		r->ParserError ("global variable %s not declared", name.chars());
-}
-*/
-
 // ============================================================================
 // Find a global variable by name
 ScriptVar* FindGlobalVariable (str name) {
-	unsigned int u = 0;
-	ITERATE_GLOBAL_VARS (u) {
-		ScriptVar* g = g_GlobalVariables[u];
-		if (!g)
-			return NULL;
-		
-		if (!g->name.compare (name))
+	for (uint i = 0; i < g_GlobalVariables.size(); i++) {
+		ScriptVar* g = &g_GlobalVariables[i];
+		if (g->name == name)
 			return g;
 	}
 	
@@ -122,12 +101,6 @@
 
 // ============================================================================
 // Count all declared global variables
-unsigned int CountGlobalVars () {
-	unsigned int count = 0;
-	unsigned int u = 0;
-	ITERATE_GLOBAL_VARS (u) {
-		if (g_GlobalVariables[u] != NULL)
-			count++;
-	}
-	return count;
+uint CountGlobalVars () {
+	return g_GlobalVariables.size();
 }
\ No newline at end of file
--- a/variables.h	Wed Dec 19 03:27:15 2012 +0200
+++ b/variables.h	Wed Dec 19 04:20:02 2012 +0200
@@ -46,24 +46,21 @@
 struct ScriptVar {
 	str name;
 	str statename;
+	type_e type;
 	int value;
 	unsigned int index;
-	ScriptVar* next;
 };
 
-#ifndef __VARIABLES_CXX__
-extern ScriptVar* g_GlobalVariables[MAX_SCRIPT_VARIABLES];
-extern ScriptVar* g_LocalVariable;
-#endif // __VARIABLES_CXX__
+extern array<ScriptVar> g_GlobalVariables;
+extern array<ScriptVar> g_LocalVariables;
 
 #define ITERATE_GLOBAL_VARS(u) \
 	for (u = 0; u < MAX_SCRIPT_VARIABLES; u++)
 #define ITERATE_SCRIPT_VARS(g) \
 	for (g = g_ScriptVariable; g != NULL; g = g->next)
 
-ScriptVar* DeclareGlobalVariable (ScriptReader* r, str name);
-unsigned int CountGlobalVars ();
-void InitVariables ();
+ScriptVar* DeclareGlobalVariable (ScriptReader* r, type_e type, str name);
+deprecated unsigned int CountGlobalVars ();
 ScriptVar* FindGlobalVariable (str name);
 
 #endif // __VARIABLES_H__
\ No newline at end of file

mercurial