00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "as_config.h"
00040 #include "as_builder.h"
00041 #include "as_parser.h"
00042 #include "as_compiler.h"
00043 #include "as_tokendef.h"
00044 #include "as_string_util.h"
00045 #include "as_outputbuffer.h"
00046 #include "as_texts.h"
00047 #include "as_scriptobject.h"
00048
00049 BEGIN_AS_NAMESPACE
00050
00051 asCBuilder::asCBuilder(asCScriptEngine *engine, asCModule *module)
00052 {
00053 this->engine = engine;
00054 this->module = module;
00055 }
00056
00057 asCBuilder::~asCBuilder()
00058 {
00059 asUINT n;
00060
00061
00062 for( n = 0; n < functions.GetLength(); n++ )
00063 {
00064 if( functions[n] )
00065 {
00066 if( functions[n]->node )
00067 {
00068 functions[n]->node->Destroy(engine);
00069 }
00070
00071 asDELETE(functions[n],sFunctionDescription);
00072 }
00073
00074 functions[n] = 0;
00075 }
00076
00077
00078 for( n = 0; n < globVariables.GetLength(); n++ )
00079 {
00080 if( globVariables[n] )
00081 {
00082 if( globVariables[n]->nextNode )
00083 {
00084 globVariables[n]->nextNode->Destroy(engine);
00085 }
00086
00087 asDELETE(globVariables[n],sGlobalVariableDescription);
00088 globVariables[n] = 0;
00089 }
00090 }
00091
00092
00093 for( n = 0; n < scripts.GetLength(); n++ )
00094 {
00095 if( scripts[n] )
00096 {
00097 asDELETE(scripts[n],asCScriptCode);
00098 }
00099
00100 scripts[n] = 0;
00101 }
00102
00103
00104 for( n = 0; n < classDeclarations.GetLength(); n++ )
00105 {
00106 if( classDeclarations[n] )
00107 {
00108 if( classDeclarations[n]->node )
00109 {
00110 classDeclarations[n]->node->Destroy(engine);
00111 }
00112
00113 asDELETE(classDeclarations[n],sClassDeclaration);
00114 classDeclarations[n] = 0;
00115 }
00116 }
00117
00118 for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
00119 {
00120 if( interfaceDeclarations[n] )
00121 {
00122 if( interfaceDeclarations[n]->node )
00123 {
00124 interfaceDeclarations[n]->node->Destroy(engine);
00125 }
00126
00127 asDELETE(interfaceDeclarations[n],sClassDeclaration);
00128 interfaceDeclarations[n] = 0;
00129 }
00130 }
00131
00132 for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
00133 {
00134 if( namedTypeDeclarations[n] )
00135 {
00136 if( namedTypeDeclarations[n]->node )
00137 {
00138 namedTypeDeclarations[n]->node->Destroy(engine);
00139 }
00140
00141 asDELETE(namedTypeDeclarations[n],sClassDeclaration);
00142 namedTypeDeclarations[n] = 0;
00143 }
00144 }
00145 }
00146
00147 int asCBuilder::AddCode(const char *name, const char *code, int codeLength, int lineOffset, int sectionIdx, bool makeCopy)
00148 {
00149 asCScriptCode *script = asNEW(asCScriptCode);
00150 script->SetCode(name, code, codeLength, makeCopy);
00151 script->lineOffset = lineOffset;
00152 script->idx = sectionIdx;
00153 scripts.PushLast(script);
00154
00155 return 0;
00156 }
00157
00158 int asCBuilder::Build()
00159 {
00160 numErrors = 0;
00161 numWarnings = 0;
00162 preMessage.isSet = false;
00163
00164 ParseScripts();
00165 CompileClasses();
00166 CompileGlobalVariables();
00167 CompileFunctions();
00168
00169 if( numErrors > 0 )
00170 return asERROR;
00171
00172 return asSUCCESS;
00173 }
00174
00175 int asCBuilder::BuildString(const char *string, asCContext *ctx)
00176 {
00177 numErrors = 0;
00178 numWarnings = 0;
00179 preMessage.isSet = false;
00180
00181
00182 asCScriptCode *script = asNEW(asCScriptCode);
00183 script->SetCode(TXT_EXECUTESTRING, string, true);
00184 script->lineOffset = -1;
00185 scripts.PushLast(script);
00186
00187
00188 asCParser parser(this);
00189 if( parser.ParseScript(scripts[0]) >= 0 )
00190 {
00191
00192 asCScriptNode *node = parser.GetScriptNode();
00193 node = node->firstChild;
00194 if( node->nodeType == snFunction )
00195 {
00196 node->DisconnectParent();
00197
00198 sFunctionDescription *func = asNEW(sFunctionDescription);
00199 functions.PushLast(func);
00200
00201 func->script = scripts[0];
00202 func->node = node;
00203 func->name = "";
00204 }
00205 else
00206 {
00207
00208 asASSERT(false);
00209 }
00210 }
00211
00212 if( numErrors == 0 )
00213 {
00214
00215 asCCompiler compiler(engine);
00216 asCScriptFunction *execfunc = asNEW(asCScriptFunction)(engine,module);
00217 if( compiler.CompileFunction(this, functions[0]->script, functions[0]->node, execfunc) >= 0 )
00218 {
00219 execfunc->id = asFUNC_STRING;
00220
00221 ctx->SetExecuteStringFunction(execfunc);
00222 }
00223 else
00224 {
00225 asDELETE(execfunc,asCScriptFunction);
00226 }
00227 }
00228
00229 if( numErrors > 0 )
00230 return asERROR;
00231
00232 return asSUCCESS;
00233 }
00234
00235 void asCBuilder::ParseScripts()
00236 {
00237 asCArray<asCParser*> parsers((int)scripts.GetLength());
00238
00239
00240 asUINT n = 0;
00241 for( n = 0; n < scripts.GetLength(); n++ )
00242 {
00243 asCParser *parser = asNEW(asCParser)(this);
00244 parsers.PushLast(parser);
00245
00246
00247 parser->ParseScript(scripts[n]);
00248 }
00249
00250 if( numErrors == 0 )
00251 {
00252
00253 for( n = 0; n < scripts.GetLength(); n++ )
00254 {
00255 asCScriptNode *node = parsers[n]->GetScriptNode();
00256
00257
00258 node = node->firstChild;
00259 while( node )
00260 {
00261 asCScriptNode *next = node->next;
00262 if( node->nodeType == snClass )
00263 {
00264 node->DisconnectParent();
00265 RegisterClass(node, scripts[n]);
00266 }
00267 else if( node->nodeType == snInterface )
00268 {
00269 node->DisconnectParent();
00270 RegisterInterface(node, scripts[n]);
00271 }
00272
00273 else if( node->nodeType == snEnum )
00274 {
00275 node->DisconnectParent();
00276 RegisterEnum(node, scripts[n]);
00277 }
00278
00279 else if( node->nodeType == snTypedef )
00280 {
00281 node->DisconnectParent();
00282 RegisterTypedef(node, scripts[n]);
00283 }
00284
00285 node = next;
00286 }
00287 }
00288
00289
00290 for( n = 0; n < interfaceDeclarations.GetLength(); n++ )
00291 {
00292 sClassDeclaration *decl = interfaceDeclarations[n];
00293
00294 asCScriptNode *node = decl->node->firstChild->next;
00295 while( node )
00296 {
00297 asCScriptNode *next = node->next;
00298 if( node->nodeType == snFunction )
00299 {
00300 node->DisconnectParent();
00301 RegisterScriptFunction(engine->GetNextScriptFunctionId(), node, decl->script, decl->objType, true);
00302 }
00303
00304 node = next;
00305 }
00306 }
00307
00308
00309
00310 module->ResolveInterfaceIds();
00311
00312
00313 for( n = 0; n < classDeclarations.GetLength(); n++ )
00314 {
00315 sClassDeclaration *decl = classDeclarations[n];
00316
00317 asCScriptNode *node = decl->node->firstChild->next;
00318
00319
00320 while( node && node->nodeType == snIdentifier )
00321 node = node->next;
00322
00323 while( node )
00324 {
00325 asCScriptNode *next = node->next;
00326 if( node->nodeType == snFunction )
00327 {
00328 node->DisconnectParent();
00329 RegisterScriptFunction(engine->GetNextScriptFunctionId(), node, decl->script, decl->objType);
00330 }
00331
00332 node = next;
00333 }
00334
00335
00336 if( decl->objType->beh.construct == engine->scriptTypeBehaviours.beh.construct )
00337 {
00338 AddDefaultConstructor(decl->objType, decl->script);
00339 }
00340 }
00341
00342
00343 for( n = 0; n < scripts.GetLength(); n++ )
00344 {
00345
00346 asCScriptNode *node = parsers[n]->GetScriptNode();
00347 node = node->firstChild;
00348 while( node )
00349 {
00350 asCScriptNode *next = node->next;
00351 node->DisconnectParent();
00352
00353 if( node->nodeType == snFunction )
00354 {
00355 RegisterScriptFunction(engine->GetNextScriptFunctionId(), node, scripts[n], 0, false, true);
00356 }
00357 else if( node->nodeType == snGlobalVar )
00358 {
00359 RegisterGlobalVar(node, scripts[n]);
00360 }
00361 else if( node->nodeType == snImport )
00362 {
00363 RegisterImportedFunction(module->GetNextImportedFunctionId(), node, scripts[n]);
00364 }
00365 else
00366 {
00367
00368 int r, c;
00369 scripts[n]->ConvertPosToRowCol(node->tokenPos, &r, &c);
00370
00371 WriteWarning(scripts[n]->name.AddressOf(), TXT_UNUSED_SCRIPT_NODE, r, c);
00372
00373 node->Destroy(engine);
00374 }
00375
00376 node = next;
00377 }
00378 }
00379 }
00380
00381 for( n = 0; n < parsers.GetLength(); n++ )
00382 {
00383 asDELETE(parsers[n],asCParser);
00384 }
00385 }
00386
00387 void asCBuilder::CompileFunctions()
00388 {
00389
00390 for( asUINT n = 0; n < functions.GetLength(); n++ )
00391 {
00392 if( functions[n] == 0 ) continue;
00393
00394 asCCompiler compiler(engine);
00395 asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
00396
00397 if( functions[n]->node )
00398 {
00399 int r, c;
00400 functions[n]->script->ConvertPosToRowCol(functions[n]->node->tokenPos, &r, &c);
00401
00402 asCString str = func->GetDeclarationStr();
00403 str.Format(TXT_COMPILING_s, str.AddressOf());
00404 WriteInfo(functions[n]->script->name.AddressOf(), str.AddressOf(), r, c, true);
00405
00406 compiler.CompileFunction(this, functions[n]->script, functions[n]->node, func);
00407
00408 preMessage.isSet = false;
00409 }
00410 else
00411 {
00412
00413
00414 asASSERT( functions[n]->name == functions[n]->objType->name );
00415 compiler.CompileDefaultConstructor(this, functions[n]->script, func);
00416 }
00417 }
00418 }
00419
00420 int asCBuilder::ParseDataType(const char *datatype, asCDataType *result)
00421 {
00422 numErrors = 0;
00423 numWarnings = 0;
00424 preMessage.isSet = false;
00425
00426 asCScriptCode source;
00427 source.SetCode("", datatype, true);
00428
00429 asCParser parser(this);
00430 int r = parser.ParseDataType(&source);
00431 if( r < 0 )
00432 return asINVALID_TYPE;
00433
00434
00435 asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
00436
00437 *result = CreateDataTypeFromNode(dataType, &source, true);
00438
00439 if( numErrors > 0 )
00440 return asINVALID_TYPE;
00441
00442 return asSUCCESS;
00443 }
00444
00445 int asCBuilder::ParseTemplateDecl(const char *decl, asCString *name, asCString *subtypeName)
00446 {
00447 numErrors = 0;
00448 numWarnings = 0;
00449 preMessage.isSet = false;
00450
00451 asCScriptCode source;
00452 source.SetCode("", decl, true);
00453
00454 asCParser parser(this);
00455 int r = parser.ParseTemplateDecl(&source);
00456 if( r < 0 )
00457 return asINVALID_TYPE;
00458
00459
00460 asCScriptNode *node = parser.GetScriptNode()->firstChild;
00461
00462 name->Assign(&decl[node->tokenPos], node->tokenLength);
00463 node = node->next;
00464 subtypeName->Assign(&decl[node->tokenPos], node->tokenLength);
00465
00466
00467
00468 if( numErrors > 0 )
00469 return asINVALID_DECLARATION;
00470
00471 return asSUCCESS;
00472 }
00473
00474 int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &name, asCDataType &type)
00475 {
00476 numErrors = 0;
00477 numWarnings = 0;
00478 preMessage.isSet = false;
00479
00480 if( dt )
00481 {
00482
00483 if( dt->GetObjectType() == 0 )
00484 return asINVALID_OBJECT;
00485 }
00486
00487
00488 asCScriptCode source;
00489 source.SetCode(TXT_PROPERTY, decl, true);
00490
00491 asCParser parser(this);
00492 int r = parser.ParsePropertyDeclaration(&source);
00493 if( r < 0 )
00494 return asINVALID_DECLARATION;
00495
00496
00497 asCScriptNode *dataType = parser.GetScriptNode()->firstChild;
00498
00499 asCScriptNode *nameNode = dataType->next;
00500
00501 type = CreateDataTypeFromNode(dataType, &source);
00502 name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength);
00503
00504
00505 if( dt )
00506 {
00507 if( CheckNameConflictMember(*dt, name.AddressOf(), nameNode, &source) < 0 )
00508 return asNAME_TAKEN;
00509 }
00510 else
00511 {
00512 if( CheckNameConflict(name.AddressOf(), nameNode, &source) < 0 )
00513 return asNAME_TAKEN;
00514 }
00515
00516 if( numErrors > 0 )
00517 return asINVALID_DECLARATION;
00518
00519 return asSUCCESS;
00520 }
00521
00522 asCObjectProperty *asCBuilder::GetObjectProperty(asCDataType &obj, const char *prop)
00523 {
00524 asASSERT(obj.GetObjectType() != 0);
00525
00526
00527
00528 asCArray<asCObjectProperty *> &props = obj.GetObjectType()->properties;
00529 for( asUINT n = 0; n < props.GetLength(); n++ )
00530 if( props[n]->name == prop )
00531 return props[n];
00532
00533 return 0;
00534 }
00535
00536 asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, bool *isCompiled, bool *isPureConstant, asQWORD *constantValue)
00537 {
00538 asUINT n;
00539
00540 if( isCompiled ) *isCompiled = true;
00541 if( isPureConstant ) *isPureConstant = false;
00542
00543
00544
00545 asCArray<asCGlobalProperty *> *props = &(engine->registeredGlobalProps);
00546 for( n = 0; n < props->GetLength(); ++n )
00547 if( (*props)[n] && (*props)[n]->name == prop )
00548 {
00549 if( module )
00550 {
00551
00552 asCConfigGroup *group = engine->FindConfigGroupForGlobalVar((*props)[n]->id);
00553 if( !group || group->HasModuleAccess(module->name.AddressOf()) )
00554 return (*props)[n];
00555 }
00556 else
00557 {
00558
00559 return (*props)[n];
00560 }
00561 }
00562
00563
00564
00565 asCArray<sGlobalVariableDescription *> *gvars = &globVariables;
00566 for( n = 0; n < gvars->GetLength(); ++n )
00567 {
00568 if( (*gvars)[n] && (*gvars)[n]->name == prop )
00569 {
00570 if( isCompiled ) *isCompiled = (*gvars)[n]->isCompiled;
00571
00572 if( isPureConstant ) *isPureConstant = (*gvars)[n]->isPureConstant;
00573 if( constantValue ) *constantValue = (*gvars)[n]->constantValue;
00574
00575 return (*gvars)[n]->property;
00576 }
00577 }
00578
00579
00580
00581 if( module )
00582 {
00583 props = &module->scriptGlobals;
00584 for( n = 0; n < props->GetLength(); ++n )
00585 if( (*props)[n]->name == prop )
00586 return (*props)[n];
00587 }
00588
00589 return 0;
00590 }
00591
00592 int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle)
00593 {
00594 numErrors = 0;
00595 numWarnings = 0;
00596 preMessage.isSet = false;
00597
00598 asCScriptCode source;
00599 source.SetCode(TXT_SYSTEM_FUNCTION, decl, true);
00600
00601 asCParser parser(this);
00602 int r = parser.ParseFunctionDefinition(&source);
00603 if( r < 0 )
00604 return asINVALID_DECLARATION;
00605
00606 asCScriptNode *node = parser.GetScriptNode();
00607
00608
00609 asCScriptNode *n = node->firstChild->next->next;
00610 func->name.Assign(&source.code[n->tokenPos], n->tokenLength);
00611
00612
00613 bool autoHandle;
00614
00615
00616 func->returnType = CreateDataTypeFromNode(node->firstChild, &source, true, objType);
00617 func->returnType = ModifyDataTypeFromNode(func->returnType, node->firstChild->next, &source, 0, &autoHandle);
00618 if( autoHandle && (!func->returnType.IsObjectHandle() || func->returnType.IsReference()) )
00619 return asINVALID_DECLARATION;
00620 if( returnAutoHandle ) *returnAutoHandle = autoHandle;
00621
00622
00623 if( isSystemFunction &&
00624 (func->returnType.GetObjectType() &&
00625 (func->returnType.GetObjectType()->flags & asOBJ_REF)) &&
00626 !(func->returnType.IsReference() ||
00627 func->returnType.IsObjectHandle()) )
00628 return asINVALID_DECLARATION;
00629
00630
00631 int paramCount = 0;
00632 n = n->next->firstChild;
00633 while( n )
00634 {
00635 paramCount++;
00636 n = n->next->next;
00637 if( n && n->nodeType == snIdentifier )
00638 n = n->next;
00639 }
00640
00641
00642 func->parameterTypes.Allocate(paramCount, false);
00643 func->inOutFlags.Allocate(paramCount, false);
00644 if( paramAutoHandles ) paramAutoHandles->Allocate(paramCount, false);
00645
00646 n = node->firstChild->next->next->next->firstChild;
00647 while( n )
00648 {
00649 asETypeModifiers inOutFlags;
00650 asCDataType type = CreateDataTypeFromNode(n, &source, false, objType);
00651 type = ModifyDataTypeFromNode(type, n->next, &source, &inOutFlags, &autoHandle);
00652
00653
00654 if( isSystemFunction &&
00655 (type.GetObjectType() &&
00656 (type.GetObjectType()->flags & asOBJ_REF)) &&
00657 !(type.IsReference() ||
00658 type.IsObjectHandle()) )
00659 return asINVALID_DECLARATION;
00660
00661
00662 func->parameterTypes.PushLast(type);
00663 func->inOutFlags.PushLast(inOutFlags);
00664
00665
00666 if( type.GetTokenType() == ttVoid )
00667 return asINVALID_DECLARATION;
00668
00669 if( autoHandle && (!type.IsObjectHandle() || type.IsReference()) )
00670 return asINVALID_DECLARATION;
00671
00672 if( paramAutoHandles ) paramAutoHandles->PushLast(autoHandle);
00673
00674
00675 if( type.GetTokenType() == ttQuestion &&
00676 !type.IsReference() )
00677 return asINVALID_DECLARATION;
00678
00679
00680 n = n->next->next;
00681 if( n && n->nodeType == snIdentifier )
00682 n = n->next;
00683 }
00684
00685
00686 if( node->lastChild->nodeType == snUndefined && node->lastChild->tokenType == ttConst )
00687 func->isReadOnly = true;
00688 else
00689 func->isReadOnly = false;
00690
00691 if( numErrors > 0 || numWarnings > 0 )
00692 return asINVALID_DECLARATION;
00693
00694 return 0;
00695 }
00696
00697 int asCBuilder::ParseVariableDeclaration(const char *decl, asCObjectProperty *var)
00698 {
00699 numErrors = 0;
00700 numWarnings = 0;
00701 preMessage.isSet = false;
00702
00703 asCScriptCode source;
00704 source.SetCode(TXT_VARIABLE_DECL, decl, true);
00705
00706 asCParser parser(this);
00707
00708 int r = parser.ParsePropertyDeclaration(&source);
00709 if( r < 0 )
00710 return asINVALID_DECLARATION;
00711
00712 asCScriptNode *node = parser.GetScriptNode();
00713
00714
00715 asCScriptNode *n = node->firstChild->next;
00716 var->name.Assign(&source.code[n->tokenPos], n->tokenLength);
00717
00718
00719 var->type = CreateDataTypeFromNode(node->firstChild, &source);
00720
00721 if( numErrors > 0 || numWarnings > 0 )
00722 return asINVALID_DECLARATION;
00723
00724 return 0;
00725 }
00726
00727 int asCBuilder::CheckNameConflictMember(asCDataType &dt, const char *name, asCScriptNode *node, asCScriptCode *code)
00728 {
00729
00730
00731
00732 asCObjectType *t = dt.GetObjectType();
00733
00734
00735 asCArray<asCObjectProperty *> &props = t->properties;
00736 for( asUINT n = 0; n < props.GetLength(); n++ )
00737 {
00738 if( props[n]->name == name )
00739 {
00740 if( code )
00741 {
00742 int r, c;
00743 code->ConvertPosToRowCol(node->tokenPos, &r, &c);
00744
00745 asCString str;
00746 str.Format(TXT_NAME_CONFLICT_s_OBJ_PROPERTY, name);
00747 WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
00748 }
00749
00750 return -1;
00751 }
00752 }
00753
00754
00755
00756 return 0;
00757 }
00758
00759 int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code)
00760 {
00761
00762
00763 if( engine->GetObjectType(name) != 0 )
00764 {
00765 if( code )
00766 {
00767 int r, c;
00768 code->ConvertPosToRowCol(node->tokenPos, &r, &c);
00769
00770 asCString str;
00771 str.Format(TXT_NAME_CONFLICT_s_EXTENDED_TYPE, name);
00772 WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
00773 }
00774
00775 return -1;
00776 }
00777
00778
00779
00780 asCGlobalProperty *prop = GetGlobalProperty(name, 0, 0, 0);
00781 if( prop )
00782 {
00783 if( code )
00784 {
00785 int r, c;
00786 code->ConvertPosToRowCol(node->tokenPos, &r, &c);
00787
00788 asCString str;
00789 str.Format(TXT_NAME_CONFLICT_s_GLOBAL_PROPERTY, name);
00790
00791 WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
00792 }
00793
00794 return -1;
00795 }
00796
00797
00798
00799
00800 asUINT n;
00801 for( n = 0; n < classDeclarations.GetLength(); n++ )
00802 {
00803 if( classDeclarations[n]->name == name )
00804 {
00805 if( code )
00806 {
00807 int r, c;
00808 code->ConvertPosToRowCol(node->tokenPos, &r, &c);
00809
00810 asCString str;
00811 str.Format(TXT_NAME_CONFLICT_s_STRUCT, name);
00812
00813 WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
00814 }
00815
00816 return -1;
00817 }
00818 }
00819
00820
00821 for( n = 0; n < namedTypeDeclarations.GetLength(); n++ )
00822 {
00823 if( namedTypeDeclarations[n]->name == name )
00824 {
00825 if( code )
00826 {
00827 int r, c;
00828 code->ConvertPosToRowCol(node->tokenPos, &r, &c);
00829
00830 asCString str;
00831
00832
00833 str.Format("Name conflict. '%s' is a named type (FIXME!).", name);
00834
00835 WriteError(code->name.AddressOf(), str.AddressOf(), r, c);
00836 }
00837
00838 return -1;
00839 }
00840 }
00841
00842 return 0;
00843 }
00844
00845
00846 int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file)
00847 {
00848
00849 asCDataType type = CreateDataTypeFromNode(node->firstChild, file);
00850
00851 if( !type.CanBeInstanciated() )
00852 {
00853 asCString str;
00854
00855 str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format().AddressOf());
00856
00857 int r, c;
00858 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
00859
00860 WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
00861 }
00862
00863 asCScriptNode *n = node->firstChild->next;
00864
00865 while( n )
00866 {
00867
00868 asCString name(&file->code[n->tokenPos], n->tokenLength);
00869 CheckNameConflict(name.AddressOf(), n, file);
00870
00871
00872 sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
00873 globVariables.PushLast(gvar);
00874
00875 gvar->script = file;
00876 gvar->name = name;
00877 gvar->isCompiled = false;
00878 gvar->datatype = type;
00879 gvar->isEnumValue = false;
00880
00881
00882 asASSERT(!gvar->datatype.IsReference());
00883
00884 gvar->idNode = n;
00885 gvar->nextNode = 0;
00886 if( n->next &&
00887 (n->next->nodeType == snAssignment ||
00888 n->next->nodeType == snArgList ||
00889 n->next->nodeType == snInitList ) )
00890 {
00891 gvar->nextNode = n->next;
00892 n->next->DisconnectParent();
00893 }
00894
00895 gvar->property = module->AllocateGlobalProperty(name.AddressOf(), gvar->datatype);
00896 gvar->index = gvar->property->id;
00897
00898 n = n->next;
00899 }
00900
00901 node->Destroy(engine);
00902
00903 return 0;
00904 }
00905
00906 int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file)
00907 {
00908 asCScriptNode *n = node->firstChild;
00909 asCString name(&file->code[n->tokenPos], n->tokenLength);
00910
00911 int r, c;
00912 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
00913
00914 CheckNameConflict(name.AddressOf(), n, file);
00915
00916 sClassDeclaration *decl = asNEW(sClassDeclaration);
00917 classDeclarations.PushLast(decl);
00918 decl->name = name;
00919 decl->script = file;
00920 decl->validState = 0;
00921 decl->node = node;
00922
00923 asCObjectType *st = asNEW(asCObjectType)(engine);
00924 st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT;
00925
00926 if( node->tokenType == ttHandle )
00927 st->flags |= asOBJ_IMPLICIT_HANDLE;
00928
00929 st->size = sizeof(asCScriptObject);
00930 st->name = name;
00931 module->classTypes.PushLast(st);
00932 engine->classTypes.PushLast(st);
00933 st->AddRef();
00934 decl->objType = st;
00935
00936
00937 st->beh = engine->scriptTypeBehaviours.beh;
00938
00939 return 0;
00940 }
00941
00942 int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file)
00943 {
00944 asCScriptNode *n = node->firstChild;
00945 asCString name(&file->code[n->tokenPos], n->tokenLength);
00946
00947 int r, c;
00948 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
00949
00950 CheckNameConflict(name.AddressOf(), n, file);
00951
00952 sClassDeclaration *decl = asNEW(sClassDeclaration);
00953 interfaceDeclarations.PushLast(decl);
00954 decl->name = name;
00955 decl->script = file;
00956 decl->validState = 0;
00957 decl->node = node;
00958
00959
00960 asCObjectType *st = asNEW(asCObjectType)(engine);
00961 st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT;
00962 st->size = 0;
00963 st->name = name;
00964 module->classTypes.PushLast(st);
00965 engine->classTypes.PushLast(st);
00966 st->AddRef();
00967 decl->objType = st;
00968
00969
00970 st->beh.construct = 0;
00971 st->beh.addref = engine->scriptTypeBehaviours.beh.addref;
00972 st->beh.release = engine->scriptTypeBehaviours.beh.release;
00973 st->beh.copy = 0;
00974
00975 return 0;
00976 }
00977
00978 void asCBuilder::CompileGlobalVariables()
00979 {
00980 asUINT n;
00981
00982 bool compileSucceeded = true;
00983
00984 asCByteCode finalInit(engine);
00985
00986
00987 int currNumErrors = numErrors;
00988 int currNumWarnings = numWarnings;
00989
00990
00991 bool msgCallback = engine->msgCallback;
00992 asSSystemFunctionInterface msgCallbackFunc = engine->msgCallbackFunc;
00993 void *msgCallbackObj = engine->msgCallbackObj;
00994
00995
00996 asCOutputBuffer outBuffer;
00997 engine->SetMessageCallback(asMETHOD(asCOutputBuffer, Callback), &outBuffer, asCALL_THISCALL);
00998
00999 asCOutputBuffer finalOutput;
01000
01001
01002
01003
01004
01005
01006
01007 bool compilingPrimitives = true;
01008
01009
01010 while( compileSucceeded )
01011 {
01012 compileSucceeded = false;
01013
01014 int accumErrors = 0;
01015 int accumWarnings = 0;
01016
01017
01018 finalOutput.Clear();
01019 for( asUINT n = 0; n < globVariables.GetLength(); n++ )
01020 {
01021 asCByteCode init(engine);
01022 numWarnings = 0;
01023 numErrors = 0;
01024 outBuffer.Clear();
01025
01026 sGlobalVariableDescription *gvar = globVariables[n];
01027 if( gvar->isCompiled )
01028 continue;
01029
01030
01031 if( compilingPrimitives && !gvar->datatype.IsPrimitive() )
01032 continue;
01033
01034 if( gvar->nextNode )
01035 {
01036 int r, c;
01037 gvar->script->ConvertPosToRowCol(gvar->nextNode->tokenPos, &r, &c);
01038 asCString str = gvar->datatype.Format();
01039 str += " " + gvar->name;
01040 str.Format(TXT_COMPILING_s, str.AddressOf());
01041 WriteInfo(gvar->script->name.AddressOf(), str.AddressOf(), r, c, true);
01042 }
01043
01044 if( gvar->isEnumValue )
01045 {
01046 int r;
01047 if( gvar->nextNode )
01048 {
01049 asCCompiler comp(engine);
01050
01051
01052 asCDataType saveType;
01053 saveType = gvar->datatype;
01054 gvar->datatype = asCDataType::CreatePrimitive(ttInt, true);
01055 r = comp.CompileGlobalVariable(this, gvar->script, gvar->nextNode, gvar);
01056 gvar->datatype = saveType;
01057 }
01058 else
01059 {
01060 r = 0;
01061
01062
01063 int enumVal = 0;
01064 if( n > 0 )
01065 {
01066 sGlobalVariableDescription *gvar2 = globVariables[n-1];
01067 if( gvar2->datatype == gvar->datatype )
01068 {
01069
01070 enumVal = (*(int*)&gvar2->constantValue) + 1;
01071
01072 if( !gvar2->isCompiled )
01073 {
01074
01075 int row, col;
01076 gvar->script->ConvertPosToRowCol(0, &row, &col);
01077
01078 asCString str = gvar->datatype.Format();
01079 str += " " + gvar->name;
01080 str.Format(TXT_COMPILING_s, str.AddressOf());
01081 WriteInfo(gvar->script->name.AddressOf(), str.AddressOf(), row, col, true);
01082
01083 str.Format(TXT_UNINITIALIZED_GLOBAL_VAR_s, gvar2->name.AddressOf());
01084 WriteError(gvar->script->name.AddressOf(), str.AddressOf(), row, col);
01085 r = -1;
01086 }
01087 }
01088 }
01089
01090
01091 *(int*)&gvar->constantValue = enumVal;
01092 }
01093
01094 if( r >= 0 )
01095 {
01096
01097 gvar->isCompiled = true;
01098 compileSucceeded = true;
01099 }
01100 }
01101 else
01102 {
01103
01104 asCCompiler comp(engine);
01105 int r = comp.CompileGlobalVariable(this, gvar->script, gvar->nextNode, gvar);
01106 if( r >= 0 )
01107 {
01108
01109 gvar->isCompiled = true;
01110 compileSucceeded = true;
01111
01112 init.AddCode(&comp.byteCode);
01113 }
01114 }
01115
01116 if( gvar->isCompiled )
01117 {
01118
01119 if( numWarnings )
01120 {
01121 currNumWarnings += numWarnings;
01122 if( msgCallback )
01123 outBuffer.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
01124 }
01125
01126
01127 finalInit.AddCode(&init);
01128 }
01129 else
01130 {
01131
01132 finalOutput.Append(outBuffer);
01133 accumErrors += numErrors;
01134 accumWarnings += numWarnings;
01135 }
01136
01137 preMessage.isSet = false;
01138 }
01139
01140 if( !compileSucceeded )
01141 {
01142 if( compilingPrimitives )
01143 {
01144
01145
01146 compilingPrimitives = false;
01147 compileSucceeded = true;
01148 }
01149 else
01150 {
01151
01152
01153 currNumWarnings += accumWarnings;
01154 currNumErrors += accumErrors;
01155 if( msgCallback )
01156 finalOutput.SendToCallback(engine, &msgCallbackFunc, msgCallbackObj);
01157 }
01158 }
01159 }
01160
01161
01162 engine->msgCallback = msgCallback;
01163 engine->msgCallbackFunc = msgCallbackFunc;
01164 engine->msgCallbackObj = msgCallbackObj;
01165
01166 numWarnings = currNumWarnings;
01167 numErrors = currNumErrors;
01168
01169
01170 finalInit.Ret(0);
01171
01172 finalInit.Finalize();
01173
01174 int id = engine->GetNextScriptFunctionId();
01175 asCScriptFunction *init = asNEW(asCScriptFunction)(engine,module);
01176
01177 init->id = id;
01178 module->initFunction = init;
01179 engine->SetScriptFunction(init);
01180
01181 init->byteCode.SetLength(finalInit.GetSize());
01182 finalInit.Output(init->byteCode.AddressOf());
01183 init->AddReferences();
01184 init->stackNeeded = finalInit.largestStackUsed;
01185
01186
01187 for( n = 0; n < globVariables.GetLength(); n++ )
01188 {
01189 asCObjectType *objectType;
01190 sGlobalVariableDescription *gvar = globVariables[n];
01191 if( !gvar->isEnumValue )
01192 continue;
01193
01194 objectType = gvar->datatype.GetObjectType();
01195 asASSERT(NULL != objectType);
01196
01197 asSEnumValue *e = asNEW(asSEnumValue);
01198 e->name = gvar->name;
01199 e->value = *(int*)&gvar->constantValue;
01200
01201 objectType->enumValues.PushLast(e);
01202
01203
01204 if( gvar->nextNode )
01205 gvar->nextNode->Destroy(engine);
01206 if( gvar->property )
01207 asDELETE(gvar->property, asCGlobalProperty);
01208
01209 asDELETE(gvar, sGlobalVariableDescription);
01210 globVariables[n] = 0;
01211 }
01212
01213 #ifdef AS_DEBUG
01214
01215 finalInit.DebugOutput("__@init.txt", module, engine);
01216 #endif
01217 }
01218
01219 void asCBuilder::CompileClasses()
01220 {
01221 asUINT n;
01222 asCArray<sClassDeclaration*> toValidate((int)classDeclarations.GetLength());
01223
01224
01225 for( n = 0; n < classDeclarations.GetLength(); n++ )
01226 {
01227 sClassDeclaration *decl = classDeclarations[n];
01228 asCScriptCode *file = decl->script;
01229
01230
01231 bool multipleInheritance = false;
01232 asCScriptNode *node = decl->node->firstChild->next;
01233 while( node && node->nodeType == snIdentifier )
01234 {
01235
01236 asCString name(&file->code[node->tokenPos], node->tokenLength);
01237
01238
01239 asCObjectType *objType = GetObjectType(name.AddressOf());
01240
01241 if( objType == 0 )
01242 {
01243 int r, c;
01244 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
01245 asCString str;
01246 str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE, name.AddressOf());
01247 WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
01248 }
01249 else if( !(objType->flags & asOBJ_SCRIPT_OBJECT) )
01250 {
01251 int r, c;
01252 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
01253 asCString str;
01254 str.Format(TXT_CANNOT_INHERIT_FROM_s, objType->name.AddressOf());
01255 WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
01256 }
01257 else if( objType->size != 0 )
01258 {
01259
01260 if( decl->objType->derivedFrom != 0 )
01261 {
01262 if( !multipleInheritance )
01263 {
01264 int r, c;
01265 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
01266 WriteError(file->name.AddressOf(), TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES, r, c);
01267 multipleInheritance = true;
01268 }
01269 }
01270 else
01271 {
01272
01273 asCObjectType *base = objType;
01274 bool error = false;
01275 while( base != 0 )
01276 {
01277 if( base == decl->objType )
01278 {
01279 int r, c;
01280 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
01281 WriteError(file->name.AddressOf(), TXT_CANNOT_INHERIT_FROM_SELF, r, c);
01282 error = true;
01283 break;
01284 }
01285
01286 base = base->derivedFrom;
01287 }
01288
01289 if( !error )
01290 {
01291 decl->objType->derivedFrom = objType;
01292 objType->AddRef();
01293 }
01294 }
01295 }
01296 else
01297 {
01298
01299 if( decl->objType->Implements(objType) )
01300 {
01301 int r, c;
01302 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
01303 asCString msg;
01304 msg.Format(TXT_INTERFACE_s_ALREADY_IMPLEMENTED, objType->GetName());
01305 WriteWarning(file->name.AddressOf(), msg.AddressOf(), r, c);
01306 }
01307 else
01308 {
01309 decl->objType->interfaces.PushLast(objType);
01310
01311
01312 for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
01313 {
01314 if( !DoesMethodExist(decl->objType, objType->methods[i]) )
01315 {
01316 int r, c;
01317 file->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
01318 asCString str;
01319 str.Format(TXT_MISSING_IMPLEMENTATION_OF_s,
01320 engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
01321 WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
01322 }
01323 }
01324 }
01325 }
01326
01327 node = node->next;
01328 }
01329 }
01330
01331
01332
01333 for( n = 0; n < classDeclarations.GetLength(); n++ )
01334 {
01335 sClassDeclaration *decl = classDeclarations[n];
01336 asCObjectType *derived = decl->objType;
01337 asCObjectType *base = derived->derivedFrom;
01338
01339 if( base == 0 ) continue;
01340
01341
01342 for( asUINT m = n+1; m < classDeclarations.GetLength(); m++ )
01343 {
01344 sClassDeclaration *declBase = classDeclarations[m];
01345 if( base == declBase->objType )
01346 {
01347 classDeclarations.RemoveIndex(n);
01348 classDeclarations.PushLast(decl);
01349
01350
01351 n--;
01352 break;
01353 }
01354 }
01355 }
01356
01357
01358 for( n = 0; n < classDeclarations.GetLength(); n++ )
01359 {
01360 sClassDeclaration *decl = classDeclarations[n];
01361
01362
01363 if( decl->objType->derivedFrom )
01364 {
01365 asCObjectType *baseType = decl->objType->derivedFrom;
01366
01367
01368 for( unsigned int n = 0; n < baseType->interfaces.GetLength(); n++ )
01369 {
01370 if( !decl->objType->Implements(baseType->interfaces[n]) )
01371 {
01372 decl->objType->interfaces.PushLast(baseType->interfaces[n]);
01373 }
01374 else
01375 {
01376
01377 int r, c;
01378 decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
01379 asCString msg;
01380 msg.Format(TXT_INTERFACE_s_ALREADY_IMPLEMENTED, baseType->interfaces[n]->GetName());
01381 WriteWarning(decl->script->name.AddressOf(), msg.AddressOf(), r, c);
01382 }
01383 }
01384
01385
01386
01387
01388 for( asUINT p = 0; p < baseType->properties.GetLength(); p++ )
01389 {
01390 asCObjectProperty *prop = AddPropertyToClass(decl, baseType->properties[p]->name, baseType->properties[p]->type);
01391
01392
01393 asASSERT(prop->byteOffset == baseType->properties[p]->byteOffset); UNUSED_VAR(prop);
01394 }
01395
01396
01397 for( asUINT m = 0; m < baseType->methods.GetLength(); m++ )
01398 {
01399
01400 asCScriptFunction *baseFunc = GetFunctionDescription(baseType->methods[m]);
01401 asCScriptFunction *derivedFunc = 0;
01402 bool found = false;
01403 for( asUINT d = 0; d < decl->objType->methods.GetLength(); d++ )
01404 {
01405 derivedFunc = GetFunctionDescription(decl->objType->methods[d]);
01406 if( derivedFunc->IsSignatureEqual(baseFunc) )
01407 {
01408 decl->objType->methods.RemoveIndex(d);
01409 found = true;
01410 break;
01411 }
01412 }
01413
01414 if( !found )
01415 {
01416
01417 decl->objType->virtualFunctionTable.PushLast(baseType->virtualFunctionTable[m]);
01418 }
01419 else
01420 {
01421
01422 decl->objType->virtualFunctionTable.PushLast(derivedFunc);
01423 }
01424 decl->objType->methods.PushLast(baseType->methods[m]);
01425 }
01426 }
01427
01428
01429 for( asUINT m = 0; m < decl->objType->methods.GetLength(); m++ )
01430 {
01431 asCScriptFunction *func = GetFunctionDescription(decl->objType->methods[m]);
01432 if( func->funcType != asFUNC_VIRTUAL )
01433 {
01434 decl->objType->virtualFunctionTable.PushLast(GetFunctionDescription(decl->objType->methods[m]));
01435
01436
01437
01438 decl->objType->methods.RemoveIndex(m);
01439 decl->objType->methods.PushLast(CreateVirtualFunction(func, (int)decl->objType->virtualFunctionTable.GetLength() - 1));
01440 m--;
01441 }
01442 }
01443
01444
01445 asCScriptNode *node = decl->node->firstChild->next;
01446
01447
01448 while( node && node->nodeType == snIdentifier )
01449 node = node->next;
01450
01451 while( node )
01452 {
01453 if( node->nodeType == snDeclaration )
01454 {
01455 asCScriptCode *file = decl->script;
01456 asCDataType dt = CreateDataTypeFromNode(node->firstChild, file);
01457 asCString name(&file->code[node->lastChild->tokenPos], node->lastChild->tokenLength);
01458
01459 if( dt.IsReadOnly() )
01460 {
01461 int r, c;
01462 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
01463
01464 WriteError(file->name.AddressOf(), TXT_PROPERTY_CANT_BE_CONST, r, c);
01465 }
01466
01467 asCDataType st;
01468 st.SetObjectType(decl->objType);
01469 CheckNameConflictMember(st, name.AddressOf(), node->lastChild, file);
01470
01471 AddPropertyToClass(decl, name, dt, file, node);
01472 }
01473 else
01474 asASSERT(false);
01475
01476 node = node->next;
01477 }
01478
01479 toValidate.PushLast(decl);
01480 }
01481
01482
01483
01484 while( toValidate.GetLength() > 0 )
01485 {
01486 asUINT numClasses = (asUINT)toValidate.GetLength();
01487
01488 asCArray<sClassDeclaration*> toValidateNext((int)toValidate.GetLength());
01489 while( toValidate.GetLength() > 0 )
01490 {
01491 sClassDeclaration *decl = toValidate[toValidate.GetLength()-1];
01492 int validState = 1;
01493 for( asUINT n = 0; n < decl->objType->properties.GetLength(); n++ )
01494 {
01495
01496 asCObjectProperty *prop = decl->objType->properties[n];
01497 asCDataType dt = prop->type;
01498
01499 if( dt.IsTemplate() )
01500 {
01501 asCDataType sub = dt;
01502 while( sub.IsTemplate() && !sub.IsObjectHandle() )
01503 sub = sub.GetSubType();
01504
01505 dt = sub;
01506 }
01507
01508 if( dt.IsObject() && !dt.IsObjectHandle() )
01509 {
01510
01511 sClassDeclaration *pdecl = 0;
01512 for( asUINT p = 0; p < classDeclarations.GetLength(); p++ )
01513 {
01514 if( classDeclarations[p]->objType == dt.GetObjectType() )
01515 {
01516 pdecl = classDeclarations[p];
01517 break;
01518 }
01519 }
01520
01521 if( pdecl )
01522 {
01523 if( pdecl->objType == decl->objType )
01524 {
01525 int r, c;
01526 decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
01527 WriteError(decl->script->name.AddressOf(), TXT_ILLEGAL_MEMBER_TYPE, r, c);
01528 validState = 2;
01529 break;
01530 }
01531 else if( pdecl->validState != 1 )
01532 {
01533 validState = pdecl->validState;
01534 break;
01535 }
01536 }
01537 }
01538 }
01539
01540 if( validState == 1 )
01541 {
01542 decl->validState = 1;
01543 toValidate.PopLast();
01544 }
01545 else if( validState == 2 )
01546 {
01547 decl->validState = 2;
01548 toValidate.PopLast();
01549 }
01550 else
01551 {
01552 toValidateNext.PushLast(toValidate.PopLast());
01553 }
01554 }
01555
01556 toValidate = toValidateNext;
01557 toValidateNext.SetLength(0);
01558
01559 if( numClasses == toValidate.GetLength() )
01560 {
01561 int r, c;
01562 toValidate[0]->script->ConvertPosToRowCol(toValidate[0]->node->tokenPos, &r, &c);
01563 WriteError(toValidate[0]->script->name.AddressOf(), TXT_ILLEGAL_MEMBER_TYPE, r, c);
01564 break;
01565 }
01566 }
01567
01568 if( numErrors > 0 ) return;
01569
01570
01571
01572
01573
01574 for( n = 0; n < classDeclarations.GetLength(); n++ )
01575 {
01576 sClassDeclaration *decl = classDeclarations[n];
01577 asCObjectType *ot = decl->objType;
01578
01579
01580 for( asUINT p = 0; p < ot->properties.GetLength(); p++ )
01581 {
01582 asCDataType dt = ot->properties[p]->type;
01583 if( dt.IsObject() )
01584 {
01585 if( dt.IsObjectHandle() )
01586 {
01587
01588
01589
01590 ot->flags |= asOBJ_GC;
01591 }
01592 else if( dt.GetObjectType()->flags & asOBJ_GC )
01593 {
01594
01595
01596
01597 ot->flags |= asOBJ_GC;
01598 }
01599
01600 if( dt.IsArrayType() )
01601 {
01602 asCDataType sub = dt.GetSubType();
01603 while( sub.IsObject() )
01604 {
01605 if( sub.IsObjectHandle() || (sub.GetObjectType()->flags & asOBJ_GC) )
01606 {
01607 decl->objType->flags |= asOBJ_GC;
01608
01609
01610 sub = dt;
01611 while( sub.IsTemplate() )
01612 {
01613 sub.GetObjectType()->flags |= asOBJ_GC;
01614 sub = sub.GetSubType();
01615 }
01616
01617 break;
01618 }
01619
01620 if( sub.IsTemplate() )
01621 sub = sub.GetSubType();
01622 else
01623 break;
01624 }
01625 }
01626 }
01627 }
01628 }
01629 }
01630
01631 int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx)
01632 {
01633 asCScriptFunction *vf = asNEW(asCScriptFunction)(engine, module);
01634
01635 vf->funcType = asFUNC_VIRTUAL;
01636 vf->name = func->name;
01637 vf->returnType = func->returnType;
01638 vf->parameterTypes = func->parameterTypes;
01639 vf->inOutFlags = func->inOutFlags;
01640 vf->id = engine->GetNextScriptFunctionId();
01641 vf->scriptSectionIdx = func->scriptSectionIdx;
01642 vf->isReadOnly = func->isReadOnly;
01643 vf->objectType = func->objectType;
01644 vf->signatureId = func->signatureId;
01645 vf->vfTableIdx = idx;
01646
01647 module->AddScriptFunction(vf);
01648
01649
01650 functions.PushLast(0);
01651
01652 return vf->id;
01653 }
01654
01655 asCObjectProperty *asCBuilder::AddPropertyToClass(sClassDeclaration *decl, const asCString &name, const asCDataType &dt, asCScriptCode *file, asCScriptNode *node)
01656 {
01657
01658 asCObjectProperty *prop = asNEW(asCObjectProperty);
01659 prop->name = name;
01660 prop->type = dt;
01661
01662 int propSize;
01663 if( dt.IsObject() )
01664 {
01665 propSize = dt.GetSizeOnStackDWords()*4;
01666 if( !dt.IsObjectHandle() )
01667 {
01668 if( !dt.CanBeInstanciated() )
01669 {
01670 asASSERT( file && node );
01671
01672 int r, c;
01673 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
01674 asCString str;
01675 str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format().AddressOf());
01676 WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
01677 }
01678 prop->type.MakeReference(true);
01679 }
01680 }
01681 else
01682 {
01683 propSize = dt.GetSizeInMemoryBytes();
01684 if( propSize == 0 && file && node )
01685 {
01686 int r, c;
01687 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
01688 asCString str;
01689 str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format().AddressOf());
01690 WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
01691 }
01692 }
01693
01694
01695 if( propSize == 2 && (decl->objType->size & 1) ) decl->objType->size += 1;
01696 if( propSize > 2 && (decl->objType->size & 3) ) decl->objType->size += 4 - (decl->objType->size & 3);
01697
01698 prop->byteOffset = decl->objType->size;
01699 decl->objType->size += propSize;
01700
01701 decl->objType->properties.PushLast(prop);
01702
01703
01704 asCConfigGroup *group = engine->FindConfigGroupForObjectType(prop->type.GetObjectType());
01705 if( group != 0 ) group->AddRef();
01706
01707 return prop;
01708 }
01709
01710 bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId)
01711 {
01712 asCScriptFunction *method = GetFunctionDescription(methodId);
01713
01714 for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
01715 {
01716 asCScriptFunction *m = GetFunctionDescription(objType->methods[n]);
01717
01718 if( m->name != method->name ) continue;
01719 if( m->returnType != method->returnType ) continue;
01720 if( m->isReadOnly != method->isReadOnly ) continue;
01721 if( m->parameterTypes != method->parameterTypes ) continue;
01722 if( m->inOutFlags != method->inOutFlags ) continue;
01723
01724 return true;
01725 }
01726
01727 return false;
01728 }
01729
01730 void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file)
01731 {
01732 int funcId = engine->GetNextScriptFunctionId();
01733
01734 asCDataType returnType = asCDataType::CreatePrimitive(ttVoid, false);
01735 asCArray<asCDataType> parameterTypes;
01736 asCArray<asETypeModifiers> inOutFlags;
01737
01738
01739 module->AddScriptFunction(file->idx, funcId, objType->name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), false, objType);
01740
01741
01742 objType->beh.construct = funcId;
01743 objType->beh.constructors[0] = funcId;
01744
01745
01746
01747 sFunctionDescription *func = asNEW(sFunctionDescription);
01748 functions.PushLast(func);
01749
01750 func->script = file;
01751 func->node = 0;
01752 func->name = objType->name;
01753 func->objType = objType;
01754 func->funcId = funcId;
01755
01756
01757 funcId = engine->GetNextScriptFunctionId();
01758 objType->beh.factory = funcId;
01759 objType->beh.factories[0] = funcId;
01760 returnType = asCDataType::CreateObjectHandle(objType, false);
01761 module->AddScriptFunction(file->idx, funcId, objType->name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), false);
01762 functions.PushLast(0);
01763 asCCompiler compiler(engine);
01764 compiler.CompileFactory(this, file, engine->scriptFunctions[funcId]);
01765 }
01766
01767 int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file)
01768 {
01769
01770 asCScriptNode *tmp = node->firstChild;
01771 asASSERT(snDataType == tmp->nodeType);
01772
01773 asCString name;
01774 asASSERT(snIdentifier == tmp->firstChild->nodeType);
01775 name.Assign(&file->code[tmp->firstChild->tokenPos], tmp->firstChild->tokenLength);
01776
01777
01778 int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file);
01779 if( asSUCCESS == r )
01780 {
01781 asCObjectType *st;
01782 asCDataType dataType;
01783
01784 st = asNEW(asCObjectType)(engine);
01785 dataType.CreatePrimitive(ttInt, false);
01786
01787 st->flags = asOBJ_ENUM;
01788 st->size = dataType.GetSizeInMemoryBytes();
01789 st->name = name;
01790
01791 module->enumTypes.PushLast(st);
01792 st->AddRef();
01793 engine->classTypes.PushLast(st);
01794
01795
01796 sClassDeclaration *decl = asNEW(sClassDeclaration);
01797 decl->name = name;
01798 decl->script = file;
01799 decl->validState = 0;
01800 decl->node = NULL;
01801 decl->objType = st;
01802 namedTypeDeclarations.PushLast(decl);
01803
01804 asCDataType type = CreateDataTypeFromNode(tmp, file);
01805 asASSERT(!type.IsReference());
01806
01807 tmp = tmp->next;
01808
01809 while( tmp )
01810 {
01811 asASSERT(snIdentifier == tmp->nodeType);
01812
01813 asCString name(&file->code[tmp->tokenPos], tmp->tokenLength);
01814
01815
01816
01817 r = CheckNameConflict(name.AddressOf(), tmp, file);
01818 if(asSUCCESS != r)
01819 {
01820 continue;
01821 }
01822
01823
01824 asCScriptNode *asnNode = tmp->next;
01825 if( asnNode && snAssignment == asnNode->nodeType )
01826 asnNode->DisconnectParent();
01827 else
01828 asnNode = 0;
01829
01830
01831 sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
01832 globVariables.PushLast(gvar);
01833
01834 gvar->script = file;
01835 gvar->idNode = 0;
01836 gvar->nextNode = asnNode;
01837 gvar->name = name;
01838 gvar->datatype = type;
01839
01840 gvar->index = 0;
01841 gvar->isCompiled = false;
01842 gvar->isPureConstant = true;
01843 gvar->isEnumValue = true;
01844 gvar->constantValue = 0xdeadbeef;
01845
01846
01847
01848 gvar->property = asNEW(asCGlobalProperty);
01849 gvar->property->name = name;
01850 gvar->property->type = gvar->datatype;
01851 gvar->property->id = 0;
01852
01853 tmp = tmp->next;
01854 }
01855 }
01856
01857 node->Destroy(engine);
01858
01859 return r;
01860 }
01861
01862 int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file)
01863 {
01864
01865 asCScriptNode *tmp = node->firstChild;
01866 asASSERT(NULL != tmp && snDataType == tmp->nodeType);
01867 asCDataType dataType;
01868 dataType.CreatePrimitive(tmp->tokenType, false);
01869 dataType.SetTokenType(tmp->tokenType);
01870 tmp = tmp->next;
01871
01872
01873 asASSERT(NULL != tmp && NULL == tmp->next);
01874 asCString name;
01875 name.Assign(&file->code[tmp->tokenPos], tmp->tokenLength);
01876
01877
01878 int r = CheckNameConflict(name.AddressOf(), tmp, file);
01879 if( asSUCCESS == r )
01880 {
01881
01882 asCObjectType *st = asNEW(asCObjectType)(engine);
01883
01884 st->flags = asOBJ_TYPEDEF;
01885 st->size = dataType.GetSizeInMemoryBytes();
01886 st->name = name;
01887 st->templateSubType = dataType;
01888
01889 st->AddRef();
01890
01891 module->typeDefs.PushLast(st);
01892 engine->classTypes.PushLast(st);
01893
01894
01895 sClassDeclaration *decl = asNEW(sClassDeclaration);
01896 decl->name = name;
01897 decl->script = file;
01898 decl->validState = 0;
01899 decl->node = NULL;
01900 decl->objType = st;
01901 namedTypeDeclarations.PushLast(decl);
01902 }
01903
01904 node->Destroy(engine);
01905
01906 if( r < 0 )
01907 {
01908 engine->ConfigError(r);
01909 }
01910
01911 return 0;
01912 }
01913
01914 int asCBuilder::RegisterScriptFunction(int funcID, asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction)
01915 {
01916
01917 bool isConstructor = false;
01918 bool isDestructor = false;
01919 asCScriptNode *n = 0;
01920 if( node->firstChild->nodeType == snDataType )
01921 n = node->firstChild->next->next;
01922 else
01923 {
01924
01925 if( node->firstChild->tokenType == ttBitNot )
01926 {
01927 n = node->firstChild->next;
01928 isDestructor = true;
01929 }
01930 else
01931 {
01932 n = node->firstChild;
01933 isConstructor = true;
01934 }
01935 }
01936
01937
01938 asCString name(&file->code[n->tokenPos], n->tokenLength);
01939 if( !isConstructor && !isDestructor )
01940 {
01941 asCDataType dt = asCDataType::CreateObject(objType, false);
01942 if( objType )
01943 CheckNameConflictMember(dt, name.AddressOf(), n, file);
01944 else
01945 CheckNameConflict(name.AddressOf(), n, file);
01946 }
01947 else
01948 {
01949
01950 if( name != objType->name )
01951 {
01952 int r, c;
01953 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
01954 WriteError(file->name.AddressOf(), TXT_CONSTRUCTOR_NAME_ERROR, r, c);
01955 }
01956
01957 if( isDestructor )
01958 name = "~" + name;
01959 }
01960
01961 if( !isInterface )
01962 {
01963 sFunctionDescription *func = asNEW(sFunctionDescription);
01964 functions.PushLast(func);
01965
01966 func->script = file;
01967 func->node = node;
01968 func->name = name;
01969 func->objType = objType;
01970 func->funcId = funcID;
01971 }
01972
01973
01974 asCDataType returnType = asCDataType::CreatePrimitive(ttVoid, false);
01975 if( !isConstructor && !isDestructor )
01976 {
01977 returnType = CreateDataTypeFromNode(node->firstChild, file);
01978 returnType = ModifyDataTypeFromNode(returnType, node->firstChild->next, file, 0, 0);
01979 }
01980
01981
01982 bool isConstMethod = false;
01983 if( objType && n->next->next && n->next->next->tokenType == ttConst )
01984 isConstMethod = true;
01985
01986
01987 int count = 0;
01988 asCScriptNode *c = n->next->firstChild;
01989 while( c )
01990 {
01991 count++;
01992 c = c->next->next;
01993 if( c && c->nodeType == snIdentifier )
01994 c = c->next;
01995 }
01996
01997
01998 if( isDestructor && count > 0 )
01999 {
02000 int r, c;
02001 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
02002
02003 WriteError(file->name.AddressOf(), TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, r, c);
02004 }
02005
02006 asCArray<asCDataType> parameterTypes(count);
02007 asCArray<asETypeModifiers> inOutFlags(count);
02008 n = n->next->firstChild;
02009 while( n )
02010 {
02011 asETypeModifiers inOutFlag;
02012 asCDataType type = CreateDataTypeFromNode(n, file);
02013 type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);
02014
02015
02016 parameterTypes.PushLast(type);
02017 inOutFlags.PushLast(inOutFlag);
02018
02019
02020 n = n->next->next;
02021 if( n && n->nodeType == snIdentifier )
02022 n = n->next;
02023 }
02024
02025
02026
02027 asCArray<int> funcs;
02028 GetFunctionDescriptions(name.AddressOf(), funcs);
02029 if( funcs.GetLength() )
02030 {
02031 for( asUINT n = 0; n < funcs.GetLength(); ++n )
02032 {
02033 asCScriptFunction *func = GetFunctionDescription(funcs[n]);
02034
02035 if( parameterTypes.GetLength() == func->parameterTypes.GetLength() )
02036 {
02037 bool match = true;
02038 if( func->objectType != objType )
02039 {
02040 match = false;
02041 break;
02042 }
02043
02044 for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
02045 {
02046 if( parameterTypes[p] != func->parameterTypes[p] )
02047 {
02048 match = false;
02049 break;
02050 }
02051 }
02052
02053 if( match )
02054 {
02055 int r, c;
02056 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
02057
02058 WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c);
02059 break;
02060 }
02061 }
02062 }
02063 }
02064
02065
02066 module->AddScriptFunction(file->idx, funcID, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), isInterface, objType, isConstMethod, isGlobalFunction);
02067
02068 if( objType )
02069 {
02070 if( isConstructor )
02071 {
02072 if( parameterTypes.GetLength() == 0 )
02073 {
02074
02075 objType->beh.construct = funcID;
02076 objType->beh.constructors[0] = funcID;
02077
02078
02079 objType->beh.factory = engine->GetNextScriptFunctionId();
02080 objType->beh.factories[0] = objType->beh.factory;
02081
02082 asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
02083 module->AddScriptFunction(file->idx, objType->beh.factory, name.AddressOf(), dt, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), false);
02084
02085
02086 functions.PushLast(0);
02087
02088
02089 asCCompiler compiler(engine);
02090 compiler.CompileFactory(this, file, engine->scriptFunctions[objType->beh.factory]);
02091 }
02092 else
02093 {
02094 objType->beh.constructors.PushLast(funcID);
02095
02096
02097
02098 int factoryId = engine->GetNextScriptFunctionId();
02099 objType->beh.factories.PushLast(factoryId);
02100
02101 asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
02102 module->AddScriptFunction(file->idx, factoryId, name.AddressOf(), dt, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), false);
02103
02104
02105 functions.PushLast(0);
02106
02107
02108 asCCompiler compiler(engine);
02109 compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]);
02110 }
02111 }
02112 else if( isDestructor )
02113 objType->beh.destruct = funcID;
02114 else
02115 objType->methods.PushLast(funcID);
02116 }
02117
02118
02119 if( isInterface && node )
02120 {
02121 node->Destroy(engine);
02122 }
02123
02124 return 0;
02125 }
02126
02127 int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCScriptCode *file)
02128 {
02129
02130 asCScriptNode *f = node->firstChild;
02131 asCScriptNode *n = f->firstChild->next->next;
02132
02133
02134 asCString name(&file->code[n->tokenPos], n->tokenLength);
02135 CheckNameConflict(name.AddressOf(), n, file);
02136
02137
02138 asCDataType returnType;
02139 returnType = CreateDataTypeFromNode(f->firstChild, file);
02140 returnType = ModifyDataTypeFromNode(returnType, f->firstChild->next, file, 0, 0);
02141
02142
02143 int count = 0;
02144 asCScriptNode *c = n->next->firstChild;
02145 while( c )
02146 {
02147 count++;
02148 c = c->next->next;
02149 if( c && c->nodeType == snIdentifier )
02150 c = c->next;
02151 }
02152
02153 asCArray<asCDataType> parameterTypes(count);
02154 asCArray<asETypeModifiers> inOutFlags(count);
02155 n = n->next->firstChild;
02156 while( n )
02157 {
02158 asETypeModifiers inOutFlag;
02159 asCDataType type = CreateDataTypeFromNode(n, file);
02160 type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);
02161
02162
02163 n = n->next->next;
02164 parameterTypes.PushLast(type);
02165 inOutFlags.PushLast(inOutFlag);
02166
02167
02168 if( n && n->nodeType == snIdentifier )
02169 n = n->next;
02170 }
02171
02172
02173 asCArray<int> funcs;
02174 GetFunctionDescriptions(name.AddressOf(), funcs);
02175 if( funcs.GetLength() )
02176 {
02177 for( asUINT n = 0; n < funcs.GetLength(); ++n )
02178 {
02179 asCScriptFunction *func = GetFunctionDescription(funcs[n]);
02180
02181
02182 if( name == func->name &&
02183 parameterTypes.GetLength() == func->parameterTypes.GetLength() )
02184 {
02185 bool match = true;
02186 for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
02187 {
02188 if( parameterTypes[p] != func->parameterTypes[p] )
02189 {
02190 match = false;
02191 break;
02192 }
02193 }
02194
02195 if( match )
02196 {
02197 int r, c;
02198 file->ConvertPosToRowCol(node->tokenPos, &r, &c);
02199
02200 WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c);
02201 break;
02202 }
02203 }
02204 }
02205 }
02206
02207
02208 n = node->firstChild->next;
02209 asCString moduleName;
02210 moduleName.Assign(&file->code[n->tokenPos+1], n->tokenLength-2);
02211
02212 node->Destroy(engine);
02213
02214
02215 module->AddImportedFunction(importID, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), moduleName);
02216
02217 return 0;
02218 }
02219
02220
02221 asCScriptFunction *asCBuilder::GetFunctionDescription(int id)
02222 {
02223
02224
02225 if( (id & 0xFFFF0000) == 0 )
02226 return engine->scriptFunctions[id];
02227 else
02228 return module->importedFunctions[id & 0xFFFF];
02229 }
02230
02231 void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs)
02232 {
02233 asUINT n;
02234
02235 for( n = 0; n < module->scriptFunctions.GetLength(); n++ )
02236 {
02237 if( module->scriptFunctions[n]->name == name &&
02238 module->scriptFunctions[n]->objectType == 0 )
02239 funcs.PushLast(module->scriptFunctions[n]->id);
02240 }
02241
02242
02243 for( n = 0; n < module->importedFunctions.GetLength(); n++ )
02244 {
02245 if( module->importedFunctions[n]->name == name )
02246 funcs.PushLast(module->importedFunctions[n]->id);
02247 }
02248
02249
02250 for( n = 0; n < engine->scriptFunctions.GetLength(); n++ )
02251 {
02252 if( engine->scriptFunctions[n] &&
02253 engine->scriptFunctions[n]->funcType == asFUNC_SYSTEM &&
02254 engine->scriptFunctions[n]->objectType == 0 &&
02255 engine->scriptFunctions[n]->name == name )
02256 {
02257
02258 asCConfigGroup *group = engine->FindConfigGroupForFunction(engine->scriptFunctions[n]->id);
02259 if( !group || group->HasModuleAccess(module->name.AddressOf()) )
02260 funcs.PushLast(engine->scriptFunctions[n]->id);
02261 }
02262 }
02263 }
02264
02265 void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope)
02266 {
02267 if( scope != "" )
02268 {
02269
02270 while( objectType && objectType->name != scope )
02271 objectType = objectType->derivedFrom;
02272
02273
02274 if( objectType == 0 )
02275 return;
02276 }
02277
02278
02279 if( objIsConst )
02280 {
02281
02282 for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
02283 {
02284 if( engine->scriptFunctions[objectType->methods[n]]->name == name &&
02285 engine->scriptFunctions[objectType->methods[n]]->isReadOnly )
02286 {
02287
02288 if( scope == "" )
02289 methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
02290 else
02291 {
02292 asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]];
02293 asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx];
02294 methods.PushLast(realFunc->id);
02295 }
02296 }
02297 }
02298 }
02299 else
02300 {
02301
02302 for( asUINT n = 0; n < objectType->methods.GetLength(); n++ )
02303 {
02304 if( engine->scriptFunctions[objectType->methods[n]]->name == name )
02305 {
02306
02307 if( scope == "" )
02308 methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id);
02309 else
02310 {
02311 asCScriptFunction *virtFunc = engine->scriptFunctions[objectType->methods[n]];
02312 asCScriptFunction *realFunc = objectType->virtualFunctionTable[virtFunc->vfTableIdx];
02313 methods.PushLast(realFunc->id);
02314 }
02315 }
02316 }
02317 }
02318 }
02319
02320 void asCBuilder::WriteInfo(const char *scriptname, const char *message, int r, int c, bool pre)
02321 {
02322
02323 if( pre )
02324 {
02325 preMessage.isSet = true;
02326 preMessage.c = c;
02327 preMessage.r = r;
02328 preMessage.message = message;
02329 }
02330 else
02331 {
02332 preMessage.isSet = false;
02333 engine->WriteMessage(scriptname, r, c, asMSGTYPE_INFORMATION, message);
02334 }
02335 }
02336
02337 void asCBuilder::WriteError(const char *scriptname, const char *message, int r, int c)
02338 {
02339 numErrors++;
02340
02341
02342 if( preMessage.isSet )
02343 WriteInfo(scriptname, preMessage.message.AddressOf(), preMessage.r, preMessage.c, false);
02344
02345 engine->WriteMessage(scriptname, r, c, asMSGTYPE_ERROR, message);
02346 }
02347
02348 void asCBuilder::WriteWarning(const char *scriptname, const char *message, int r, int c)
02349 {
02350 numWarnings++;
02351
02352
02353 if( preMessage.isSet )
02354 WriteInfo(scriptname, preMessage.message.AddressOf(), preMessage.r, preMessage.c, false);
02355
02356 engine->WriteMessage(scriptname, r, c, asMSGTYPE_WARNING, message);
02357 }
02358
02359
02360 asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCode *file, bool acceptHandleForScope, asCObjectType *templateType)
02361 {
02362 asASSERT(node->nodeType == snDataType);
02363
02364 asCDataType dt;
02365
02366 asCScriptNode *n = node->firstChild;
02367
02368 bool isConst = false;
02369 bool isImplicitHandle = false;
02370 if( n->tokenType == ttConst )
02371 {
02372 isConst = true;
02373 n = n->next;
02374 }
02375
02376 if( n->tokenType == ttIdentifier )
02377 {
02378 asCString str;
02379 str.Assign(&file->code[n->tokenPos], n->tokenLength);
02380
02381 asCObjectType *ot = 0;
02382
02383
02384
02385
02386 if( templateType && (templateType->flags & asOBJ_TEMPLATE) && str == templateType->templateSubType.GetObjectType()->name )
02387 ot = templateType->templateSubType.GetObjectType();
02388
02389 if( ot == 0 )
02390 ot = GetObjectType(str.AddressOf());
02391
02392 if( ot == 0 )
02393 {
02394 asCString msg;
02395 msg.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE, (const char *)str.AddressOf());
02396
02397 int r, c;
02398 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
02399
02400 WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
02401
02402 dt.SetTokenType(ttInt);
02403 }
02404 else
02405 {
02406 if( ot->flags & asOBJ_IMPLICIT_HANDLE )
02407 isImplicitHandle = true;
02408
02409
02410 asCConfigGroup *group = engine->FindConfigGroupForObjectType(ot);
02411 if( !module || !group || group->HasModuleAccess(module->name.AddressOf()) )
02412 {
02413 if(asOBJ_TYPEDEF == (ot->flags & asOBJ_TYPEDEF))
02414 {
02415
02416
02417 dt = ot->templateSubType;
02418 dt.MakeReadOnly(isConst);
02419 }
02420 else
02421 {
02422 if( ot->flags & asOBJ_TEMPLATE )
02423 {
02424 n = n->next;
02425
02426
02427
02428
02429 asCDataType subType = CreateDataTypeFromNode(n, file, false, ot);
02430 if( subType.GetObjectType() != ot->templateSubType.GetObjectType() )
02431 {
02432
02433
02434 asCObjectType *otInstance = engine->GetTemplateInstanceType(ot, subType);
02435
02436 if( !otInstance )
02437 {
02438 asCString msg;
02439 msg.Format(TXT_CANNOT_INSTANCIATE_TEMPLATE_s_WITH_s, ot->name.AddressOf(), subType.Format().AddressOf());
02440 int r, c;
02441 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
02442 WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
02443 }
02444
02445 ot = otInstance;
02446 }
02447 }
02448
02449
02450 if( ot )
02451 dt = asCDataType::CreateObject(ot, isConst);
02452 else
02453 dt = asCDataType::CreatePrimitive(ttInt, isConst);
02454 }
02455 }
02456 else
02457 {
02458 asCString msg;
02459 msg.Format(TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE, (const char *)str.AddressOf());
02460
02461 int r, c;
02462 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
02463
02464 WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
02465
02466 dt.SetTokenType(ttInt);
02467 }
02468 }
02469 }
02470 else
02471 {
02472
02473 dt = asCDataType::CreatePrimitive(n->tokenType, isConst);
02474 }
02475
02476
02477 n = n->next;
02478 while( n && (n->tokenType == ttOpenBracket || n->tokenType == ttHandle) )
02479 {
02480 if( n->tokenType == ttOpenBracket )
02481 {
02482
02483 if( !dt.CanBeInstanciated() )
02484 {
02485 int r, c;
02486 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
02487
02488 asCString str;
02489
02490 str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format().AddressOf());
02491
02492 WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
02493 }
02494
02495
02496 if( dt.MakeArray(engine) < 0 )
02497 {
02498 int r, c;
02499 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
02500 WriteError(file->name.AddressOf(), TXT_TOO_MANY_ARRAY_DIMENSIONS, r, c);
02501 break;
02502 }
02503 }
02504 else
02505 {
02506
02507 if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
02508 {
02509 int r, c;
02510 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
02511 WriteError(file->name.AddressOf(), TXT_OBJECT_HANDLE_NOT_SUPPORTED, r, c);
02512 break;
02513 }
02514 }
02515 n = n->next;
02516 }
02517
02518 if( isImplicitHandle )
02519 {
02520
02521 if( dt.MakeHandle(true, acceptHandleForScope) < 0 )
02522 {
02523 int r, c;
02524 file->ConvertPosToRowCol(n->tokenPos, &r, &c);
02525 WriteError(file->name.AddressOf(), TXT_OBJECT_HANDLE_NOT_SUPPORTED, r, c);
02526 }
02527 }
02528
02529 return dt;
02530 }
02531
02532 asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScriptNode *node, asCScriptCode *file, asETypeModifiers *inOutFlags, bool *autoHandle)
02533 {
02534 asCDataType dt = type;
02535
02536 if( inOutFlags ) *inOutFlags = asTM_NONE;
02537
02538
02539 asCScriptNode *n = node->firstChild;
02540 if( n && n->tokenType == ttAmp )
02541 {
02542 dt.MakeReference(true);
02543 n = n->next;
02544
02545 if( n )
02546 {
02547 if( inOutFlags )
02548 {
02549 if( n->tokenType == ttIn )
02550 *inOutFlags = asTM_INREF;
02551 else if( n->tokenType == ttOut )
02552 *inOutFlags = asTM_OUTREF;
02553 else if( n->tokenType == ttInOut )
02554 *inOutFlags = asTM_INOUTREF;
02555 else
02556 asASSERT(false);
02557 }
02558
02559 n = n->next;
02560 }
02561 else
02562 {
02563 if( inOutFlags )
02564 *inOutFlags = asTM_INOUTREF;
02565 }
02566
02567 if( !engine->ep.allowUnsafeReferences &&
02568 inOutFlags && *inOutFlags == asTM_INOUTREF )
02569 {
02570
02571 if( !dt.IsObject() || dt.IsObjectHandle() || !dt.GetObjectType()->beh.addref || !dt.GetObjectType()->beh.release )
02572 {
02573 int r, c;
02574 file->ConvertPosToRowCol(node->firstChild->tokenPos, &r, &c);
02575 WriteError(file->name.AddressOf(), TXT_ONLY_OBJECTS_MAY_USE_REF_INOUT, r, c);
02576 }
02577 }
02578 }
02579
02580 if( autoHandle ) *autoHandle = false;
02581
02582 if( n && n->tokenType == ttPlus )
02583 {
02584 if( autoHandle ) *autoHandle = true;
02585 }
02586
02587 return dt;
02588 }
02589
02590 const asCString &asCBuilder::GetConstantString(int strID)
02591 {
02592 return module->GetConstantString(strID);
02593 }
02594
02595 asCObjectType *asCBuilder::GetObjectType(const char *type)
02596 {
02597
02598 asCObjectType *ot = engine->GetObjectType(type);
02599 if( !ot && module )
02600 ot = module->GetObjectType(type);
02601
02602 return ot;
02603 }
02604
02605 int asCBuilder::GetEnumValueFromObjectType(asCObjectType *objType, const char *name, asCDataType &outDt, asDWORD &outValue)
02606 {
02607 if( !objType || !(objType->flags & asOBJ_ENUM) )
02608 return 0;
02609
02610 for( asUINT n = 0; n < objType->enumValues.GetLength(); ++n )
02611 {
02612 if( objType->enumValues[n]->name == name )
02613 {
02614 outDt = asCDataType::CreateObject(objType, true);
02615 outValue = objType->enumValues[n]->value;
02616 return 1;
02617 }
02618 }
02619
02620 return 0;
02621 }
02622
02623 int asCBuilder::GetEnumValue(const char *name, asCDataType &outDt, asDWORD &outValue)
02624 {
02625 bool found = false;
02626
02627
02628 asUINT t;
02629 for( t = 0; t < engine->objectTypes.GetLength(); t++ )
02630 {
02631 asCObjectType *ot = engine->objectTypes[t];
02632 if( GetEnumValueFromObjectType( ot, name, outDt, outValue ) )
02633 {
02634 if( !found )
02635 {
02636 found = true;
02637 }
02638 else
02639 {
02640
02641 return 2;
02642 }
02643 }
02644 }
02645
02646 for( t = 0; t < module->enumTypes.GetLength(); t++ )
02647 {
02648 asCObjectType *ot = module->enumTypes[t];
02649 if( GetEnumValueFromObjectType( ot, name, outDt, outValue ) )
02650 {
02651 if( !found )
02652 {
02653 found = true;
02654 }
02655 else
02656 {
02657
02658 return 2;
02659 }
02660 }
02661 }
02662
02663 if( found )
02664 return 1;
02665
02666
02667 return 0;
02668 }
02669
02670 END_AS_NAMESPACE