Просмотр исходного кода

Halfway to change enum/const declaration from global to local, meanwhile raise an error when try redeclare an already declared enum/const.

mingodad 13 лет назад
Родитель
Сommit
e07e89dfe6

+ 5 - 1
squirrel/sqarray.h

@@ -32,6 +32,10 @@ public:
 		}
 		else return false;
 	}
+	bool Exists(const SQInteger nidx)
+	{
+		return (nidx>=0 && nidx<(SQInteger)_values.size());
+	}
 	bool Set(const SQInteger nidx,const SQObjectPtr &val)
 	{
 		if(nidx>=0 && nidx<(SQInteger)_values.size()){
@@ -88,7 +92,7 @@ public:
 	{
 		sq_delete(this,SQArray);
 	}
-	
+
 	SQObjectPtrVec _values;
 };
 #endif //_SQARRAY_H_

+ 9 - 3
squirrel/sqclass.h

@@ -45,6 +45,9 @@ public:
 		}
 		return false;
 	}
+	bool Exists(const SQObjectPtr &key) {
+		return _members->Exists(key);
+	}
 	bool GetConstructor(SQObjectPtr &ctor)
 	{
 		if(_constructoridx != -1) {
@@ -83,14 +86,14 @@ public:
 #define calcinstancesize(_theclass_) \
 	(_theclass_->_udsize + sq_aligning(sizeof(SQInstance) +  (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))
 
-struct SQInstance : public SQDelegable 
+struct SQInstance : public SQDelegable
 {
 	void Init(SQSharedState *ss);
 	SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);
 	SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);
 public:
 	static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {
-		
+
 		SQInteger size = calcinstancesize(theclass);
 		SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
 		new (newinst) SQInstance(ss, theclass,size);
@@ -123,6 +126,9 @@ public:
 		}
 		return false;
 	}
+	bool Exists(const SQObjectPtr &key)  {
+		return _class->_members->Exists(key);
+	}
 	bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {
 		SQObjectPtr idx;
 		if(_class->_members->Get(key,idx) && _isfield(idx)) {
@@ -147,7 +153,7 @@ public:
 		SQ_FREE(this, size);
 	}
 	void Finalize();
-#ifndef NO_GARBAGE_COLLECTOR 
+#ifndef NO_GARBAGE_COLLECTOR
 	void Mark(SQCollectable ** );
 	SQObjectType GetType() {return OT_INSTANCE;}
 #endif

+ 71 - 27
squirrel/sqcompiler.cpp

@@ -250,7 +250,8 @@ public:
 		case TK_LOCAL_UINT_T:
 		case TK_LOCAL_FLOAT_T:
 		case TK_LOCAL_DOUBLE_T:
-		case TK_LOCAL_LONG_DOUBLE_T:
+		case TK_LOCAL_LONG_DOUBLE_T:
+		//case TK_CONST:
 		case TK_LOCAL:		LocalDeclStatement();	break;
 		case TK_RETURN:
 		case TK_YIELD: {
@@ -327,20 +328,27 @@ public:
 			Lex();
 			CommaExpr();
 			_fs->AddInstruction(_OP_THROW, _fs->PopTarget());
-			break;
+			break;
+
 		case TK_CONST:
-			{
+			{
 			Lex();
 			SQObject id = Expect(TK_IDENTIFIER);
 			Expect('=');
 			SQObject val = ExpectScalar();
-			OptionalSemicolon();
+			OptionalSemicolon();
 			SQTable *enums = _table(_ss(_vm)->_consts);
-			SQObjectPtr strongid = id;
+			SQObjectPtr strongid = id;
+			if(enums->Exists(strongid)) {
+			    strongid.Null();
+			    Error(_SC("constant '%s' already exists"), _stringval(id));
+			}
 			enums->NewSlot(strongid,SQObjectPtr(val));
-			strongid.Null();
+			strongid.Null();
+
 			}
-			break;
+			break;
+
 		default:
 			CommaExpr();
 			_fs->DiscardTarget();
@@ -408,6 +416,11 @@ public:
 	void CommaExpr(bool warningAssign=false)
 	{
 		for(Expression(warningAssign);_token == ',';_fs->PopTarget(), Lex(), CommaExpr(warningAssign));
+	}
+	void ErrorIfConst(){
+        SQLocalVarInfo &vsrc = _fs->_vlocals[_fs->TopTarget()];
+printf("%d %d %d %d %s\n", __LINE__, vsrc._scope, vsrc._type, vsrc._pos, vsrc._name._unVal.pString ? _stringval(vsrc._name) : "?");
+        if(vsrc._type & _VAR_CONST) Error(_SC("can't assign to a const variable"));
 	}
 	void Expression(bool warningAssign=false)
 	{
@@ -426,8 +439,10 @@ public:
 		case TK_MODEQ:{
 			SQInteger op = _token;
 			SQInteger ds = _es.etype;
-			SQInteger pos = _es.epos;
-			if(ds == EXPR) Error(_SC("can't assign expression"));
+			SQInteger pos = _es.epos;
+
+			if(ds == EXPR) Error(_SC("can't assign expression"));
+            ErrorIfConst();
 			Lex(); Expression();
 
 			switch(op){
@@ -687,7 +702,7 @@ public:
 					Lex();
 					switch(_es.etype)
 					{
-						case EXPR: Error(_SC("can't '++' or '--' an expression")); break;
+						case EXPR: Error(_SC("can't '++' or '--' an expression")); break;
 						case OBJECT:
 						case BASE:
 							Emit2ArgsOP(_OP_PINC, diff);
@@ -1038,15 +1053,22 @@ public:
 	    if(found >= 0){
 	        SQLocalVarInfo &lvi = _fs->_vlocals[found];
 	        if(lvi._scope == scope)
-                Error(_SC("local '%s' already declared"), _string(name)->_val);
+                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, _string(name)->_val);
+                        _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()
 	{
-		SQObject varname;
+		SQObject varname;
+		SQBool is_const_declaration = _token == TK_CONST;
 		SQInteger declType = _token;
 		Lex();
 		if( _token == TK_FUNCTION) {
@@ -1057,7 +1079,7 @@ public:
 			CreateFunction(varname,false);
 			_fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
 			_fs->PopTarget();
-			_fs->PushLocalVariable(varname, _scope.nested);
+			_fs->PushLocalVariable(varname, _scope.nested, _VAR_CLOSURE);
 			return;
 		}
 
@@ -1068,26 +1090,34 @@ public:
 				Lex(); Expression();
 				SQInteger src = _fs->PopTarget();
 				SQInteger dest = _fs->PushTarget();
-				if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
-			}
+				if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
+				declType = _VAR_ANY;
+			}
+			else if(is_const_declaration) Error(_SC("const '%s' need an initializer"), _stringval(varname));
 			else{
 			    SQInteger dest = _fs->PushTarget();
 			    switch(declType){
-			        /*
                     case TK_LOCAL_CHAR_T:
                     case TK_LOCAL_WCHAR_T:
+                        _fs->AddInstruction(_OP_LOADNULLS, dest,1);
+                        declType = _VAR_STRING;
                         break;
-                    */
+
                     case TK_LOCAL_BOOL_T:
                         //default value false
                         _fs->AddInstruction(_OP_LOADBOOL, dest,0);
+                        declType = _VAR_BOOL;
                         break;
-                    /*
+
                     case TK_LOCAL_TABLE_T:
+                        _fs->AddInstruction(_OP_LOADNULLS, dest,1);
+                        declType = _VAR_TABLE;
                         break;
                     case TK_LOCAL_ARRAY_T:
+                        _fs->AddInstruction(_OP_LOADNULLS, dest,1);
+                        declType = _VAR_ARRAY;
                         break;
-                    */
+
                     case TK_LOCAL_INT8_T:
                     case TK_LOCAL_INT16_T:
                     case TK_LOCAL_INT32_T:
@@ -1100,21 +1130,24 @@ public:
                     case TK_LOCAL_UINT_T:
                         //default value 0
                         _fs->AddInstruction(_OP_LOADINT, dest,0);
+                        declType = _VAR_INTEGER;
                         break;
                     case TK_LOCAL_FLOAT_T:
                     case TK_LOCAL_DOUBLE_T:
                     case TK_LOCAL_LONG_DOUBLE_T:
                         //default value 0.0
                         _fs->AddInstruction(_OP_LOADFLOAT, dest,0);
+                        declType = _VAR_FLOAT;
                         break;
                     //case TK_LOCAL:
                     default:
                         //default value null
-                        _fs->AddInstruction(_OP_LOADNULLS, dest,1);
+                        _fs->AddInstruction(_OP_LOADNULLS, dest,1);
+                        declType = _VAR_ANY;
 			    }
 			}
 			_fs->PopTarget();
-			_fs->PushLocalVariable(varname, _scope.nested);
+			_fs->PushLocalVariable(varname, _scope.nested, is_const_declaration ? _VAR_CONST : declType);
 			if(_token == _SC(',')) Lex(); else break;
 		} while(1);
 	}
@@ -1430,8 +1463,17 @@ if(color == "yellow"){
 		Lex();
 		SQObject id = Expect(TK_IDENTIFIER);
 		Expect(_SC('{'));
+
+        //checkLocalNameScope(id, _scope.nested);
+		SQTable *enums = _table(_ss(_vm)->_consts);
+		SQObjectPtr strongid = id;
+		if(enums->Exists(strongid)) {
+		    strongid.Null();
+		    Error(_SC("constant '%s' already exists"), _stringval(id));
+		}
 
-		SQObject table = _fs->CreateTable();
+		SQObject table = _fs->CreateTable();
+		//_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
 		SQInteger nval = 0;
 		while(_token != _SC('}')) {
 			SQObject key = Expect(TK_IDENTIFIER);
@@ -1443,12 +1485,14 @@ if(color == "yellow"){
 			else {
 				val._type = OT_INTEGER;
 				val._unVal.nInteger = nval++;
-			}
+			}
+			//SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
+            //_fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
+
 			_table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
 			if(_token == ',') Lex();
-		}
-		SQTable *enums = _table(_ss(_vm)->_consts);
-		SQObjectPtr strongid = id;
+		}
+
 		enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
 		strongid.Null();
 		Lex();

+ 25 - 10
squirrel/sqfuncproto.h

@@ -11,7 +11,7 @@ enum SQOuterType {
 
 struct SQOuterVar
 {
-	
+
 	SQOuterVar(){}
 	SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)
 	{
@@ -29,23 +29,38 @@ struct SQOuterVar
 	SQObjectPtr _name;
 	SQObjectPtr _src;
 };
+
+#define _VAR_ANY			0x00000001
+#define _VAR_INTEGER		0x00000002
+#define _VAR_FLOAT			0x00000004
+#define _VAR_BOOL			0x00000008
+#define _VAR_STRING			0x00000010
+#define _VAR_TABLE			0x00000020
+#define _VAR_ARRAY			0x00000040
+#define _VAR_CLOSURE		0x00000080
+#define _VAR_CLASS			0x00000100
+#define _VAR_REFERENCE  	0x00000200
+#define _VAR_CONST  		0x00000400
 
 struct SQLocalVarInfo
 {
-	SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0),_scope(0){}
+	SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0),
+        _type(_VAR_ANY),_scope(0) {}
 	SQLocalVarInfo(const SQLocalVarInfo &lvi)
 	{
 		_name=lvi._name;
 		_start_op=lvi._start_op;
 		_end_op=lvi._end_op;
-		_pos=lvi._pos;
-		_scope=lvi._scope;
+		_pos=lvi._pos;
+		_type=lvi._type;
+		_scope=lvi._scope;
 	}
 	SQObjectPtr _name;
 	SQUnsignedInteger _start_op;
 	SQUnsignedInteger _end_op;
 	SQUnsignedInteger _pos;
-	SQInteger _scope;
+	unsigned short _type;
+	unsigned short _scope;
 };
 
 struct SQLineInfo { SQInteger _line;SQInteger _op; };
@@ -66,7 +81,7 @@ struct SQFunctionProto : public CHAINABLE_OBJ
 private:
 	SQFunctionProto(SQSharedState *ss);
 	~SQFunctionProto();
-	
+
 public:
 	static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions,
 		SQInteger nliterals,SQInteger nparameters,
@@ -101,7 +116,7 @@ public:
 		_CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
 		return f;
 	}
-	void Release(){ 
+	void Release(){
 		_DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);
 		_DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);
 		_DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);
@@ -112,7 +127,7 @@ public:
 		this->~SQFunctionProto();
 		sq_vm_free(this,size);
 	}
-	
+
 	const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
 	SQInteger GetLine(SQInstruction *curr);
 	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
@@ -139,7 +154,7 @@ public:
 
 	SQInteger _nparameters;
 	SQObjectPtr *_parameters;
-	
+
 	SQInteger _nfunctions;
 	SQObjectPtr *_functions;
 
@@ -148,7 +163,7 @@ public:
 
 	SQInteger _ndefaultparams;
 	SQInteger *_defaultparams;
-	
+
 	SQInteger _ninstructions;
 	SQInstruction _instructions[1];
 };

