Quellcode durchsuchen

Added code to detect global name colision with local names on the same compilation unit.

mingodad vor 13 Jahren
Ursprung
Commit
1eb3917cca
1 geänderte Dateien mit 80 neuen und 40 gelöschten Zeilen
  1. 80 40
      squirrel/sqcompiler.cpp

+ 80 - 40
squirrel/sqcompiler.cpp

@@ -84,11 +84,18 @@ public:
 		_scope.stacksize = 0;
 		_scope.stacksize = 0;
 		_scope.nested = 0;
 		_scope.nested = 0;
 		compilererror = NULL;
 		compilererror = NULL;
+		_globals = SQTable::Create(_ss(_vm),0);
 	}
 	}
+	~SQCompiler(){
+	    _table(_globals)->Finalize();
+	    _globals.Null();
+	}
+
 	static void ThrowError(void *ud, const SQChar *s) {
 	static void ThrowError(void *ud, const SQChar *s) {
 		SQCompiler *c = (SQCompiler *)ud;
 		SQCompiler *c = (SQCompiler *)ud;
 		c->Error(s);
 		c->Error(s);
-	}
+	}
+
 	void Error(const SQChar *s, ...)
 	void Error(const SQChar *s, ...)
 	{
 	{
 		static SQChar temp[256];
 		static SQChar temp[256];
@@ -98,7 +105,8 @@ public:
 		va_end(vl);
 		va_end(vl);
 		compilererror = temp;
 		compilererror = temp;
 		longjmp(_errorjmp,1);
 		longjmp(_errorjmp,1);
-	}
+	}
+
 	void Warning(const SQChar *s, ...)
 	void Warning(const SQChar *s, ...)
 	{
 	{
 		va_list vl;
 		va_list vl;
@@ -106,6 +114,39 @@ public:
 		scvfprintf(stderr, s, vl);
 		scvfprintf(stderr, s, vl);
 		va_end(vl);
 		va_end(vl);
 	}
 	}
+
+	void CheckGlobalName(const SQObject &name, bool addIfNotExists=false, bool checkLocals=true){
+	    if(_table(_globals)->Exists(name)){
+            if(checkLocals) Error(_SC("global '%s' already declared"), _stringval(name));
+            else Warning(_SC("WARNING: %s:%d:%d global '%s' already declared will be shadowed\n"),
+                        _stringval(_sourcename), _lex._currentline, _lex._currentcolumn, _stringval(name));
+	    }
+	    else if(checkLocals) CheckLocalNameScope(name, -1, false);
+	    if(addIfNotExists) {
+	        SQObjectPtr oname = name, otrue = true;
+	        _table(_globals)->NewSlot(oname, otrue);
+	    }
+	}
+
+	void CheckLocalNameScope(const SQObject &name, SQInteger scope, bool checkGlobals=true){
+	    SQInteger found = _fs->GetLocalVariable(name);
+	    if(found >= 0){
+	        SQLocalVarInfo &lvi = _fs->_vlocals[found];
+	        if(lvi._scope == scope)
+                Error(_SC("local '%s' already declared"), _stringval(name));
+            else
+                Warning(_SC("WARNING: %s:%d:%d local '%s' already declared will be shadowed\n"),
+                        _stringval(_sourcename), _lex._currentline, _lex._currentcolumn, _stringval(name));
+	    }
+	    else
+	    {
+	        found = _fs->FindOuterVariable(name);
+	        if(found >= 0) Warning(_SC("WARNING: %s:%d:%d outer variable '%s' already declared will be shadowed\n"),
+                        _stringval(_sourcename), _lex._currentline, _lex._currentcolumn, _stringval(name));
+	    }
+	    if(checkGlobals) CheckGlobalName(name, false, false);
+	}
+
 	bool IsConstant(const SQObject &name,SQObject &e){
 	bool IsConstant(const SQObject &name,SQObject &e){
         SQObjectPtr val;
         SQObjectPtr val;
 	    for(int i=_scope.nested-1; i >= 0; --i){
 	    for(int i=_scope.nested-1; i >= 0; --i){
@@ -119,21 +160,36 @@ public:
             return true;
             return true;
         }
         }
         return false;
         return false;
-	}
-	bool ConstsExists(const SQObjectPtr &key){
-        if(_scope.nested && _table(_scope_consts[_scope.nested-1])->Exists(key)) return true;
-        return _table(_ss(_vm)->_consts)->Exists(key);
 	}
 	}
