int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &name, asCDataType &type) { numErrors = 0; numWarnings = 0; preMessage.isSet = false; if( dt ) { // Verify that the object type exist if( dt->GetObjectType() == 0 ) return asINVALID_OBJECT; } // Check property declaration and type asCScriptCode source; source.SetCode(TXT_PROPERTY, decl, true); asCParser parser(this); int r = parser.ParsePropertyDeclaration(&source); if( r < 0 ) return asINVALID_DECLARATION; // Get data type and property name asCScriptNode *dataType = parser.GetScriptNode()->firstChild; asCScriptNode *nameNode = dataType->next; type = CreateDataTypeFromNode(dataType, &source); name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength); // Verify property name if( dt ) if( CheckNameConflictMember(*dt, name.AddressOf(), nameNode, &source) < 0 ) return asINVALID_NAME; else if( CheckNameConflict(name.AddressOf(), nameNode, &source) < 0 ) return asINVALID_NAME; if( numErrors > 0 ) return asINVALID_DECLARATION; return asSUCCESS; }
int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file) { asCScriptNode *n = node->firstChild; GETSTRING(name, &file->code[n->tokenPos], n->tokenLength); int r, c; file->ConvertPosToRowCol(n->tokenPos, &r, &c); CheckNameConflict(name.AddressOf(), n, file); sClassDeclaration *decl = new sClassDeclaration; classDeclarations.PushLast(decl); decl->name = name; decl->script = file; decl->validState = 0; decl->node = node; asCObjectType *st = new asCObjectType(engine); st->arrayType = 0; st->flags = asOBJ_CLASS_CDA | asOBJ_SCRIPT_STRUCT; st->size = sizeof(asCScriptStruct); st->name = name; st->tokenType = ttIdentifier; module->classTypes.PushLast(st); engine->classTypes.PushLast(st); st->refCount++; decl->objType = st; // Use the default script class behaviours st->beh.construct = engine->scriptTypeBehaviours.beh.construct; st->beh.constructors.PushLast(st->beh.construct); st->beh.addref = engine->scriptTypeBehaviours.beh.addref; st->beh.release = engine->scriptTypeBehaviours.beh.release; st->beh.copy = engine->scriptTypeBehaviours.beh.copy; st->beh.operators.PushLast(ttAssignment); st->beh.operators.PushLast(st->beh.copy); return 0; }
int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file) { // What data type is it? asCDataType type = CreateDataTypeFromNode(node->firstChild, file); if( type.GetSizeOnStackDWords() == 0 || (type.IsObject() && !type.IsObjectHandle() && type.GetSizeInMemoryBytes() == 0) ) { asCString str; // TODO: Change to "'type' cannot be declared as variable" str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format().AddressOf()); int r, c; file->ConvertPosToRowCol(node->tokenPos, &r, &c); WriteError(file->name.AddressOf(), str.AddressOf(), r, c); } asCScriptNode *n = node->firstChild->next; while( n ) { // Verify that the name isn't taken GETSTRING(name, &file->code[n->tokenPos], n->tokenLength); CheckNameConflict(name.AddressOf(), n, file); // Register the global variable sGlobalVariableDescription *gvar = new sGlobalVariableDescription; globVariables.PushLast(gvar); gvar->script = file; gvar->name = name; gvar->isCompiled = false; gvar->datatype = type; // TODO: Give error message if wrong assert(!gvar->datatype.IsReference()); // Allocate space on the global memory stack gvar->index = module->AllocGlobalMemory(gvar->datatype.GetSizeOnStackDWords()); gvar->node = 0; if( n->next && (n->next->nodeType == snAssignment || n->next->nodeType == snArgList || n->next->nodeType == snInitList ) ) { gvar->node = n->next; n->next->DisconnectParent(); } // Add script variable to engine asCProperty *prop = new asCProperty; prop->index = gvar->index; prop->name = name; prop->type = gvar->datatype; module->scriptGlobals.PushLast(prop); gvar->property = prop; n = n->next; } delete node; return 0; }
int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCScriptCode *file) { // Find name asCScriptNode *f = node->firstChild; asCScriptNode *n = f->firstChild->next->next; // Check for name conflicts GETSTRING(name, &file->code[n->tokenPos], n->tokenLength); CheckNameConflict(name.AddressOf(), n, file); // Initialize a script function object for registration asCDataType returnType; returnType = CreateDataTypeFromNode(f->firstChild, file); returnType = ModifyDataTypeFromNode(returnType, f->firstChild->next, file, 0, 0); asCArray<asCDataType> parameterTypes; asCArray<int> inOutFlags; n = n->next->firstChild; while( n ) { int inOutFlag; asCDataType type = CreateDataTypeFromNode(n, file); type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0); // Store the parameter type n = n->next->next; parameterTypes.PushLast(type); inOutFlags.PushLast(inOutFlag); // Move to next parameter if( n && n->nodeType == snIdentifier ) n = n->next; } // Check that the same function hasn't been registered already asCArray<int> funcs; GetFunctionDescriptions(name.AddressOf(), funcs); if( funcs.GetLength() ) { for( asUINT n = 0; n < funcs.GetLength(); ++n ) { asCScriptFunction *func = GetFunctionDescription(funcs[n]); // TODO: Isn't the name guaranteed to be equal, because of GetFunctionDescriptions()? if( name == func->name && parameterTypes.GetLength() == func->parameterTypes.GetLength() ) { bool match = true; for( asUINT p = 0; p < parameterTypes.GetLength(); ++p ) { if( parameterTypes[p] != func->parameterTypes[p] ) { match = false; break; } } if( match ) { int r, c; file->ConvertPosToRowCol(node->tokenPos, &r, &c); WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c); break; } } } } // Read the module name as well n = node->firstChild->next; int moduleNameString = module->AddConstantString(&file->code[n->tokenPos+1], n->tokenLength-2); delete node; // Register the function module->AddImportedFunction(importID, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), moduleNameString); return 0; }
int asCBuilder::RegisterScriptFunction(int funcID, asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface) { // Find name bool isConstructor = false; asCScriptNode *n = 0; if( node->firstChild->nodeType == snDataType ) n = node->firstChild->next->next; else { n = node->firstChild; isConstructor = true; } // Check for name conflicts GETSTRING(name, &file->code[n->tokenPos], n->tokenLength); if( !isConstructor ) CheckNameConflict(name.AddressOf(), n, file); else { // Verify that the name of the function is the same as the class if( name != objType->name ) { int r, c; file->ConvertPosToRowCol(n->tokenPos, &r, &c); WriteError(file->name.AddressOf(), TXT_CONSTRUCTOR_NAME_ERROR, r, c); } } if( !isInterface ) { sFunctionDescription *func = new sFunctionDescription; functions.PushLast(func); func->script = file; func->node = node; func->name = name; func->objType = objType; func->funcId = funcID; } // Initialize a script function object for registration asCDataType returnType = asCDataType::CreatePrimitive(ttVoid, false); if( !isConstructor ) { returnType = CreateDataTypeFromNode(node->firstChild, file); returnType = ModifyDataTypeFromNode(returnType, node->firstChild->next, file, 0, 0); module->RefConfigGroupForObjectType(returnType.GetObjectType()); } asCArray<asCDataType> parameterTypes; asCArray<int> inOutFlags; n = n->next->firstChild; while( n ) { int inOutFlag; asCDataType type = CreateDataTypeFromNode(n, file); type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0); module->RefConfigGroupForObjectType(type.GetObjectType()); // Store the parameter type parameterTypes.PushLast(type); inOutFlags.PushLast(inOutFlag); // Move to next parameter n = n->next->next; if( n && n->nodeType == snIdentifier ) n = n->next; } // Check that the same function hasn't been registered already asCArray<int> funcs; GetFunctionDescriptions(name.AddressOf(), funcs); if( funcs.GetLength() ) { for( asUINT n = 0; n < funcs.GetLength(); ++n ) { asCScriptFunction *func = GetFunctionDescription(funcs[n]); if( parameterTypes.GetLength() == func->parameterTypes.GetLength() ) { bool match = true; for( asUINT p = 0; p < parameterTypes.GetLength(); ++p ) { if( parameterTypes[p] != func->parameterTypes[p] ) { match = false; break; } } if( match ) { int r, c; file->ConvertPosToRowCol(node->tokenPos, &r, &c); WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c); break; } } } } // Register the function module->AddScriptFunction(file->idx, funcID, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), isInterface, objType); if( objType ) { if( isConstructor ) { if( parameterTypes.GetLength() == 0 ) { // Overload the default constructor objType->beh.construct = funcID; objType->beh.constructors[0] = funcID; } else objType->beh.constructors.PushLast(funcID); } else objType->methods.PushLast(funcID); } // We need to delete the node already if this is an interface method if( isInterface && node ) delete node; return 0; }
int asCBuilder::RegisterScriptFunction(int funcID, asCScriptNode *node, asCScriptCode *file) { // Find name asCScriptNode *n = node->firstChild->next->next; // Check for name conflicts GETSTRING(name, &file->code[n->tokenPos], n->tokenLength); CheckNameConflict(name.AddressOf(), n, file); sFunctionDescription *func = new sFunctionDescription; functions.PushLast(func); func->script = file; func->node = node; func->name = name; // Initialize a script function object for registration asCDataType returnType; returnType = CreateDataTypeFromNode(node->firstChild, file); returnType = ModifyDataTypeFromNode(returnType, node->firstChild->next, 0, 0); module->RefConfigGroupForObjectType(returnType.GetObjectType()); asCArray<asCDataType> parameterTypes; asCArray<int> inOutFlags; n = n->next->firstChild; while( n ) { int inOutFlag; asCDataType type = CreateDataTypeFromNode(n, file); type = ModifyDataTypeFromNode(type, n->next, &inOutFlag, 0); module->RefConfigGroupForObjectType(type.GetObjectType()); // Store the parameter type parameterTypes.PushLast(type); inOutFlags.PushLast(inOutFlag); // Move to next parameter n = n->next->next; if( n && n->nodeType == snIdentifier ) n = n->next; } // Check that the same function hasn't been registered already asCArray<int> funcs; GetFunctionDescriptions(name.AddressOf(), funcs); if( funcs.GetLength() ) { for( asUINT n = 0; n < funcs.GetLength(); ++n ) { asCScriptFunction *func = GetFunctionDescription(funcs[n]); if( parameterTypes.GetLength() == func->parameterTypes.GetLength() ) { bool match = true; for( asUINT p = 0; p < parameterTypes.GetLength(); ++p ) { if( parameterTypes[p] != func->parameterTypes[p] ) { match = false; break; } } if( match ) { int r, c; file->ConvertPosToRowCol(node->tokenPos, &r, &c); WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c); break; } } } } // Register the function module->AddScriptFunction(file->idx, funcID, func->name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), parameterTypes.GetLength()); return 0; }