+ 16 - 2
squirrel/sqfuncstate.cpp

@@ -351,16 +351,18 @@ bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
 	return false;
 }
 
-SQInteger SQFuncState::PushLocalVariable(const SQObject &name, SQInteger scope)
-{
+SQInteger SQFuncState::PushLocalVariable(const SQObject &name, SQInteger scope, SQInteger type)
+{
 	SQInteger pos=_vlocals.size();
 	SQLocalVarInfo lvi;
 	lvi._name=name;
 	lvi._start_op=GetCurrentPos()+1;
 	lvi._pos=_vlocals.size();
 	lvi._scope=scope;
+	lvi._type=type;
 	_vlocals.push_back(lvi);
 	if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
+printf("%d %d %d %d %d %s\n", __LINE__, scope, type, pos, lvi._start_op, _stringval(lvi._name));
 	return pos;
 }
 
@@ -386,6 +388,18 @@ void SQFuncState::MarkLocalAsOuter(SQInteger pos)
 	_outers++;
 }
 
+SQInteger SQFuncState::FindOuterVariable(const SQObject &name)
+{
+	SQInteger pos=-1;
+	if(_parent) {
+		pos = _parent->GetLocalVariable(name);
+		if(pos == -1) {
+			pos = _parent->FindOuterVariable(name);
+		}
+	}
+	return pos;
+}
+
 SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
 {
 	SQInteger outers = _outervalues.size();

+ 3 - 2
squirrel/sqfuncstate.h

@@ -28,11 +28,12 @@ struct SQFuncState
 	SQInteger GetCurrentPos(){return _instructions.size()-1;}
 	SQInteger GetNumericConstant(const SQInteger cons);
 	SQInteger GetNumericConstant(const SQFloat cons);
-	SQInteger PushLocalVariable(const SQObject &name, SQInteger scope);
+	SQInteger PushLocalVariable(const SQObject &name, SQInteger scope, SQInteger type=_VAR_ANY);
 	void AddParameter(const SQObject &name, SQInteger scope);
 	//void AddOuterValue(const SQObject &name);
 	SQInteger GetLocalVariable(const SQObject &name);
-	void MarkLocalAsOuter(SQInteger pos);
+	void MarkLocalAsOuter(SQInteger pos);
+	SQInteger FindOuterVariable(const SQObject &name);
 	SQInteger GetOuterVariable(const SQObject &name);
 	SQInteger GenerateCode();
 	SQInteger GetStackSize();

+ 7 - 0
squirrel/sqtable.cpp

@@ -116,6 +116,13 @@ bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)
 	}
 	return false;
 }