+
+	void CheckConstsExists(const SQObjectPtr &key){
+	    int found = -1;
+	    for(int i=_scope.nested-1; i >= 0; --i){
+	        if(_table(_scope_consts[i])->Exists(key)) {
+	            found = i+1;
+	            break;
+	        }
+	    }
+	    if(found < 0 && _table(_ss(_vm)->_consts)->Exists(key)) found = 0;
+        if(found == _scope.nested) {
+            Error(_SC("constant '%s' already exists\n"), _stringval(key));
+        }
+        if(found >= 0) Warning(_SC("WARNING: %s:%d:%d an already defined constant '%s' will be shadowed\n"),
+            _stringval(_sourcename), _lex._currentline, _lex._currentcolumn,  _stringval(key));
+	}
+
 	bool ConstsGet(const SQObjectPtr &key,SQObjectPtr &val){
 	bool ConstsGet(const SQObjectPtr &key,SQObjectPtr &val){
 	    for(int i=_scope.nested-1; i >= 0; --i){
 	    for(int i=_scope.nested-1; i >= 0; --i){
 	        if(_table(_scope_consts[i])->Get(key,val)) return true;
 	        if(_table(_scope_consts[i])->Get(key,val)) return true;
 	    }
 	    }
 	    return _table(_ss(_vm)->_consts)->Get(key,val);
 	    return _table(_ss(_vm)->_consts)->Get(key,val);
 	}
 	}
+
 	bool ConstsNewSlot(const SQObjectPtr &key, const SQObjectPtr &val){
 	bool ConstsNewSlot(const SQObjectPtr &key, const SQObjectPtr &val){
 	    if(_scope.nested) return _table(_scope_consts[_scope.nested-1])->NewSlot(key,val);
 	    if(_scope.nested) return _table(_scope_consts[_scope.nested-1])->NewSlot(key,val);
 	    return _table(_ss(_vm)->_consts)->NewSlot(key,val);
 	    return _table(_ss(_vm)->_consts)->NewSlot(key,val);
-	}
+	}
+
 	void Lex(){	_token = _lex.Lex();}
 	void Lex(){	_token = _lex.Lex();}
 	SQObjectPtr GetTokenObject(SQInteger tok)
 	SQObjectPtr GetTokenObject(SQInteger tok)
 	{
 	{
@@ -366,10 +422,8 @@ public:
 			SQObject id = Expect(TK_IDENTIFIER);
 			SQObject id = Expect(TK_IDENTIFIER);
 			Expect('=');
 			Expect('=');
 			SQObjectPtr strongid = id;
 			SQObjectPtr strongid = id;
-			if(ConstsExists(strongid)) {
-			    strongid.Null();
-			    Error(_SC("constant '%s' already exists"), _stringval(id));
-			}
+			CheckLocalNameScope(id, _scope.nested);
+			CheckConstsExists(strongid);
 			SQObject val = ExpectScalar();
 			SQObject val = ExpectScalar();
 			OptionalSemicolon();
 			OptionalSemicolon();
 			ConstsNewSlot(strongid,SQObjectPtr(val));
 			ConstsNewSlot(strongid,SQObjectPtr(val));
@@ -1080,23 +1134,6 @@ public:
 			_fs->SetIntructionParam(tpos, 1, nkeys);
 			_fs->SetIntructionParam(tpos, 1, nkeys);
 		Lex();
 		Lex();
 	}
 	}
