Преглед на файлове

Added constexpr and inline C++ keywords
Add a check in SharedState to not call OT_NULL.

mingodad преди 9 години
родител
ревизия
6b596522e2
променени са 4 файла, в които са добавени 81 реда и са изтрити 23 реда
  1. 72 21
      SquiLu/squirrel/sqcompiler.cpp
  2. 2 0
      SquiLu/squirrel/sqcompiler.h
  3. 2 0
      SquiLu/squirrel/sqlexer.cpp
  4. 5 2
      SquiLu/squirrel/sqstate.cpp

+ 72 - 21
SquiLu/squirrel/sqcompiler.cpp

@@ -184,6 +184,10 @@ public:
 		va_end(vl);
 	}
 
+	bool CheckNameIsType(const SQObject &name){
+	    return _table(_type_names)->Exists(name);
+	}
+
 	bool CheckTypeName(const SQObject &name, bool addIfNotExists=false){
 	    bool found = _table(_type_names)->Exists(name);
 	    if(addIfNotExists && !found) {
@@ -679,6 +683,8 @@ public:
 			}
 			break;
 
+		case TK_INLINE: //accept and ignore
+		case TK_CONSTEXPR: //accept and ignore
 		case TK_FRIEND:
 		case TK_VOLATILE:
 		    Lex();
@@ -1310,7 +1316,7 @@ public:
 		case TK_FUNCTION: FunctionExp(_token);break;
 		case _SC('@'): FunctionExp(_token,true);break;
 		case TK_STRUCT:
-		case TK_CLASS: Lex(); ClassExp();break;
+		case TK_CLASS: Lex(); ClassExp(NULL);break;
 		case _SC('-'):
 			Lex();
 			switch(_token) {
@@ -1415,16 +1421,25 @@ public:
 		 SQInteger closure = _fs->PopTarget();
          _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
 	}
-	void CheckClassMemberExists(SQObjectPtr &member_names, SQObject &name)
+	void AddClassMemberExists(SQObjectPtr &member_names, SQObject &name)
+	{
+        SQObjectPtr oname = name, otrue = true;
+        _table(member_names)->NewSlot(oname, otrue);
+	}
+	void CheckClassMemberExists(SQObjectPtr &member_names, SQObject &name, bool addIfNotExists=true)
 	{
         if(_table(member_names)->Exists(name))
         {
             Error(_SC("class already has a member named: %s"), _stringval(name));
         }
-        SQObjectPtr oname = name, otrue = true;
-        _table(member_names)->NewSlot(oname, otrue);
+        if(addIfNotExists) AddClassMemberExists(member_names, name);
+	}
+	void CheckClassMemberExists(SQObjectPtr &member_names, const SQChar *name)
+	{
+	    SQObject oname = _fs->CreateString(name);
+	    CheckClassMemberExists(member_names, oname);
 	}
-	void ParseTableOrClass(SQInteger separator,SQInteger terminator)
+	void ParseTableOrClass(SQInteger separator,SQInteger terminator, SQObjectPtr *class_name=NULL)
 	{
 	    SQObjectPtr member_names;
 		SQInteger saved_tok, tpos = _fs->GetCurrentPos(),nkeys = 0;
@@ -1438,6 +1453,7 @@ public:
 		while(_token != terminator) {
 			bool hasattrs = false;
 			bool isstatic = false;
+			bool cppDestructor = false;
 			//bool isvirtual = false;
 			//bool isprivate = false;
 			const SQChar *membertypename = 0;
@@ -1496,12 +1512,23 @@ function_params_decl:
 				SQInteger next_token = _SC('=');
 				if(isClass)
                 {
-                    CheckClassMemberExists(member_names, obj_id);
+                    CheckClassMemberExists(member_names, obj_id, false);
                     addClassMember = 0;
                     switch(_token)
                     {
                         case _SC('('): //C/C++ style function declaration
                             Lex();
+                            if(class_name)
+                            {
+                                //printf("ClassMember %d : %s : %s\n", (int)cppDestructor, _stringval(*class_name), _stringval(obj_id));
+                                if(memcmp(_stringval(*class_name), _stringval(obj_id), _string(*class_name)->_len) == 0)
+                                {
+                                    //C++ style constructor/destructor declaration
+                                    obj_id = _fs->CreateString(cppDestructor ? _SC("destructor") : _SC("constructor"));
+                                    cppDestructor = false;
+                                }
+                            }
+                            AddClassMemberExists(member_names, obj_id);
                             goto function_params_decl;
                             break;
                         case _SC(':'): //typescript field with type annotation
@@ -1519,9 +1546,17 @@ function_params_decl:
                             Lex();
                             ++addClassMember;
                             break;
+                        case TK_IDENTIFIER: //if 2 identifier found the first should be a type
+                            if(CheckNameIsType(obj_id)) //Struct/Class/Typedef names
+                            {
+                                membertypename = _stringval(obj_id);
+                                goto member_has_type;
+                            }
+
                     }
                     if(addClassMember)
                     {
+                        AddClassMemberExists(member_names, obj_id);
                         _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(obj_id));
                         _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(), 1);
                         break;
@@ -1543,6 +1578,20 @@ function_params_decl:
                     Lex();
                     goto member_has_type;
                 }
+            case _SC('~'): //C++ style destructor declaration
+                if(isClass)
+                {
+                    cppDestructor = true;
+                    Lex();
+                    goto member_has_type;
+                    continue;
+                }
+            case TK_CONSTEXPR:
+                if(isClass)
+                {
+                    Lex();
+                    continue;
+                }
                 //else fallthrough
 			default :
 				ErrorIfNotToken(TK_IDENTIFIER);
@@ -1985,24 +2034,25 @@ if(color == "yellow"){
 	void ClassStatement()
 	{
 		SQExpState es;
+		SQObjectPtr class_name;
 		Lex();
 		if(_token == TK_IDENTIFIER) {
-		    SQObjectPtr str = SQString::Create(_ss(_vm), _lex._svalue);
-		    CheckGlobalName(str, true);
-            CheckTypeName(str, true); //to allow C/C++ style instance declarations
+		    class_name = SQString::Create(_ss(_vm), _lex._svalue);
+		    CheckGlobalName(class_name, true);
+            CheckTypeName(class_name, true); //to allow C/C++ style instance declarations
 		}
 		es = _es;
 		_es.donot_get = true;
 		PrefixedExpr();
+        if(_token == _SC(';')) //class forward declaration
+        {
+            //return;
+        }
 		if(_es.etype == EXPR) {
 			Error(_SC("invalid class name"));
 		}
 		else if(_es.etype == OBJECT || _es.etype == BASE) {
-            if(_token == _SC(';')) //class forward declaration
-            {
-
-            }
-			ClassExp();
+			ClassExp(&class_name);
 			EmitDerefOp(_OP_NEWSLOT);
 			_fs->PopTarget();
 		}
@@ -2170,7 +2220,7 @@ error:
 		CreateFunction(dummy, lambda ? eFunctionType_lambda : eFunctionType_anonymous);
 		_fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
 	}
-	void ClassExp()
+	void ClassExp(SQObjectPtr *class_name)
 	{
 		SQInteger base = -1;
 		SQInteger attrs = -1;
@@ -2202,7 +2252,7 @@ error:
 		if(attrs != -1) _fs->PopTarget();
 		if(base != -1) _fs->PopTarget();
 		_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);
-		ParseTableOrClass(_SC(';'),_SC('}'));
+		ParseTableOrClass(_SC(';'),_SC('}'), class_name);
 	}
 	void DeleteExpr()
 	{
@@ -2280,16 +2330,17 @@ error:
 				break;
 			}
 			else {
-				if(_token == _SC('&')){
-					is_reference = 1;
-					Lex();
-				}
+				if(_token == TK_CONST) Lex(); //C/C++ const parameters
 				switch(_token)
 				{
-				    CASE_TK_LOCAL_TYPES: //accept C/C++ type parameter declarations
+                CASE_TK_LOCAL_TYPES: //accept C/C++ type parameter declarations
 				        param_type_name = _lex.GetTokenName(_token);
 				        Lex();
 				}
+				if(_token == _SC('&')){
+					is_reference = 1;
+					Lex();
+				}
 				paramname = Expect(TK_IDENTIFIER);
 				funcstate->AddParameter(paramname, _scope.nested+1, is_reference ? _VAR_REFERENCE : _VAR_ANY);
 				if(param_type_name)

+ 2 - 0
SquiLu/squirrel/sqcompiler.h

@@ -23,6 +23,7 @@ struct SQVM;
     ENUM_TK(CLASS)\
     ENUM_TK(CLONE)\
     ENUM_TK(CONST)\
+    ENUM_TK(CONSTEXPR)\
     ENUM_TK(COMMENT_BLOCK)\
     ENUM_TK(COMMENT_LINE)\
     ENUM_TK(CONSTRUCTOR)\
@@ -53,6 +54,7 @@ struct SQVM;
     ENUM_TK(IF)\
     ENUM_TK(IGNORE)\
     ENUM_TK(IN)\
+    ENUM_TK(INLINE)\
     ENUM_TK(INSTANCEOF)\
     ENUM_TK(INTEGER)\
     ENUM_TK(LE)\

+ 2 - 0
SquiLu/squirrel/sqlexer.cpp

@@ -68,6 +68,7 @@ SQTable * SQLexer::GetKeywords()
 	ADD_KEYWORD(clone, TK_CLONE);
 	ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
 	ADD_KEYWORD(const,TK_CONST);
+	ADD_KEYWORD(constexpr,TK_CONSTEXPR);
 	ADD_KEYWORD(continue, TK_CONTINUE);
 	ADD_KEYWORD(declare, TK_DECLARE);
 	ADD_KEYWORD(default, TK_DEFAULT);
@@ -94,6 +95,7 @@ SQTable * SQLexer::GetKeywords()
 	ADD_KEYWORD(int64_t, TK_LOCAL_INT64_T);
 	ADD_KEYWORD(int8_t, TK_LOCAL_INT8_T);
 	ADD_KEYWORD(in, TK_IN);
+	ADD_KEYWORD(inline, TK_INLINE);
 	ADD_KEYWORD(int_t, TK_LOCAL_INT_T);
 	ADD_KEYWORD(let, TK_LOCAL);
 	ADD_KEYWORD(__LINE__,TK___LINE__);

+ 5 - 2
SquiLu/squirrel/sqstate.cpp

@@ -182,8 +182,11 @@ SQSharedState::~SQSharedState()
 		_systemstrings->back().Null();
 		_systemstrings->pop_back();
 	}
-	_thread(_root_vm)->Finalize();
-	_root_vm.Null();
+	if(type(_root_vm) != OT_NULL)
+    {
+        _thread(_root_vm)->Finalize();
+        _root_vm.Null();
+    }
 	_table_default_delegate.Null();
 	_array_default_delegate.Null();
 	_string_default_delegate.Null();