+bool SQTable::Exists(const SQObjectPtr &key)
+{
+	if(type(key) == OT_NULL)
+		return false;
+	_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
+	return n ? true : false;
+}
 bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
 {
 	assert(type(key) != OT_NULL);

+ 6 - 5
squirrel/sqtable.h

@@ -22,7 +22,7 @@ inline SQHash HashObj(const SQObjectPtr &key)
 	}
 }
 
-struct SQTable : public SQDelegable 
+struct SQTable : public SQDelegable
 {
 private:
 	struct _HashNode
@@ -36,7 +36,7 @@ private:
 	_HashNode *_nodes;
 	SQInteger _numofnodes;
 	SQInteger _usednodes;
-	
+
 ///////////////////////////
 	void AllocNodes(SQInteger nSize);
 	void Rehash(bool force);
@@ -59,7 +59,7 @@ public:
 		for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
 		SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
 	}
-#ifndef NO_GARBAGE_COLLECTOR 
+#ifndef NO_GARBAGE_COLLECTOR
 	void Mark(SQCollectable **chain);
 	SQObjectType GetType() {return OT_TABLE;}
 #endif
@@ -74,19 +74,20 @@ public:
 		return NULL;
 	}
 	bool Get(const SQObjectPtr &key,SQObjectPtr &val);
+	bool Exists(const SQObjectPtr &key);
 	void Remove(const SQObjectPtr &key);
 	bool Set(const SQObjectPtr &key, const SQObjectPtr &val);
 	//returns true if a new slot has been created false if it was already present
 	bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
 	SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
-	
+
 	SQInteger CountUsed(){ return _usednodes;}
 	void Clear();
 	void Release()
 	{
 		sq_delete(this, SQTable);
 	}
-	
+
 };
 
 #endif //_SQTABLE_H_

+ 1 - 1
squirrel/sqvm.cpp

@@ -1312,7 +1312,7 @@ bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr
 	case OT_INSTANCE:
 		if(_instance(self)->Set(key,val)) return true;
 		break;
-	case OT_ARRAY:
+	case OT_ARRAY:
 		if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }
 		if(!_array(self)->Set(tointeger(key),val)) {
 			Raise_IdxError(key);