-	void checkLocalNameScope(const SQObject &name, SQInteger scope){
-	    SQInteger found = _fs->GetLocalVariable(name);
-	    if(found >= 0){
-	        SQLocalVarInfo &lvi = _fs->_vlocals[found];
-	        if(lvi._scope == scope)
-                Error(_SC("local '%s' already declared"), _stringval(name));
-            else
-                Warning(_SC("WARNING: at line %d:%d local '%s' already declared will be shadowed\n"),
-                        _lex._currentline, _lex._currentcolumn, _stringval(name));
-	    }
-	    else
-	    {
-	        found = _fs->FindOuterVariable(name);
-	        if(found >= 0) Warning(_SC("WARNING: at line %d:%d outer variable '%s' already declared will be shadowed\n"),
-                        _lex._currentline, _lex._currentcolumn, _stringval(name));
-	    }
-	}
 	void LocalDeclStatement()
 	void LocalDeclStatement()
 	{
 	{
 		SQObject varname;
 		SQObject varname;
@@ -1107,7 +1144,7 @@ public:
 		if( _token == TK_FUNCTION) {
 		if( _token == TK_FUNCTION) {
 			Lex();
 			Lex();
 			varname = Expect(TK_IDENTIFIER);
 			varname = Expect(TK_IDENTIFIER);
-			checkLocalNameScope(varname, _scope.nested);
+			CheckLocalNameScope(varname, _scope.nested);
 			Expect(_SC('('));
 			Expect(_SC('('));
 			//the following is an attempt to allow local declared functions be called recursivelly
 			//the following is an attempt to allow local declared functions be called recursivelly
 			SQInteger old_pos = _fs->GetCurrentPos(); //save current instructions position
 			SQInteger old_pos = _fs->GetCurrentPos(); //save current instructions position
@@ -1129,7 +1166,7 @@ public:
 		        Lex();
 		        Lex();
 		    }
 		    }
 			varname = Expect(TK_IDENTIFIER);
 			varname = Expect(TK_IDENTIFIER);
-			checkLocalNameScope(varname, _scope.nested);
+			CheckLocalNameScope(varname, _scope.nested);
 			if(_token == _SC('=')) {
 			if(_token == _SC('=')) {
 				Lex(); Expression();
 				Lex(); Expression();
 				SQInteger src = _fs->PopTarget();
 				SQInteger src = _fs->PopTarget();
@@ -1430,7 +1467,8 @@ if(color == "yellow"){
 	void FunctionStatement()
 	void FunctionStatement()
 	{
 	{
 		SQObject id;
 		SQObject id;
-		Lex(); id = Expect(TK_IDENTIFIER);
+		Lex(); id = Expect(TK_IDENTIFIER);
+		CheckGlobalName(id, true);
 		_fs->PushTarget(0);
 		_fs->PushTarget(0);
 		_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
 		_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
 		if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
 		if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
@@ -1450,14 +1488,18 @@ if(color == "yellow"){
 	void ClassStatement()
 	void ClassStatement()
 	{
 	{
 		SQExpState es;
 		SQExpState es;
-		Lex();
+		Lex();
+		if(_token == TK_IDENTIFIER) {
+		    SQObjectPtr str = SQString::Create(_ss(_vm), _lex._svalue);
+		    CheckGlobalName(str, true);
+		}
 		es = _es;
 		es = _es;
 		_es.donot_get = true;
 		_es.donot_get = true;
 		PrefixedExpr();
 		PrefixedExpr();
 		if(_es.etype == EXPR) {
 		if(_es.etype == EXPR) {
 			Error(_SC("invalid class name"));
 			Error(_SC("invalid class name"));
 		}
 		}
-		else if(_es.etype == OBJECT || _es.etype == BASE) {
+		else if(_es.etype == OBJECT || _es.etype == BASE) {
 			ClassExp();
 			ClassExp();
 			EmitDerefOp(_OP_NEWSLOT);
 			EmitDerefOp(_OP_NEWSLOT);
 			_fs->PopTarget();
 			_fs->PopTarget();
@@ -1511,13 +1553,10 @@ if(color == "yellow"){
 		SQObject id = Expect(TK_IDENTIFIER);
 		SQObject id = Expect(TK_IDENTIFIER);
 		Expect(_SC('{'));
 		Expect(_SC('{'));
 
 
-        //checkLocalNameScope(id, _scope.nested);
+        //CheckLocalNameScope(id, _scope.nested);
 		SQObjectPtr strongid = id;
 		SQObjectPtr strongid = id;
-		if(ConstsExists(strongid)) {
-		    strongid.Null();
-		    Error(_SC("constant '%s' already exists"), _stringval(id));
-		}
-
+		CheckLocalNameScope(id, _scope.nested);
+        CheckConstsExists(strongid);
 		SQObject table = _fs->CreateTable();
 		SQObject table = _fs->CreateTable();
 		//_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
 		//_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
 		SQInteger nval = 0;
 		SQInteger nval = 0;
@@ -1744,7 +1783,8 @@ private:
 	SQChar *compilererror;
 	SQChar *compilererror;
 	jmp_buf _errorjmp;
 	jmp_buf _errorjmp;
 	SQVM *_vm;
 	SQVM *_vm;
-	SQObjectPtrVec _scope_consts;
+	SQObjectPtrVec _scope_consts;
+	SQObjectPtr _globals;
 };
 };
 
 
 bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
 bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)