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 #include <math.h>
00039
00040 #include "as_config.h"
00041 #include "as_compiler.h"
00042 #include "as_tokendef.h"
00043 #include "as_tokenizer.h"
00044 #include "as_string_util.h"
00045 #include "as_texts.h"
00046 #include "as_parser.h"
00047
00048 BEGIN_AS_NAMESPACE
00049
00050 #ifdef AS_DEPRECATED
00051
00052
00053 const int behave_dual_token[] =
00054 {
00055 ttPlus, asBEHAVE_ADD,
00056 ttMinus, asBEHAVE_SUBTRACT,
00057 ttStar, asBEHAVE_MULTIPLY,
00058 ttSlash, asBEHAVE_DIVIDE,
00059 ttPercent, asBEHAVE_MODULO,
00060 ttEqual, asBEHAVE_EQUAL,
00061 ttNotEqual, asBEHAVE_NOTEQUAL,
00062 ttLessThan, asBEHAVE_LESSTHAN,
00063 ttGreaterThan, asBEHAVE_GREATERTHAN,
00064 ttLessThanOrEqual, asBEHAVE_LEQUAL,
00065 ttGreaterThanOrEqual, asBEHAVE_GEQUAL,
00066 ttBitOr, asBEHAVE_BIT_OR,
00067 ttAmp, asBEHAVE_BIT_AND,
00068 ttBitXor, asBEHAVE_BIT_XOR,
00069 ttBitShiftLeft, asBEHAVE_BIT_SLL,
00070 ttBitShiftRight, asBEHAVE_BIT_SRL,
00071 ttBitShiftRightArith, asBEHAVE_BIT_SRA,
00072 ttAssignment, asBEHAVE_ASSIGNMENT,
00073 ttAddAssign, asBEHAVE_ADD_ASSIGN,
00074 ttSubAssign, asBEHAVE_SUB_ASSIGN,
00075 ttMulAssign, asBEHAVE_MUL_ASSIGN,
00076 ttDivAssign, asBEHAVE_DIV_ASSIGN,
00077 ttModAssign, asBEHAVE_MOD_ASSIGN,
00078 ttOrAssign, asBEHAVE_OR_ASSIGN,
00079 ttAndAssign, asBEHAVE_AND_ASSIGN,
00080 ttXorAssign, asBEHAVE_XOR_ASSIGN,
00081 ttShiftLeftAssign, asBEHAVE_SLL_ASSIGN,
00082 ttShiftRightLAssign, asBEHAVE_SRL_ASSIGN,
00083 ttShiftRightAAssign, asBEHAVE_SRA_ASSIGN
00084 };
00085
00086 const int num_dual_tokens = sizeof(behave_dual_token)/sizeof(int)/2;
00087 #endif
00088
00089 asCCompiler::asCCompiler(asCScriptEngine *engine) : byteCode(engine)
00090 {
00091 builder = 0;
00092 script = 0;
00093
00094 variables = 0;
00095 isProcessingDeferredParams = false;
00096 noCodeOutput = 0;
00097 }
00098
00099 asCCompiler::~asCCompiler()
00100 {
00101 while( variables )
00102 {
00103 asCVariableScope *var = variables;
00104 variables = variables->parent;
00105
00106 asDELETE(var,asCVariableScope);
00107 }
00108 }
00109
00110 void asCCompiler::Reset(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc)
00111 {
00112 this->builder = builder;
00113 this->engine = builder->engine;
00114 this->script = script;
00115 this->outFunc = outFunc;
00116
00117 hasCompileErrors = false;
00118
00119 m_isConstructor = false;
00120 m_isConstructorCalled = false;
00121
00122 nextLabel = 0;
00123 breakLabels.SetLength(0);
00124 continueLabels.SetLength(0);
00125
00126 byteCode.ClearAll();
00127 objVariableTypes.SetLength(0);
00128 objVariablePos.SetLength(0);
00129
00130 globalExpression = false;
00131 }
00132
00133 int asCCompiler::CompileDefaultConstructor(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc)
00134 {
00135 Reset(builder, script, outFunc);
00136
00137
00138 if( outFunc->objectType->derivedFrom )
00139 {
00140
00141 byteCode.InstrSHORT(asBC_PSF, 0);
00142 byteCode.Instr(asBC_RDSPTR);
00143 byteCode.Call(asBC_CALL, outFunc->objectType->derivedFrom->beh.construct, AS_PTR_SIZE);
00144 }
00145
00146
00147 byteCode.Ret(AS_PTR_SIZE);
00148
00149 byteCode.Finalize();
00150
00151
00152 outFunc->byteCode.SetLength(byteCode.GetSize());
00153 byteCode.Output(outFunc->byteCode.AddressOf());
00154 outFunc->AddReferences();
00155 outFunc->stackNeeded = byteCode.largestStackUsed;
00156 outFunc->lineNumbers = byteCode.lineNumbers;
00157 outFunc->objVariablePos = objVariablePos;
00158 outFunc->objVariableTypes = objVariableTypes;
00159
00160 #ifdef AS_DEBUG
00161
00162 byteCode.DebugOutput(("__" + outFunc->objectType->name + "_" + outFunc->name + "__dc.txt").AddressOf(), builder->module, engine);
00163 #endif
00164
00165 return 0;
00166 }
00167
00168 int asCCompiler::CompileFactory(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc)
00169 {
00170 Reset(builder, script, outFunc);
00171
00172 unsigned int n;
00173
00174
00175 asCDataType dt = asCDataType::CreateObject(outFunc->returnType.GetObjectType(), false);
00176 int constructor = 0;
00177 for( n = 0; n < dt.GetBehaviour()->factories.GetLength(); n++ )
00178 {
00179 if( dt.GetBehaviour()->factories[n] == outFunc->id )
00180 {
00181 constructor = dt.GetBehaviour()->constructors[n];
00182 break;
00183 }
00184 }
00185
00186
00187 int varOffset = AllocateVariable(dt, true);
00188
00189 byteCode.Push(AS_PTR_SIZE);
00190 byteCode.InstrSHORT(asBC_PSF, (short)varOffset);
00191
00192
00193 int argDwords = (int)outFunc->GetSpaceNeededForArguments();
00194 for( int a = argDwords-1; a >= 0; a-- )
00195 byteCode.InstrSHORT(asBC_PshV4, short(-a));
00196
00197 byteCode.Alloc(asBC_ALLOC, dt.GetObjectType(), constructor, argDwords + AS_PTR_SIZE);
00198
00199
00200 byteCode.InstrSHORT(asBC_LOADOBJ, (short)varOffset);
00201
00202 byteCode.Pop(AS_PTR_SIZE);
00203 byteCode.Ret(argDwords);
00204
00205 byteCode.Finalize();
00206
00207
00208 objVariableTypes.PushLast(variableAllocations[0].GetObjectType());
00209 objVariablePos.PushLast(GetVariableOffset(0));
00210
00211
00212 outFunc->byteCode.SetLength(byteCode.GetSize());
00213 byteCode.Output(outFunc->byteCode.AddressOf());
00214 outFunc->AddReferences();
00215 outFunc->stackNeeded = byteCode.largestStackUsed;
00216 outFunc->lineNumbers = byteCode.lineNumbers;
00217 outFunc->objVariablePos = objVariablePos;
00218 outFunc->objVariableTypes = objVariableTypes;
00219
00220
00221 outFunc->dontCleanUpOnException = true;
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 return 0;
00232 }
00233
00234 int asCCompiler::CompileTemplateFactoryStub(asCBuilder *builder, int trueFactoryId, asCObjectType *objType, asCScriptFunction *outFunc)
00235 {
00236 Reset(builder, 0, outFunc);
00237
00238 asCScriptFunction *descr = builder->GetFunctionDescription(trueFactoryId);
00239
00240 byteCode.InstrPTR(asBC_OBJTYPE, objType);
00241 byteCode.Call(asBC_CALLSYS, trueFactoryId, descr->GetSpaceNeededForArguments());
00242 byteCode.Ret(outFunc->GetSpaceNeededForArguments());
00243
00244 byteCode.Finalize();
00245
00246
00247 outFunc->byteCode.SetLength(byteCode.GetSize());
00248 byteCode.Output(outFunc->byteCode.AddressOf());
00249 outFunc->AddReferences();
00250 outFunc->stackNeeded = byteCode.largestStackUsed;
00251 outFunc->lineNumbers = byteCode.lineNumbers;
00252 outFunc->objVariablePos = objVariablePos;
00253 outFunc->objVariableTypes = objVariableTypes;
00254
00255
00256 outFunc->dontCleanUpOnException = true;
00257
00258 return 0;
00259 }
00260
00261 int asCCompiler::CompileFunction(asCBuilder *builder, asCScriptCode *script, asCScriptNode *func, asCScriptFunction *outFunc)
00262 {
00263 Reset(builder, script, outFunc);
00264
00265 int stackPos = 0;
00266 if( outFunc->objectType )
00267 stackPos = -AS_PTR_SIZE;
00268
00269
00270 nextLabel++;
00271
00272
00273
00274
00275 AddVariableScope();
00276
00277
00278
00279 bool isDestructor = false;
00280 asCDataType returnType;
00281 if( func->firstChild->nodeType == snDataType )
00282 {
00283 returnType = builder->CreateDataTypeFromNode(func->firstChild, script);
00284 returnType = builder->ModifyDataTypeFromNode(returnType, func->firstChild->next, script, 0, 0);
00285
00286
00287 if( !returnType.CanBeInstanciated() &&
00288 returnType != asCDataType::CreatePrimitive(ttVoid, false) )
00289 {
00290 asCString str;
00291 str.Format(TXT_DATA_TYPE_CANT_BE_s, returnType.Format().AddressOf());
00292 Error(str.AddressOf(), func->firstChild);
00293 }
00294
00295
00296
00297 if( returnType.IsReference() )
00298 {
00299 Error(TXT_SCRIPT_FUNCTIONS_DOESNT_SUPPORT_RETURN_REF, func->firstChild);
00300 }
00301 }
00302 else
00303 {
00304 returnType = asCDataType::CreatePrimitive(ttVoid, false);
00305 if( func->firstChild->tokenType == ttBitNot )
00306 isDestructor = true;
00307 else
00308 m_isConstructor = true;
00309 }
00310
00311
00312
00313
00314 asCScriptNode *node = func->firstChild;
00315 while( node && node->nodeType != snParameterList )
00316 node = node->next;
00317
00318
00319 asCVariableScope vs(0);
00320
00321 if( node ) node = node->firstChild;
00322 while( node )
00323 {
00324
00325 asCDataType type = builder->CreateDataTypeFromNode(node, script);
00326
00327 asETypeModifiers inoutFlag = asTM_NONE;
00328 type = builder->ModifyDataTypeFromNode(type, node->next, script, &inoutFlag, 0);
00329
00330
00331 if( (type.IsReference() && inoutFlag != asTM_INOUTREF && !type.CanBeInstanciated()) ||
00332 (!type.IsReference() && !type.CanBeInstanciated()) )
00333 {
00334 asCString str;
00335 str.Format(TXT_PARAMETER_CANT_BE_s, type.Format().AddressOf());
00336 Error(str.AddressOf(), node);
00337 }
00338
00339
00340 node = node->next->next;
00341 if( node && node->nodeType == snIdentifier )
00342 {
00343 asCString name(&script->code[node->tokenPos], node->tokenLength);
00344
00345 if( vs.DeclareVariable(name.AddressOf(), type, stackPos) < 0 )
00346 Error(TXT_PARAMETER_ALREADY_DECLARED, node);
00347
00348 outFunc->AddVariable(name, type, stackPos);
00349
00350 node = node->next;
00351 }
00352 else
00353 vs.DeclareVariable("", type, stackPos);
00354
00355
00356 stackPos -= type.GetSizeOnStackDWords();
00357 }
00358
00359 int n;
00360 for( n = (int)vs.variables.GetLength() - 1; n >= 0; n-- )
00361 {
00362 variables->DeclareVariable(vs.variables[n]->name.AddressOf(), vs.variables[n]->type, vs.variables[n]->stackOffset);
00363 }
00364
00365
00366 if( (returnType.GetSizeOnStackDWords() == 0 && returnType != asCDataType::CreatePrimitive(ttVoid, false)) ||
00367 (returnType.IsReference() && !returnType.CanBeInstanciated()) )
00368 {
00369 asCString str;
00370 str.Format(TXT_RETURN_CANT_BE_s, returnType.Format().AddressOf());
00371 Error(str.AddressOf(), node);
00372 }
00373
00374 variables->DeclareVariable("return", returnType, stackPos);
00375
00376
00377
00378
00379
00380
00381
00382 asCParser parser(builder);
00383 int r = parser.ParseStatementBlock(script, func->lastChild);
00384 if( r < 0 ) return -1;
00385 asCScriptNode *block = parser.GetScriptNode();
00386
00387 bool hasReturn;
00388 asCByteCode bc(engine);
00389 LineInstr(&bc, func->lastChild->tokenPos);
00390 CompileStatementBlock(block, false, &hasReturn, &bc);
00391 LineInstr(&bc, func->lastChild->tokenPos + func->lastChild->tokenLength);
00392
00393
00394 if( returnType != asCDataType::CreatePrimitive(ttVoid, false) )
00395 {
00396 if( hasReturn == false )
00397 Error(TXT_NOT_ALL_PATHS_RETURN, func->lastChild);
00398 }
00399
00400
00401
00402
00403
00404 byteCode.InstrWORD(asBC_JitEntry, 0);
00405
00406
00407 int varSize = GetVariableOffset((int)variableAllocations.GetLength()) - 1;
00408 byteCode.Push(varSize);
00409
00410 if( outFunc->objectType )
00411 {
00412
00413 if( m_isConstructor && !m_isConstructorCalled && outFunc->objectType->derivedFrom )
00414 {
00415 byteCode.InstrSHORT(asBC_PSF, 0);
00416 byteCode.Instr(asBC_RDSPTR);
00417 byteCode.Call(asBC_CALL, outFunc->objectType->derivedFrom->beh.construct, AS_PTR_SIZE);
00418 }
00419
00420
00421
00422 byteCode.InstrSHORT(asBC_PSF, 0);
00423 byteCode.Instr(asBC_RDSPTR);
00424 byteCode.Call(asBC_CALLSYS, outFunc->objectType->beh.addref, AS_PTR_SIZE);
00425 }
00426
00427
00428 byteCode.AddCode(&bc);
00429
00430
00431 for( n = (int)variables->variables.GetLength() - 1; n >= 0; n-- )
00432 {
00433 sVariable *v = variables->variables[n];
00434 if( v->stackOffset > 0 )
00435 {
00436
00437 if( v->name != "return" && v->name != "return address" )
00438 CallDestructor(v->type, v->stackOffset, &byteCode);
00439
00440 DeallocateVariable(v->stackOffset);
00441 }
00442 }
00443
00444
00445
00446 byteCode.Label(0);
00447
00448
00449 if( outFunc->objectType )
00450 {
00451 byteCode.InstrSHORT(asBC_PSF, 0);
00452 byteCode.InstrPTR(asBC_FREE, outFunc->objectType);
00453 }
00454
00455
00456 for( n = (int)variables->variables.GetLength() - 1; n >= 0; n-- )
00457 {
00458 sVariable *v = variables->variables[n];
00459 if( v->stackOffset <= 0 )
00460 {
00461
00462 if( v->name != "return" && v->name != "return address" )
00463 CallDestructor(v->type, v->stackOffset, &byteCode);
00464 }
00465
00466
00467 }
00468
00469
00470 if( hasCompileErrors ) return -1;
00471
00472
00473 asASSERT(variableAllocations.GetLength() == freeVariables.GetLength());
00474
00475
00476 RemoveVariableScope();
00477
00478 byteCode.Pop(varSize);
00479
00480 byteCode.Ret(-stackPos);
00481
00482
00483 for( n = 0; n < (signed)variableIsTemporary.GetLength(); n++ )
00484 {
00485 if( variableIsTemporary[n] )
00486 byteCode.DefineTemporaryVariable(GetVariableOffset(n));
00487 }
00488
00489
00490 byteCode.Finalize();
00491
00492
00493 for( n = 0; n < (int)variableAllocations.GetLength(); n++ )
00494 {
00495 if( variableAllocations[n].IsObject() && !variableAllocations[n].IsReference() )
00496 {
00497 objVariableTypes.PushLast(variableAllocations[n].GetObjectType());
00498 objVariablePos.PushLast(GetVariableOffset(n));
00499 }
00500 }
00501
00502 if( hasCompileErrors ) return -1;
00503
00504
00505 outFunc->byteCode.SetLength(byteCode.GetSize());
00506 byteCode.Output(outFunc->byteCode.AddressOf());
00507 outFunc->AddReferences();
00508 outFunc->stackNeeded = byteCode.largestStackUsed;
00509 outFunc->lineNumbers = byteCode.lineNumbers;
00510 outFunc->objVariablePos = objVariablePos;
00511 outFunc->objVariableTypes = objVariableTypes;
00512
00513 #ifdef AS_DEBUG
00514
00515 if( outFunc->objectType )
00516 byteCode.DebugOutput(("__" + outFunc->objectType->name + "_" + outFunc->name + ".txt").AddressOf(), builder->module, engine);
00517 else
00518 byteCode.DebugOutput(("__" + outFunc->name + ".txt").AddressOf(), builder->module, engine);
00519 #endif
00520
00521 return 0;
00522 }
00523
00524
00525
00526
00527
00528 int asCCompiler::CallDefaultConstructor(asCDataType &type, int offset, asCByteCode *bc, asCScriptNode *node, bool isGlobalVar)
00529 {
00530
00531 if( type.IsObject() && !type.IsObjectHandle() )
00532 {
00533 if( type.GetObjectType()->flags & asOBJ_REF )
00534 {
00535 asSExprContext ctx(engine);
00536
00537 int func = 0;
00538 asSTypeBehaviour *beh = type.GetBehaviour();
00539 if( beh ) func = beh->factory;
00540
00541 if( func > 0 )
00542 {
00543 if( !isGlobalVar )
00544 {
00545
00546 PerformFunctionCall(func, &ctx, false, 0, type.GetObjectType(), true, offset);
00547
00548
00549 ctx.bc.Pop(AS_PTR_SIZE);
00550 }
00551 else
00552 {
00553
00554 PerformFunctionCall(func, &ctx, false, 0, type.GetObjectType());
00555
00556
00557 ctx.bc.Instr(asBC_RDSPTR);
00558 ctx.bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(offset));
00559 ctx.bc.InstrPTR(asBC_REFCPY, type.GetObjectType());
00560 ctx.bc.Pop(AS_PTR_SIZE);
00561 ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc);
00562 }
00563
00564 bc->AddCode(&ctx.bc);
00565 }
00566 else
00567 {
00568 asCString str;
00569 str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, type.GetObjectType()->GetName());
00570 Error(str.AddressOf(), node);
00571
00572 return -1;
00573 }
00574 }
00575 else
00576 {
00577 if( isGlobalVar )
00578 bc->InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(offset));
00579 else
00580 bc->InstrSHORT(asBC_PSF, (short)offset);
00581
00582 asSTypeBehaviour *beh = type.GetBehaviour();
00583
00584 int func = 0;
00585 if( beh ) func = beh->construct;
00586
00587
00588
00589 bc->Alloc(asBC_ALLOC, type.GetObjectType(), func, AS_PTR_SIZE);
00590 }
00591 }
00592 return 0;
00593 }
00594
00595 void asCCompiler::CallDestructor(asCDataType &type, int offset, asCByteCode *bc)
00596 {
00597 if( !type.IsReference() )
00598 {
00599
00600 if( type.IsObject() )
00601 {
00602
00603 bc->InstrSHORT(asBC_PSF, (short)offset);
00604 bc->InstrPTR(asBC_FREE, type.GetObjectType());
00605 }
00606 }
00607 }
00608
00609 void asCCompiler::LineInstr(asCByteCode *bc, size_t pos)
00610 {
00611 int r, c;
00612 script->ConvertPosToRowCol(pos, &r, &c);
00613 bc->Line(r, c);
00614 }
00615
00616 void asCCompiler::CompileStatementBlock(asCScriptNode *block, bool ownVariableScope, bool *hasReturn, asCByteCode *bc)
00617 {
00618 *hasReturn = false;
00619 bool isFinished = false;
00620 bool hasWarned = false;
00621
00622 if( ownVariableScope )
00623 AddVariableScope();
00624
00625 asCScriptNode *node = block->firstChild;
00626 while( node )
00627 {
00628 if( !hasWarned && (*hasReturn || isFinished) )
00629 {
00630 hasWarned = true;
00631 Warning(TXT_UNREACHABLE_CODE, node);
00632 }
00633
00634 if( node->nodeType == snBreak || node->nodeType == snContinue )
00635 isFinished = true;
00636
00637 asCByteCode statement(engine);
00638 if( node->nodeType == snDeclaration )
00639 CompileDeclaration(node, &statement);
00640 else
00641 CompileStatement(node, hasReturn, &statement);
00642
00643 LineInstr(bc, node->tokenPos);
00644 bc->AddCode(&statement);
00645
00646 if( !hasCompileErrors )
00647 asASSERT( tempVariables.GetLength() == 0 );
00648
00649 node = node->next;
00650 }
00651
00652 if( ownVariableScope )
00653 {
00654
00655
00656 for( int n = (int)variables->variables.GetLength() - 1; n >= 0; n-- )
00657 {
00658 sVariable *v = variables->variables[n];
00659
00660
00661
00662
00663 if( !isFinished && !*hasReturn )
00664 CallDestructor(v->type, v->stackOffset, bc);
00665
00666
00667 if( v->stackOffset > 0 )
00668 DeallocateVariable(v->stackOffset);
00669 }
00670
00671 RemoveVariableScope();
00672 }
00673 }
00674
00675 int asCCompiler::CompileGlobalVariable(asCBuilder *builder, asCScriptCode *script, asCScriptNode *node, sGlobalVariableDescription *gvar)
00676 {
00677 Reset(builder, script, 0);
00678 globalExpression = true;
00679
00680
00681 AddVariableScope();
00682
00683 asSExprContext ctx(engine);
00684
00685 gvar->isPureConstant = false;
00686
00687
00688 asCParser parser(builder);
00689 if( node )
00690 {
00691 int r = parser.ParseGlobalVarInit(script, node);
00692 if( r < 0 )
00693 return r;
00694
00695 node = parser.GetScriptNode();
00696 }
00697
00698
00699 if( node && node->nodeType == snArgList )
00700 {
00701
00702 if( gvar->datatype.GetObjectType() == 0 || gvar->datatype.IsObjectHandle() )
00703 {
00704 Error(TXT_MUST_BE_OBJECT, node);
00705 }
00706 else
00707 {
00708
00709 asCArray<asSExprContext *> args;
00710 if( CompileArgumentList(node, args) >= 0 )
00711 {
00712
00713 asCArray<int> funcs;
00714 asSTypeBehaviour *beh = gvar->datatype.GetBehaviour();
00715 if( beh )
00716 {
00717 if( gvar->datatype.GetObjectType()->flags & asOBJ_REF )
00718 funcs = beh->factories;
00719 else
00720 funcs = beh->constructors;
00721 }
00722
00723 asCString str = gvar->datatype.Format();
00724 MatchFunctions(funcs, args, node, str.AddressOf());
00725
00726 if( funcs.GetLength() == 1 )
00727 {
00728 if( gvar->datatype.GetObjectType()->flags & asOBJ_REF )
00729 {
00730 MakeFunctionCall(&ctx, funcs[0], 0, args, node);
00731
00732
00733 ctx.bc.Instr(asBC_RDSPTR);
00734 ctx.bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(gvar->index));
00735 ctx.bc.InstrPTR(asBC_REFCPY, gvar->datatype.GetObjectType());
00736 ctx.bc.Pop(AS_PTR_SIZE);
00737 ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc);
00738 }
00739 else
00740 {
00741
00742 ctx.bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(gvar->index));
00743
00744 PrepareFunctionCall(funcs[0], &ctx.bc, args);
00745 MoveArgsToStack(funcs[0], &ctx.bc, args, false);
00746
00747 PerformFunctionCall(funcs[0], &ctx, true, &args, gvar->datatype.GetObjectType());
00748 }
00749 }
00750 }
00751
00752
00753 for( asUINT n = 0; n < args.GetLength(); n++ )
00754 if( args[n] )
00755 {
00756 asDELETE(args[n],asSExprContext);
00757 }
00758 }
00759 }
00760 else if( node && node->nodeType == snInitList )
00761 {
00762 asCTypeInfo ti;
00763 ti.Set(gvar->datatype);
00764 ti.isVariable = false;
00765 ti.isTemporary = false;
00766 ti.stackOffset = (short)gvar->index;
00767
00768 CompileInitList(&ti, node, &ctx.bc);
00769
00770 node = node->next;
00771 }
00772 else
00773 {
00774
00775 if( gvar->datatype.IsObject() && !gvar->datatype.IsObjectHandle() )
00776 {
00777 CallDefaultConstructor(gvar->datatype, gvar->index, &ctx.bc, gvar->idNode, true);
00778 }
00779
00780 if( node )
00781 {
00782 asSExprContext expr(engine);
00783 int r = CompileAssignment(node, &expr); if( r < 0 ) return r;
00784
00785 if( gvar->datatype.IsPrimitive() )
00786 {
00787 if( gvar->datatype.IsReadOnly() && expr.type.isConstant )
00788 {
00789 ImplicitConversion(&expr, gvar->datatype, node, asIC_IMPLICIT_CONV);
00790
00791 gvar->isPureConstant = true;
00792 gvar->constantValue = expr.type.qwordValue;
00793 }
00794
00795 asSExprContext lctx(engine);
00796 lctx.type.Set(gvar->datatype);
00797 lctx.type.dataType.MakeReference(true);
00798 lctx.type.dataType.MakeReadOnly(false);
00799
00800
00801
00802 if( !gvar->isEnumValue )
00803 lctx.bc.InstrWORD(asBC_LDG, (asWORD)builder->module->GetGlobalVarPtrIndex(gvar->index));
00804
00805 DoAssignment(&ctx, &lctx, &expr, node, node, ttAssignment, node);
00806 }
00807 else
00808 {
00809 asSExprContext lexpr(engine);
00810 lexpr.type.Set(gvar->datatype);
00811 lexpr.type.dataType.MakeReference(true);
00812 lexpr.type.dataType.MakeReadOnly(false);
00813 lexpr.type.stackOffset = -1;
00814
00815 if( gvar->datatype.IsObjectHandle() )
00816 lexpr.type.isExplicitHandle = true;
00817
00818 lexpr.bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(gvar->index));
00819
00820
00821
00822
00823
00824
00825 bool assigned = false;
00826 if( lexpr.type.dataType.IsObject() && !lexpr.type.isExplicitHandle )
00827 {
00828 assigned = CompileOverloadedDualOperator(node, &lexpr, &expr, &ctx);
00829 if( assigned )
00830 {
00831
00832 ctx.bc.Pop(ctx.type.dataType.GetSizeOnStackDWords());
00833
00834
00835 ProcessDeferredParams(&ctx);
00836 }
00837 }
00838
00839 #ifdef AS_DEPRECATED
00840 if( !assigned )
00841 {
00842 asSTypeBehaviour *beh = 0;
00843 if( !lexpr.type.isExplicitHandle )
00844 beh = lexpr.type.dataType.GetBehaviour();
00845 if( beh )
00846 {
00847
00848 int op = asBEHAVE_ASSIGNMENT;
00849 asCArray<int> ops;
00850 asUINT n;
00851 for( n = 0; n < beh->operators.GetLength(); n += 2 )
00852 {
00853 if( op == beh->operators[n] )
00854 ops.PushLast(beh->operators[n+1]);
00855 }
00856
00857 asCArray<int> match;
00858 MatchArgument(ops, match, &expr.type, 0);
00859
00860 if( match.GetLength() > 0 )
00861 assigned = true;
00862
00863 if( match.GetLength() == 1 )
00864 {
00865
00866 if( lexpr.type.dataType.IsArrayType() )
00867 if( !lexpr.type.dataType.IsEqualExceptRefAndConst(expr.type.dataType) )
00868 Error(TXT_BOTH_MUST_BE_SAME, node);
00869
00870 asCScriptFunction *descr = engine->scriptFunctions[match[0]];
00871
00872
00873 MergeExprContexts(&ctx, &expr);
00874
00875 PrepareArgument(&descr->parameterTypes[0], &expr, node, true, descr->inOutFlags[0]);
00876 MergeExprContexts(&ctx, &expr);
00877
00878
00879 asCArray<asSExprContext*> args;
00880 args.PushLast(&expr);
00881 MoveArgsToStack(match[0], &ctx.bc, args, false);
00882
00883
00884 ctx.bc.AddCode(&lexpr.bc);
00885 ctx.bc.Instr(asBC_RDSPTR);
00886
00887 PerformFunctionCall(match[0], &ctx, false, &args);
00888
00889 ctx.bc.Pop(ctx.type.dataType.GetSizeOnStackDWords());
00890
00891 ProcessDeferredParams(&ctx);
00892 }
00893 else if( match.GetLength() > 1 )
00894 {
00895 Error(TXT_MORE_THAN_ONE_MATCHING_OP, node);
00896 }
00897 }
00898 }
00899 #endif
00900 if( !assigned )
00901 {
00902 PrepareForAssignment(&lexpr.type.dataType, &expr, node);
00903
00904
00905
00906
00907 if( gvar->datatype.IsReadOnly() && expr.type.isConstant )
00908 {
00909 gvar->isPureConstant = true;
00910 gvar->constantValue = expr.type.qwordValue;
00911 }
00912
00913
00914 MergeExprContexts(&ctx, &expr);
00915
00916
00917 ctx.bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(gvar->index));
00918
00919 PerformAssignment(&lexpr.type, &expr.type, &ctx.bc, node);
00920
00921
00922 ReleaseTemporaryVariable(expr.type, &ctx.bc);
00923
00924 ctx.bc.Pop(expr.type.dataType.GetSizeOnStackDWords());
00925 }
00926 }
00927 }
00928 }
00929
00930
00931 int varSize = GetVariableOffset((int)variableAllocations.GetLength()) - 1;
00932
00933
00934
00935 int n;
00936 for( n = 0; n < varSize; n++ )
00937 byteCode.InstrINT(asBC_PshC4, 0);
00938
00939 byteCode.AddCode(&ctx.bc);
00940
00941
00942 for( n = (int)variables->variables.GetLength() - 1; n >= 0; --n )
00943 {
00944 sVariable *v = variables->variables[n];
00945
00946
00947 CallDestructor(v->type, v->stackOffset, &byteCode);
00948
00949 DeallocateVariable(v->stackOffset);
00950 }
00951
00952 if( hasCompileErrors ) return -1;
00953
00954
00955 asASSERT(variableAllocations.GetLength() == freeVariables.GetLength());
00956
00957
00958 RemoveVariableScope();
00959
00960 byteCode.Pop(varSize);
00961
00962 return 0;
00963 }
00964
00965 void asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, asCScriptNode *node, bool isFunction, int refType, asCArray<int> *reservedVars)
00966 {
00967 asCDataType param = *paramType;
00968 if( paramType->GetTokenType() == ttQuestion )
00969 {
00970
00971 param = ctx->type.dataType;
00972 param.MakeHandle(ctx->type.isExplicitHandle);
00973 param.MakeReference(paramType->IsReference());
00974 param.MakeReadOnly(paramType->IsReadOnly());
00975 }
00976 else
00977 param = *paramType;
00978
00979 asCDataType dt = param;
00980
00981
00982 if( isFunction && dt.IsReference() )
00983 {
00984 if( paramType->GetTokenType() == ttQuestion )
00985 {
00986 asCByteCode tmpBC(engine);
00987
00988
00989 tmpBC.InstrDWORD(asBC_TYPEID, engine->GetTypeIdFromDataType(param));
00990
00991
00992 tmpBC.AddCode(&ctx->bc);
00993 ctx->bc.AddCode(&tmpBC);
00994 }
00995
00996
00997 dt.MakeReference(false);
00998 dt.MakeReadOnly(false);
00999
01000 int offset;
01001 if( refType == 1 )
01002 {
01003 ProcessPropertyGetAccessor(ctx, node);
01004
01005
01006
01007 if( dt.IsPrimitive() || dt.IsNullHandle() )
01008 {
01009 IsVariableInitialized(&ctx->type, node);
01010
01011 if( ctx->type.dataType.IsReference() ) ConvertToVariable(ctx);
01012 ImplicitConversion(ctx, dt, node, asIC_IMPLICIT_CONV, true, reservedVars);
01013
01014 if( !(param.IsReadOnly() && ctx->type.isVariable) )
01015 ConvertToTempVariable(ctx);
01016
01017 PushVariableOnStack(ctx, true);
01018 ctx->type.dataType.MakeReadOnly(param.IsReadOnly());
01019 }
01020 else
01021 {
01022 IsVariableInitialized(&ctx->type, node);
01023
01024 ImplicitConversion(ctx, param, node, asIC_IMPLICIT_CONV, true, reservedVars);
01025
01026 if( !ctx->type.dataType.IsEqualExceptRef(param) )
01027 {
01028 asCString str;
01029 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, ctx->type.dataType.Format().AddressOf(), param.Format().AddressOf());
01030 Error(str.AddressOf(), node);
01031
01032 ctx->type.Set(param);
01033 }
01034
01035
01036
01037
01038
01039
01040 if( !ctx->type.isTemporary && !(param.IsReadOnly() && ctx->type.isVariable))
01041 {
01042
01043 asCArray<int> vars;
01044 ctx->bc.GetVarsUsed(vars);
01045 if( reservedVars ) vars.Concatenate(*reservedVars);
01046 offset = AllocateVariableNotIn(dt, true, &vars);
01047
01048
01049 asCByteCode tmpBC(engine);
01050 CallDefaultConstructor(dt, offset, &tmpBC, node);
01051
01052
01053 tmpBC.AddCode(&ctx->bc);
01054 ctx->bc.AddCode(&tmpBC);
01055
01056
01057 PrepareForAssignment(&dt, ctx, node);
01058
01059 dt.MakeReference(true);
01060 asCTypeInfo type;
01061 type.Set(dt);
01062 type.isTemporary = true;
01063 type.stackOffset = (short)offset;
01064
01065 if( dt.IsObjectHandle() )
01066 type.isExplicitHandle = true;
01067
01068 ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
01069
01070 PerformAssignment(&type, &ctx->type, &ctx->bc, node);
01071
01072 ctx->bc.Pop(ctx->type.dataType.GetSizeOnStackDWords());
01073
01074 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
01075
01076 ctx->type = type;
01077
01078 ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
01079 if( dt.IsObject() && !dt.IsObjectHandle() )
01080 ctx->bc.Instr(asBC_RDSPTR);
01081
01082 if( paramType->IsReadOnly() )
01083 ctx->type.dataType.MakeReadOnly(true);
01084 }
01085 }
01086 }
01087 else if( refType == 2 )
01088 {
01089
01090 asCArray<int> vars;
01091 ctx->bc.GetVarsUsed(vars);
01092 if( reservedVars ) vars.Concatenate(*reservedVars);
01093 offset = AllocateVariableNotIn(dt, true, &vars);
01094
01095 if( dt.IsPrimitive() )
01096 {
01097 ctx->type.SetVariable(dt, offset, true);
01098 PushVariableOnStack(ctx, true);
01099 }
01100 else
01101 {
01102
01103 asCByteCode tmpBC(engine);
01104 CallDefaultConstructor(dt, offset, &tmpBC, node);
01105
01106
01107 tmpBC.AddCode(&ctx->bc);
01108 ctx->bc.AddCode(&tmpBC);
01109
01110 dt.MakeReference((!dt.IsObject() || dt.IsObjectHandle()));
01111 asCTypeInfo type;
01112 type.Set(dt);
01113 type.isTemporary = true;
01114 type.stackOffset = (short)offset;
01115
01116 ctx->type = type;
01117
01118 ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
01119 if( dt.IsObject() && !dt.IsObjectHandle() )
01120 ctx->bc.Instr(asBC_RDSPTR);
01121 }
01122
01123
01124
01125 }
01126 else if( refType == asTM_INOUTREF )
01127 {
01128
01129 if( !ctx->type.isVariable && ctx->type.isConstant )
01130 {
01131 Error(TXT_NOT_VALID_REFERENCE, node);
01132 }
01133
01134
01135
01136
01137
01138 if( !engine->ep.allowUnsafeReferences &&
01139 !ctx->type.isVariable &&
01140 ctx->type.dataType.IsObject() &&
01141 !ctx->type.dataType.IsObjectHandle() &&
01142 ctx->type.dataType.GetBehaviour()->addref &&
01143 ctx->type.dataType.GetBehaviour()->release )
01144 {
01145
01146 asSExprContext tmp(engine);
01147 asCDataType dt = ctx->type.dataType;
01148 dt.MakeHandle(true);
01149 dt.MakeReference(false);
01150
01151 asCArray<int> vars;
01152 ctx->bc.GetVarsUsed(vars);
01153 if( reservedVars ) vars.Concatenate(*reservedVars);
01154 offset = AllocateVariableNotIn(dt, true, &vars);
01155
01156
01157 if( !ctx->type.dataType.IsObjectHandle() && ctx->type.dataType.IsReference() )
01158 ctx->bc.Instr(asBC_RDSPTR);
01159 ctx->bc.InstrWORD(asBC_PSF, (asWORD)offset);
01160 ctx->bc.InstrPTR(asBC_REFCPY, ctx->type.dataType.GetObjectType());
01161 ctx->bc.Pop(AS_PTR_SIZE);
01162 ctx->bc.InstrWORD(asBC_PSF, (asWORD)offset);
01163
01164 dt.MakeHandle(false);
01165 dt.MakeReference(true);
01166
01167
01168 if( ctx->type.isTemporary )
01169 {
01170 ReleaseTemporaryVariable(ctx->type.stackOffset, &ctx->bc);
01171 }
01172
01173 ctx->type.SetVariable(dt, offset, true);
01174 }
01175
01176
01177 if( ctx->type.dataType.IsObject() && ctx->type.dataType.IsReference() )
01178 Dereference(ctx, true);
01179 else if( ctx->type.isVariable )
01180 ctx->bc.InstrSHORT(asBC_PSF, ctx->type.stackOffset);
01181 else if( ctx->type.dataType.IsPrimitive() )
01182 ctx->bc.Instr(asBC_PshRPtr);
01183 }
01184 }
01185 else
01186 {
01187 ProcessPropertyGetAccessor(ctx, node);
01188
01189 if( dt.IsPrimitive() )
01190 {
01191 IsVariableInitialized(&ctx->type, node);
01192
01193 if( ctx->type.dataType.IsReference() ) ConvertToVariable(ctx);
01194
01195
01196 ImplicitConversion(ctx, dt, node, asIC_IMPLICIT_CONV, true, reservedVars);
01197
01198 if( ctx->type.isVariable )
01199 {
01200 PushVariableOnStack(ctx, dt.IsReference());
01201 }
01202 else if( ctx->type.isConstant )
01203 {
01204 ConvertToVariable(ctx);
01205 PushVariableOnStack(ctx, dt.IsReference());
01206 }
01207 }
01208 else
01209 {
01210 IsVariableInitialized(&ctx->type, node);
01211
01212
01213 ImplicitConversion(ctx, dt, node, asIC_IMPLICIT_CONV, true, reservedVars);
01214
01215
01216 if( !ctx->type.dataType.IsEqualExceptRef(dt) )
01217 {
01218 asCString str;
01219 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, ctx->type.dataType.Format().AddressOf(), dt.Format().AddressOf());
01220 Error(str.AddressOf(), node);
01221
01222 ctx->type.Set(dt);
01223 }
01224
01225 if( dt.IsObjectHandle() )
01226 ctx->type.isExplicitHandle = true;
01227
01228 if( dt.IsObject() )
01229 {
01230 if( !dt.IsReference() )
01231 {
01232
01233
01234 PrepareTemporaryObject(node, ctx, reservedVars);
01235
01236
01237
01238
01239 dt.MakeReference(true);
01240 }
01241 else
01242 {
01243
01244
01245 dt.MakeReference(false);
01246 }
01247 }
01248 }
01249 }
01250
01251
01252 if( param.IsReference() || param.IsObject() )
01253 {
01254
01255 if( refType != 3 )
01256 {
01257 ctx->bc.Pop(AS_PTR_SIZE);
01258 ctx->bc.InstrSHORT(asBC_VAR, ctx->type.stackOffset);
01259 }
01260
01261 ProcessDeferredParams(ctx);
01262 }
01263 }
01264
01265 void asCCompiler::PrepareFunctionCall(int funcID, asCByteCode *bc, asCArray<asSExprContext *> &args)
01266 {
01267
01268 asCScriptFunction *descr = builder->GetFunctionDescription(funcID);
01269
01270
01271 asSExprContext e(engine);
01272 int n;
01273 for( n = (int)args.GetLength()-1; n >= 0; n-- )
01274 {
01275
01276
01277 asCArray<int> reservedVars;
01278 for( int m = n-1; m >= 0; m-- )
01279 args[m]->bc.GetVarsUsed(reservedVars);
01280
01281 PrepareArgument2(&e, args[n], &descr->parameterTypes[n], true, descr->inOutFlags[n], &reservedVars);
01282 }
01283
01284 bc->AddCode(&e.bc);
01285 }
01286
01287 void asCCompiler::MoveArgsToStack(int funcID, asCByteCode *bc, asCArray<asSExprContext *> &args, bool addOneToOffset)
01288 {
01289 asCScriptFunction *descr = builder->GetFunctionDescription(funcID);
01290
01291 int offset = 0;
01292 if( addOneToOffset )
01293 offset += AS_PTR_SIZE;
01294
01295
01296 for( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
01297 {
01298 if( descr->parameterTypes[n].IsReference() )
01299 {
01300 if( descr->parameterTypes[n].IsObject() && !descr->parameterTypes[n].IsObjectHandle() )
01301 {
01302 if( descr->inOutFlags[n] != asTM_INOUTREF )
01303 bc->InstrWORD(asBC_GETOBJREF, (asWORD)offset);
01304 if( args[n]->type.dataType.IsObjectHandle() )
01305 bc->InstrWORD(asBC_ChkNullS, (asWORD)offset);
01306 }
01307 else if( descr->inOutFlags[n] != asTM_INOUTREF )
01308 {
01309 if( descr->parameterTypes[n].GetTokenType() == ttQuestion &&
01310 args[n]->type.dataType.IsObject() && !args[n]->type.dataType.IsObjectHandle() )
01311 {
01312
01313
01314 bc->InstrWORD(asBC_GETOBJREF, (asWORD)offset);
01315 }
01316 else
01317 bc->InstrWORD(asBC_GETREF, (asWORD)offset);
01318 }
01319 }
01320 else if( descr->parameterTypes[n].IsObject() )
01321 {
01322 bc->InstrWORD(asBC_GETOBJ, (asWORD)offset);
01323
01324
01325 DeallocateVariable(args[n]->type.stackOffset);
01326 args[n]->type.isTemporary = false;
01327 }
01328
01329 offset += descr->parameterTypes[n].GetSizeOnStackDWords();
01330 }
01331 }
01332
01333 int asCCompiler::CompileArgumentList(asCScriptNode *node, asCArray<asSExprContext*> &args)
01334 {
01335 asASSERT(node->nodeType == snArgList);
01336
01337
01338 asCScriptNode *arg = node->firstChild;
01339 int argCount = 0;
01340 while( arg )
01341 {
01342 argCount++;
01343 arg = arg->next;
01344 }
01345
01346
01347 args.SetLength(argCount);
01348 int n;
01349 for( n = 0; n < argCount; n++ )
01350 args[n] = 0;
01351
01352 n = argCount-1;
01353
01354
01355 bool anyErrors = false;
01356 arg = node->lastChild;
01357 while( arg )
01358 {
01359 asSExprContext expr(engine);
01360 int r = CompileAssignment(arg, &expr);
01361 if( r < 0 ) anyErrors = true;
01362
01363 args[n] = asNEW(asSExprContext)(engine);
01364 MergeExprContexts(args[n], &expr);
01365 args[n]->type = expr.type;
01366 args[n]->property_get = expr.property_get;
01367 args[n]->property_set = expr.property_set;
01368 args[n]->property_const = expr.property_const;
01369 args[n]->exprNode = arg;
01370
01371 n--;
01372 arg = arg->prev;
01373 }
01374
01375 return anyErrors ? -1 : 0;
01376 }
01377
01378 void asCCompiler::MatchFunctions(asCArray<int> &funcs, asCArray<asSExprContext*> &args, asCScriptNode *node, const char *name, asCObjectType *objectType, bool isConstMethod, bool silent, bool allowObjectConstruct, const asCString &scope)
01379 {
01380 asUINT n;
01381 if( funcs.GetLength() > 0 )
01382 {
01383
01384 for( n = 0; n < funcs.GetLength(); ++n )
01385 {
01386 asCScriptFunction *desc = builder->GetFunctionDescription(funcs[n]);
01387
01388 if( desc->parameterTypes.GetLength() != args.GetLength() )
01389 {
01390
01391 if( n == funcs.GetLength()-1 )
01392 funcs.PopLast();
01393 else
01394 funcs[n] = funcs.PopLast();
01395 n--;
01396 }
01397 }
01398
01399
01400 asCArray<int> matchingFuncs = funcs;
01401
01402 for( n = 0; n < args.GetLength(); ++n )
01403 {
01404 asCArray<int> tempFuncs;
01405 MatchArgument(funcs, tempFuncs, &args[n]->type, n, allowObjectConstruct);
01406
01407
01408 for( asUINT f = 0; f < matchingFuncs.GetLength(); f++ )
01409 {
01410 asUINT c;
01411 for( c = 0; c < tempFuncs.GetLength(); c++ )
01412 {
01413 if( matchingFuncs[f] == tempFuncs[c] )
01414 break;
01415 }
01416
01417
01418 if( c == tempFuncs.GetLength() )
01419 {
01420
01421 if( f == matchingFuncs.GetLength()-1 )
01422 matchingFuncs.PopLast();
01423 else
01424 matchingFuncs[f] = matchingFuncs.PopLast();
01425 f--;
01426 }
01427 }
01428 }
01429
01430 funcs = matchingFuncs;
01431 }
01432
01433 if( !isConstMethod )
01434 FilterConst(funcs);
01435
01436 if( funcs.GetLength() != 1 && !silent )
01437 {
01438
01439 asCString str;
01440 if( scope != "" )
01441 {
01442 if( scope == "::" )
01443 str = scope;
01444 else
01445 str = scope + "::";
01446 }
01447 str += name;
01448 str += "(";
01449 if( args.GetLength() )
01450 str += args[0]->type.dataType.Format();
01451 for( n = 1; n < args.GetLength(); n++ )
01452 str += ", " + args[n]->type.dataType.Format();
01453 str += ")";
01454
01455 if( isConstMethod )
01456 str += " const";
01457
01458 if( objectType && scope == "" )
01459 str = objectType->name + "::" + str;
01460
01461 if( funcs.GetLength() == 0 )
01462 {
01463 str.Format(TXT_NO_MATCHING_SIGNATURES_TO_s, str.AddressOf());
01464 Error(str.AddressOf(), node);
01465 }
01466 else
01467 {
01468 str.Format(TXT_MULTIPLE_MATCHING_SIGNATURES_TO_s, str.AddressOf());
01469 Error(str.AddressOf(), node);
01470
01471 PrintMatchingFuncs(funcs, node);
01472 }
01473 }
01474 }
01475
01476 void asCCompiler::CompileDeclaration(asCScriptNode *decl, asCByteCode *bc)
01477 {
01478
01479 asCDataType type = builder->CreateDataTypeFromNode(decl->firstChild, script);
01480
01481
01482 asCScriptNode *node = decl->firstChild->next;
01483 while( node )
01484 {
01485
01486 if( !type.CanBeInstanciated() )
01487 {
01488 asCString str;
01489
01490 str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format().AddressOf());
01491 Error(str.AddressOf(), node);
01492
01493
01494 type = asCDataType::CreatePrimitive(ttInt, false);
01495 }
01496
01497
01498 asCString name(&script->code[node->tokenPos], node->tokenLength);
01499
01500
01501 if( engine->GetObjectType(name.AddressOf()) != 0 )
01502 {
01503 asCString str;
01504 str.Format(TXT_ILLEGAL_VARIABLE_NAME_s, name.AddressOf());
01505 Error(str.AddressOf(), node);
01506 }
01507
01508 int offset = AllocateVariable(type, false);
01509 if( variables->DeclareVariable(name.AddressOf(), type, offset) < 0 )
01510 {
01511 asCString str;
01512 str.Format(TXT_s_ALREADY_DECLARED, name.AddressOf());
01513 Error(str.AddressOf(), node);
01514 }
01515
01516 outFunc->AddVariable(name, type, offset);
01517
01518
01519 asCScriptNode *varNode = node;
01520
01521 node = node->next;
01522 if( node && node->nodeType == snArgList )
01523 {
01524
01525 if( type.GetObjectType() == 0 || type.IsObjectHandle() )
01526 {
01527 Error(TXT_MUST_BE_OBJECT, node);
01528 }
01529 else
01530 {
01531
01532 asCArray<asSExprContext *> args;
01533
01534 if( CompileArgumentList(node, args) >= 0 )
01535 {
01536
01537 asCArray<int> funcs;
01538 asSTypeBehaviour *beh = type.GetBehaviour();
01539 if( beh )
01540 {
01541 if( type.GetObjectType()->flags & asOBJ_REF )
01542 funcs = beh->factories;
01543 else
01544 funcs = beh->constructors;
01545 }
01546
01547 asCString str = type.Format();
01548 MatchFunctions(funcs, args, node, str.AddressOf());
01549
01550 if( funcs.GetLength() == 1 )
01551 {
01552 sVariable *v = variables->GetVariable(name.AddressOf());
01553 asSExprContext ctx(engine);
01554 if( v->type.GetObjectType()->flags & asOBJ_REF )
01555 {
01556 MakeFunctionCall(&ctx, funcs[0], 0, args, node, true, v->stackOffset);
01557
01558
01559 ctx.bc.Pop(AS_PTR_SIZE);
01560 }
01561 else
01562 {
01563 ctx.bc.InstrSHORT(asBC_VAR, (short)v->stackOffset);
01564
01565 PrepareFunctionCall(funcs[0], &ctx.bc, args);
01566 MoveArgsToStack(funcs[0], &ctx.bc, args, false);
01567
01568 int offset = 0;
01569 asCScriptFunction *descr = builder->GetFunctionDescription(funcs[0]);
01570 for( asUINT n = 0; n < args.GetLength(); n++ )
01571 offset += descr->parameterTypes[n].GetSizeOnStackDWords();
01572
01573 ctx.bc.InstrWORD(asBC_GETREF, (asWORD)offset);
01574
01575 PerformFunctionCall(funcs[0], &ctx, true, &args, type.GetObjectType());
01576 }
01577 bc->AddCode(&ctx.bc);
01578 }
01579 }
01580
01581
01582 for( asUINT n = 0; n < args.GetLength(); n++ )
01583 if( args[n] )
01584 {
01585 asDELETE(args[n],asSExprContext);
01586 }
01587 }
01588
01589 node = node->next;
01590 }
01591 else if( node && node->nodeType == snInitList )
01592 {
01593 sVariable *v = variables->GetVariable(name.AddressOf());
01594
01595 asCTypeInfo ti;
01596 ti.Set(type);
01597 ti.isVariable = true;
01598 ti.isTemporary = false;
01599 ti.stackOffset = (short)v->stackOffset;
01600
01601 CompileInitList(&ti, node, bc);
01602
01603 node = node->next;
01604 }
01605 else
01606 {
01607 asSExprContext ctx(engine);
01608
01609
01610 CallDefaultConstructor(type, offset, &ctx.bc, varNode);
01611
01612
01613 if( node && node->nodeType == snAssignment )
01614 {
01615
01616 asSExprContext expr(engine);
01617 int r = CompileAssignment(node, &expr);
01618 if( r >= 0 )
01619 {
01620 if( type.IsPrimitive() )
01621 {
01622 if( type.IsReadOnly() && expr.type.isConstant )
01623 {
01624 ImplicitConversion(&expr, type, node, asIC_IMPLICIT_CONV);
01625
01626 sVariable *v = variables->GetVariable(name.AddressOf());
01627 v->isPureConstant = true;
01628 v->constantValue = expr.type.qwordValue;
01629 }
01630
01631 asSExprContext lctx(engine);
01632 lctx.type.SetVariable(type, offset, false);
01633 lctx.type.dataType.MakeReadOnly(false);
01634
01635 DoAssignment(&ctx, &lctx, &expr, node, node, ttAssignment, node);
01636 }
01637 else
01638 {
01639
01640
01641 asSExprContext lexpr(engine);
01642 lexpr.type.Set(type);
01643 lexpr.type.dataType.MakeReference(true);
01644
01645 lexpr.type.dataType.MakeReadOnly(false);
01646
01647 if( type.IsObjectHandle() )
01648 lexpr.type.isExplicitHandle = true;
01649
01650 sVariable *v = variables->GetVariable(name.AddressOf());
01651 lexpr.bc.InstrSHORT(asBC_PSF, (short)v->stackOffset);
01652 lexpr.type.stackOffset = (short)v->stackOffset;
01653
01654
01655
01656
01657
01658
01659
01660 bool assigned = false;
01661 if( lexpr.type.dataType.IsObject() && !lexpr.type.isExplicitHandle )
01662 {
01663 assigned = CompileOverloadedDualOperator(node, &lexpr, &expr, &ctx);
01664 if( assigned )
01665 {
01666
01667 ctx.bc.Pop(ctx.type.dataType.GetSizeOnStackDWords());
01668
01669
01670 ProcessDeferredParams(&ctx);
01671 }
01672 }
01673 #ifdef AS_DEPRECATED
01674 if( !assigned )
01675 {
01676 asSTypeBehaviour *beh = 0;
01677 if( !lexpr.type.isExplicitHandle )
01678 beh = lexpr.type.dataType.GetBehaviour();
01679 bool assigned = false;
01680 if( beh )
01681 {
01682
01683 int op = asBEHAVE_ASSIGNMENT;
01684 asCArray<int> ops;
01685 asUINT n;
01686 for( n = 0; n < beh->operators.GetLength(); n += 2 )
01687 {
01688 if( op == beh->operators[n] )
01689 ops.PushLast(beh->operators[n+1]);
01690 }
01691
01692 asCArray<int> match;
01693 MatchArgument(ops, match, &expr.type, 0);
01694
01695 if( match.GetLength() > 0 )
01696 assigned = true;
01697
01698 if( match.GetLength() == 1 )
01699 {
01700
01701 if( lexpr.type.dataType.IsArrayType() )
01702 if( !lexpr.type.dataType.IsEqualExceptRefAndConst(expr.type.dataType) )
01703 Error(TXT_BOTH_MUST_BE_SAME, node);
01704
01705 asCScriptFunction *descr = engine->scriptFunctions[match[0]];
01706
01707
01708 MergeExprContexts(&ctx, &expr);
01709
01710 PrepareArgument(&descr->parameterTypes[0], &expr, node, true, descr->inOutFlags[0]);
01711 MergeExprContexts(&ctx, &expr);
01712
01713 asCArray<asSExprContext*> args;
01714 args.PushLast(&expr);
01715 MoveArgsToStack(match[0], &ctx.bc, args, false);
01716
01717
01718 ctx.bc.AddCode(&lexpr.bc);
01719 ctx.bc.Instr(asBC_RDSPTR);
01720
01721 PerformFunctionCall(match[0], &ctx, false, &args);
01722
01723 ctx.bc.Pop(ctx.type.dataType.GetSizeOnStackDWords());
01724
01725 ProcessDeferredParams(&ctx);
01726 }
01727 else if( match.GetLength() > 1 )
01728 {
01729 Error(TXT_MORE_THAN_ONE_MATCHING_OP, node);
01730 }
01731 }
01732 }
01733 #endif
01734 if( !assigned )
01735 {
01736 PrepareForAssignment(&lexpr.type.dataType, &expr, node);
01737
01738
01739
01740
01741 if( v->type.IsReadOnly() && expr.type.isConstant )
01742 {
01743 v->isPureConstant = true;
01744 v->constantValue = expr.type.qwordValue;
01745 }
01746
01747
01748 MergeExprContexts(&ctx, &expr);
01749
01750
01751 ctx.bc.AddCode(&lexpr.bc);
01752 lexpr.type.stackOffset = (short)v->stackOffset;
01753
01754 PerformAssignment(&lexpr.type, &expr.type, &ctx.bc, node->prev);
01755
01756
01757 ReleaseTemporaryVariable(expr.type, &ctx.bc);
01758
01759 ctx.bc.Pop(expr.type.dataType.GetSizeOnStackDWords());
01760
01761 ProcessDeferredParams(&ctx);
01762 }
01763 }
01764 }
01765
01766 node = node->next;
01767 }
01768
01769 bc->AddCode(&ctx.bc);
01770
01771
01772 }
01773 }
01774 }
01775
01776 void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByteCode *bc)
01777 {
01778 if( var->dataType.IsArrayType() && !var->dataType.IsObjectHandle() )
01779 {
01780
01781 int countElements = 0;
01782 asCScriptNode *el = node->firstChild;
01783 while( el )
01784 {
01785 countElements++;
01786 el = el->next;
01787 }
01788
01789
01790
01791
01792 asCArray<int> funcs;
01793 if( var->dataType.GetObjectType()->flags & asOBJ_REF )
01794 funcs = var->dataType.GetBehaviour()->factories;
01795 else
01796 funcs = var->dataType.GetBehaviour()->constructors;
01797
01798 asCArray<asSExprContext *> args;
01799 asSExprContext arg1(engine);
01800 arg1.bc.InstrDWORD(asBC_PshC4, countElements);
01801 arg1.type.Set(asCDataType::CreatePrimitive(ttUInt, false));
01802 args.PushLast(&arg1);
01803
01804 asCString str = var->dataType.Format();
01805 MatchFunctions(funcs, args, node, str.AddressOf());
01806
01807 if( funcs.GetLength() == 1 )
01808 {
01809 asSExprContext ctx(engine);
01810
01811 if( var->dataType.GetObjectType()->flags & asOBJ_REF )
01812 {
01813 PrepareFunctionCall(funcs[0], &ctx.bc, args);
01814 MoveArgsToStack(funcs[0], &ctx.bc, args, false);
01815
01816 if( var->isVariable )
01817 {
01818
01819 PerformFunctionCall(funcs[0], &ctx, false, &args, 0, true, var->stackOffset);
01820 ctx.bc.Pop(AS_PTR_SIZE);
01821 }
01822 else
01823 {
01824 PerformFunctionCall(funcs[0], &ctx, false, &args);
01825
01826
01827 ctx.bc.Instr(asBC_RDSPTR);
01828 ctx.bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(var->stackOffset));
01829 ctx.bc.InstrPTR(asBC_REFCPY, var->dataType.GetObjectType());
01830 ctx.bc.Pop(AS_PTR_SIZE);
01831 ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc);
01832 }
01833 }
01834 else
01835 {
01836 if( var->isVariable )
01837 ctx.bc.InstrSHORT(asBC_PSF, var->stackOffset);
01838 else
01839 ctx.bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(var->stackOffset));
01840
01841 PrepareFunctionCall(funcs[0], &ctx.bc, args);
01842 MoveArgsToStack(funcs[0], &ctx.bc, args, false);
01843
01844 PerformFunctionCall(funcs[0], &ctx, true, &args, var->dataType.GetObjectType());
01845 }
01846
01847 bc->AddCode(&ctx.bc);
01848 }
01849 else
01850 return;
01851
01852
01853 asCDataType retType;
01854 retType = var->dataType.GetSubType();
01855 retType.MakeReference(true);
01856 retType.MakeReadOnly(false);
01857 int funcId = 0;
01858 asSTypeBehaviour *beh = var->dataType.GetBehaviour();
01859 for( asUINT n = 0; n < beh->operators.GetLength(); n += 2 )
01860 {
01861 if( asBEHAVE_INDEX == beh->operators[n] )
01862 {
01863 asCScriptFunction *desc = builder->GetFunctionDescription(beh->operators[n+1]);
01864 if( !desc->isReadOnly &&
01865 desc->parameterTypes.GetLength() == 1 &&
01866 (desc->parameterTypes[0] == asCDataType::CreatePrimitive(ttUInt, false) ||
01867 desc->parameterTypes[0] == asCDataType::CreatePrimitive(ttInt, false)) &&
01868 desc->returnType == retType )
01869 {
01870 funcId = beh->operators[n+1];
01871 break;
01872 }
01873 }
01874 }
01875
01876 if( funcId == 0 )
01877 {
01878 Error(TXT_NO_APPROPRIATE_INDEX_OPERATOR, node);
01879 return;
01880 }
01881
01882 asUINT index = 0;
01883 el = node->firstChild;
01884 while( el )
01885 {
01886 if( el->nodeType == snAssignment || el->nodeType == snInitList )
01887 {
01888 asSExprContext lctx(engine);
01889 asSExprContext rctx(engine);
01890
01891 if( el->nodeType == snAssignment )
01892 {
01893
01894 CompileAssignment(el, &rctx);
01895 }
01896 else if( el->nodeType == snInitList )
01897 {
01898 int offset = AllocateVariable(var->dataType.GetSubType(), true);
01899
01900 rctx.type.Set(var->dataType.GetSubType());
01901 rctx.type.isVariable = true;
01902 rctx.type.isTemporary = true;
01903 rctx.type.stackOffset = (short)offset;
01904
01905 CompileInitList(&rctx.type, el, &rctx.bc);
01906
01907
01908 rctx.bc.InstrSHORT(asBC_PSF, rctx.type.stackOffset);
01909
01910
01911 rctx.type.dataType.MakeReference(true);
01912 }
01913
01914
01915 lctx.bc.InstrDWORD(asBC_PshC4, index);
01916 if( var->isVariable )
01917 lctx.bc.InstrSHORT(asBC_PSF, var->stackOffset);
01918 else
01919 lctx.bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(var->stackOffset));
01920 lctx.bc.Instr(asBC_RDSPTR);
01921 lctx.bc.Call(asBC_CALLSYS, funcId, 1+AS_PTR_SIZE);
01922
01923 if( !var->dataType.GetSubType().IsPrimitive() )
01924 lctx.bc.Instr(asBC_PshRPtr);
01925
01926 lctx.type.Set(var->dataType.GetSubType());
01927
01928 if( !lctx.type.dataType.IsObject() || lctx.type.dataType.IsObjectHandle() )
01929 lctx.type.dataType.MakeReference(true);
01930
01931
01932 if( lctx.type.dataType.IsObjectHandle() )
01933 lctx.type.isExplicitHandle = true;
01934
01935 asSExprContext ctx(engine);
01936 DoAssignment(&ctx, &lctx, &rctx, el, el, ttAssignment, el);
01937
01938 if( !lctx.type.dataType.IsPrimitive() )
01939 ctx.bc.Pop(AS_PTR_SIZE);
01940
01941
01942 ReleaseTemporaryVariable(ctx.type, &ctx.bc);
01943
01944 ProcessDeferredParams(&ctx);
01945
01946 bc->AddCode(&ctx.bc);
01947 }
01948
01949 el = el->next;
01950 index++;
01951 }
01952 }
01953 else
01954 {
01955 asCString str;
01956 str.Format(TXT_INIT_LIST_CANNOT_BE_USED_WITH_s, var->dataType.Format().AddressOf());
01957 Error(str.AddressOf(), node);
01958 }
01959 }
01960
01961 void asCCompiler::CompileStatement(asCScriptNode *statement, bool *hasReturn, asCByteCode *bc)
01962 {
01963 *hasReturn = false;
01964
01965 if( statement->nodeType == snStatementBlock )
01966 CompileStatementBlock(statement, true, hasReturn, bc);
01967 else if( statement->nodeType == snIf )
01968 CompileIfStatement(statement, hasReturn, bc);
01969 else if( statement->nodeType == snFor )
01970 CompileForStatement(statement, bc);
01971 else if( statement->nodeType == snWhile )
01972 CompileWhileStatement(statement, bc);
01973 else if( statement->nodeType == snDoWhile )
01974 CompileDoWhileStatement(statement, bc);
01975 else if( statement->nodeType == snExpressionStatement )
01976 CompileExpressionStatement(statement, bc);
01977 else if( statement->nodeType == snBreak )
01978 CompileBreakStatement(statement, bc);
01979 else if( statement->nodeType == snContinue )
01980 CompileContinueStatement(statement, bc);
01981 else if( statement->nodeType == snSwitch )
01982 CompileSwitchStatement(statement, hasReturn, bc);
01983 else if( statement->nodeType == snReturn )
01984 {
01985 CompileReturnStatement(statement, bc);
01986 *hasReturn = true;
01987 }
01988 }
01989
01990 void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCode *bc)
01991 {
01992
01993
01994
01995 int breakLabel = nextLabel++;
01996 breakLabels.PushLast(breakLabel);
01997
01998
01999
02000 AddVariableScope(true, false);
02001
02002
02003
02004
02005
02006
02007 asSExprContext expr(engine);
02008 CompileAssignment(snode->firstChild, &expr);
02009
02010
02011 if( !expr.type.dataType.IsIntegerType() && !expr.type.dataType.IsUnsignedType() && !expr.type.dataType.IsEnumType() )
02012 {
02013 Error(TXT_SWITCH_MUST_BE_INTEGRAL, snode->firstChild);
02014 return;
02015 }
02016
02017
02018
02019 asCDataType to;
02020 if( expr.type.dataType.IsIntegerType() || expr.type.dataType.IsEnumType() )
02021 to.SetTokenType(ttInt);
02022 else if( expr.type.dataType.IsUnsignedType() )
02023 to.SetTokenType(ttUInt);
02024 ImplicitConversion(&expr, to, snode->firstChild, asIC_IMPLICIT_CONV, true);
02025
02026 ConvertToVariable(&expr);
02027 int offset = expr.type.stackOffset;
02028
02029
02030
02031
02032
02033
02034
02035 int firstCaseLabel = nextLabel;
02036 int defaultLabel = 0;
02037
02038 asCArray<int> caseValues;
02039 asCArray<int> caseLabels;
02040
02041
02042 asCScriptNode *cnode = snode->firstChild->next;
02043 while( cnode )
02044 {
02045
02046 if( cnode->firstChild && cnode->firstChild->nodeType == snExpression )
02047 {
02048
02049 asSExprContext c(engine);
02050 CompileExpression(cnode->firstChild, &c);
02051
02052
02053 if( !c.type.isConstant )
02054 Error(TXT_SWITCH_CASE_MUST_BE_CONSTANT, cnode->firstChild);
02055
02056
02057 if( !c.type.dataType.IsIntegerType() && !c.type.dataType.IsUnsignedType() && !c.type.dataType.IsEnumType() )
02058 Error(TXT_SWITCH_MUST_BE_INTEGRAL, cnode->firstChild);
02059
02060 ImplicitConversion(&c, to, cnode->firstChild, asIC_IMPLICIT_CONV, true);
02061
02062
02063 if( caseValues.IndexOf(c.type.intValue) >= 0 )
02064 {
02065 Error(TXT_DUPLICATE_SWITCH_CASE, cnode->firstChild);
02066 }
02067
02068
02069
02070
02071 caseValues.PushLast(c.type.intValue);
02072
02073
02074 caseLabels.PushLast(nextLabel++);
02075 }
02076 else
02077 {
02078
02079 if( cnode->next )
02080 {
02081 Error(TXT_DEFAULT_MUST_BE_LAST, cnode);
02082 break;
02083 }
02084
02085
02086 defaultLabel = nextLabel++;
02087 }
02088
02089 cnode = cnode->next;
02090 }
02091
02092
02093 if (caseValues.GetLength() == 0)
02094 {
02095 Error(TXT_EMPTY_SWITCH, snode);
02096 return;
02097 }
02098
02099 if( defaultLabel == 0 )
02100 defaultLabel = breakLabel;
02101
02102
02103
02104
02105
02106
02107
02108
02109 for( asUINT fwd = 1; fwd < caseValues.GetLength(); fwd++ )
02110 {
02111 for( int bck = fwd - 1; bck >= 0; bck-- )
02112 {
02113 int bckp = bck + 1;
02114 if( caseValues[bck] > caseValues[bckp] )
02115 {
02116
02117 int swap = caseValues[bckp];
02118 caseValues[bckp] = caseValues[bck];
02119 caseValues[bck] = swap;
02120
02121 swap = caseLabels[bckp];
02122 caseLabels[bckp] = caseLabels[bck];
02123 caseLabels[bck] = swap;
02124 }
02125 else
02126 break;
02127 }
02128 }
02129
02130
02131 asCArray<int> ranges;
02132 ranges.PushLast(0);
02133 asUINT n;
02134 for( n = 1; n < caseValues.GetLength(); ++n )
02135 {
02136
02137
02138 if( caseValues[n] > caseValues[n-1] + 5 )
02139 ranges.PushLast(n);
02140 }
02141
02142
02143 int tmpOffset = AllocateVariable(asCDataType::CreatePrimitive(ttInt, false), true);
02144 expr.bc.InstrSHORT_DW(asBC_SetV4, (short)tmpOffset, caseValues[caseValues.GetLength()-1]);
02145 expr.bc.InstrW_W(asBC_CMPi, offset, tmpOffset);
02146 expr.bc.InstrDWORD(asBC_JP, defaultLabel);
02147 ReleaseTemporaryVariable(tmpOffset, &expr.bc);
02148
02149
02150
02151
02152
02153 int range;
02154 for( range = 0; range < (int)ranges.GetLength(); range++ )
02155 {
02156
02157 int maxRange = caseValues[ranges[range]];
02158 int index = ranges[range];
02159 for( ; (index < (int)caseValues.GetLength()) && (caseValues[index] <= maxRange + 5); index++ )
02160 maxRange = caseValues[index];
02161
02162
02163 if( index - ranges[range] > 2 )
02164 {
02165
02166 tmpOffset = AllocateVariable(asCDataType::CreatePrimitive(ttInt, false), true);
02167 expr.bc.InstrSHORT_DW(asBC_SetV4, (short)tmpOffset, caseValues[ranges[range]]);
02168 expr.bc.InstrW_W(asBC_CMPi, offset, tmpOffset);
02169 expr.bc.InstrDWORD(asBC_JS, defaultLabel);
02170 ReleaseTemporaryVariable(tmpOffset, &expr.bc);
02171
02172 int nextRangeLabel = nextLabel++;
02173
02174 if( range < (int)ranges.GetLength() - 1 )
02175 {
02176
02177 tmpOffset = AllocateVariable(asCDataType::CreatePrimitive(ttInt, false), true);
02178 expr.bc.InstrSHORT_DW(asBC_SetV4, (short)tmpOffset, maxRange);
02179 expr.bc.InstrW_W(asBC_CMPi, offset, tmpOffset);
02180 expr.bc.InstrDWORD(asBC_JP, nextRangeLabel);
02181 ReleaseTemporaryVariable(tmpOffset, &expr.bc);
02182 }
02183
02184
02185 tmpOffset = AllocateVariable(asCDataType::CreatePrimitive(ttInt, false), true);
02186 expr.bc.InstrSHORT_DW(asBC_SetV4, (short)tmpOffset, caseValues[ranges[range]]);
02187 expr.bc.InstrW_W_W(asBC_SUBi, tmpOffset, offset, tmpOffset);
02188 ReleaseTemporaryVariable(tmpOffset, &expr.bc);
02189 expr.bc.JmpP(tmpOffset, maxRange - caseValues[ranges[range]]);
02190
02191
02192 index = ranges[range];
02193 for( int n = caseValues[index]; n <= maxRange; n++ )
02194 {
02195 if( caseValues[index] == n )
02196 expr.bc.InstrINT(asBC_JMP, caseLabels[index++]);
02197 else
02198 expr.bc.InstrINT(asBC_JMP, defaultLabel);
02199 }
02200
02201 expr.bc.Label((short)nextRangeLabel);
02202 }
02203 else
02204 {
02205
02206 int n;
02207 for( n = ranges[range]; n < index; ++n )
02208 {
02209 tmpOffset = AllocateVariable(asCDataType::CreatePrimitive(ttInt, false), true);
02210 expr.bc.InstrSHORT_DW(asBC_SetV4, (short)tmpOffset, caseValues[n]);
02211 expr.bc.InstrW_W(asBC_CMPi, offset, tmpOffset);
02212 expr.bc.InstrDWORD(asBC_JZ, caseLabels[n]);
02213 ReleaseTemporaryVariable(tmpOffset, &expr.bc);
02214 }
02215 }
02216 }
02217
02218
02219 expr.bc.InstrINT(asBC_JMP, defaultLabel);
02220
02221
02222 ReleaseTemporaryVariable(expr.type, &expr.bc);
02223
02224
02225
02226
02227
02228
02229 cnode = snode->firstChild->next;
02230 while( cnode )
02231 {
02232
02233 if( cnode->firstChild && cnode->firstChild->nodeType == snExpression )
02234 {
02235 expr.bc.Label((short)firstCaseLabel++);
02236
02237 CompileCase(cnode->firstChild->next, &expr.bc);
02238 }
02239 else
02240 {
02241 expr.bc.Label((short)defaultLabel);
02242
02243
02244 if( cnode->next )
02245 {
02246
02247 break;
02248 }
02249
02250 CompileCase(cnode->firstChild, &expr.bc);
02251 }
02252
02253 cnode = cnode->next;
02254 }
02255
02256
02257
02258 bc->AddCode(&expr.bc);
02259
02260
02261 bc->Label((short)breakLabel);
02262
02263 breakLabels.PopLast();
02264 RemoveVariableScope();
02265 }
02266
02267 void asCCompiler::CompileCase(asCScriptNode *node, asCByteCode *bc)
02268 {
02269 bool isFinished = false;
02270 bool hasReturn = false;
02271 while( node )
02272 {
02273 if( hasReturn || isFinished )
02274 {
02275 Warning(TXT_UNREACHABLE_CODE, node);
02276 break;
02277 }
02278
02279 if( node->nodeType == snBreak || node->nodeType == snContinue )
02280 isFinished = true;
02281
02282 asCByteCode statement(engine);
02283 CompileStatement(node, &hasReturn, &statement);
02284
02285 LineInstr(bc, node->tokenPos);
02286 bc->AddCode(&statement);
02287
02288 if( !hasCompileErrors )
02289 asASSERT( tempVariables.GetLength() == 0 );
02290
02291 node = node->next;
02292 }
02293 }
02294
02295 void asCCompiler::CompileIfStatement(asCScriptNode *inode, bool *hasReturn, asCByteCode *bc)
02296 {
02297
02298
02299 int afterLabel = nextLabel++;
02300
02301
02302 asSExprContext expr(engine);
02303 CompileAssignment(inode->firstChild, &expr);
02304 if( !expr.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) )
02305 {
02306 Error(TXT_EXPR_MUST_BE_BOOL, inode->firstChild);
02307 expr.type.SetConstantDW(asCDataType::CreatePrimitive(ttBool, true), 1);
02308 }
02309
02310 if( expr.type.dataType.IsReference() ) ConvertToVariable(&expr);
02311 ProcessDeferredParams(&expr);
02312
02313 if( !expr.type.isConstant )
02314 {
02315 ProcessPropertyGetAccessor(&expr, inode);
02316
02317 ConvertToVariable(&expr);
02318
02319
02320 bc->AddCode(&expr.bc);
02321
02322
02323 bc->InstrSHORT(asBC_CpyVtoR4, expr.type.stackOffset);
02324 bc->Instr(asBC_ClrHi);
02325 bc->InstrDWORD(asBC_JZ, afterLabel);
02326 ReleaseTemporaryVariable(expr.type, bc);
02327 }
02328 else if( expr.type.dwordValue == 0 )
02329 {
02330
02331 bc->InstrINT(asBC_JMP, afterLabel);
02332
02333
02334 }
02335
02336
02337 bool origIsConstructorCalled = m_isConstructorCalled;
02338
02339 bool hasReturn1;
02340 asCByteCode ifBC(engine);
02341 CompileStatement(inode->firstChild->next, &hasReturn1, &ifBC);
02342
02343
02344 LineInstr(bc, inode->firstChild->next->tokenPos);
02345 bc->AddCode(&ifBC);
02346
02347 if( inode->firstChild->next->nodeType == snExpressionStatement && inode->firstChild->next->firstChild == 0 )
02348 {
02349
02350 Error(TXT_IF_WITH_EMPTY_STATEMENT, inode->firstChild->next);
02351 }
02352
02353
02354
02355 bool constructorCall1 = false;
02356 bool constructorCall2 = false;
02357 if( !origIsConstructorCalled && m_isConstructorCalled )
02358 constructorCall1 = true;
02359
02360
02361 if( inode->firstChild->next != inode->lastChild )
02362 {
02363
02364 m_isConstructorCalled = origIsConstructorCalled;
02365
02366 int afterElse = 0;
02367 if( !hasReturn1 )
02368 {
02369 afterElse = nextLabel++;
02370
02371
02372 bc->InstrINT(asBC_JMP, afterElse);
02373 }
02374
02375
02376 bc->Label((short)afterLabel);
02377
02378 bool hasReturn2;
02379 asCByteCode elseBC(engine);
02380 CompileStatement(inode->lastChild, &hasReturn2, &elseBC);
02381
02382
02383 LineInstr(bc, inode->lastChild->tokenPos);
02384 bc->AddCode(&elseBC);
02385
02386 if( inode->lastChild->nodeType == snExpressionStatement && inode->lastChild->firstChild == 0 )
02387 {
02388
02389 Error(TXT_ELSE_WITH_EMPTY_STATEMENT, inode->lastChild);
02390 }
02391
02392 if( !hasReturn1 )
02393 {
02394
02395 bc->Label((short)afterElse);
02396 }
02397
02398
02399 *hasReturn = hasReturn1 && hasReturn2;
02400
02401 if( !origIsConstructorCalled && m_isConstructorCalled )
02402 constructorCall2 = true;
02403 }
02404 else
02405 {
02406
02407 bc->Label((short)afterLabel);
02408 *hasReturn = false;
02409 }
02410
02411
02412 if( (constructorCall1 && !constructorCall2) ||
02413 (constructorCall2 && !constructorCall1) )
02414 {
02415 Error(TXT_BOTH_CONDITIONS_MUST_CALL_CONSTRUCTOR, inode);
02416 }
02417
02418 m_isConstructorCalled = origIsConstructorCalled || constructorCall1 || constructorCall2;
02419 }
02420
02421 void asCCompiler::CompileForStatement(asCScriptNode *fnode, asCByteCode *bc)
02422 {
02423
02424 AddVariableScope(true, true);
02425
02426
02427 int beforeLabel = nextLabel++;
02428 int afterLabel = nextLabel++;
02429 int continueLabel = nextLabel++;
02430
02431 continueLabels.PushLast(continueLabel);
02432 breakLabels.PushLast(afterLabel);
02433
02434
02435
02436 asCByteCode initBC(engine);
02437 if( fnode->firstChild->nodeType == snDeclaration )
02438 CompileDeclaration(fnode->firstChild, &initBC);
02439 else
02440 CompileExpressionStatement(fnode->firstChild, &initBC);
02441
02442
02443
02444 asSExprContext expr(engine);
02445 asCScriptNode *second = fnode->firstChild->next;
02446 if( second->firstChild )
02447 {
02448 int r = CompileAssignment(second->firstChild, &expr);
02449 if( r >= 0 )
02450 {
02451 if( !expr.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) )
02452 Error(TXT_EXPR_MUST_BE_BOOL, second);
02453 else
02454 {
02455 if( expr.type.dataType.IsReference() ) ConvertToVariable(&expr);
02456 ProcessDeferredParams(&expr);
02457
02458
02459 ConvertToVariable(&expr);
02460 expr.bc.InstrSHORT(asBC_CpyVtoR4, expr.type.stackOffset);
02461 expr.bc.Instr(asBC_ClrHi);
02462 expr.bc.InstrDWORD(asBC_JZ, afterLabel);
02463 ReleaseTemporaryVariable(expr.type, &expr.bc);
02464 }
02465 }
02466 }
02467
02468
02469
02470 asCByteCode nextBC(engine);
02471 asCScriptNode *third = second->next;
02472 if( third->nodeType == snExpressionStatement )
02473 CompileExpressionStatement(third, &nextBC);
02474
02475
02476
02477 bool hasReturn;
02478 asCByteCode forBC(engine);
02479 CompileStatement(fnode->lastChild, &hasReturn, &forBC);
02480
02481
02482
02483 bc->AddCode(&initBC);
02484 bc->Label((short)beforeLabel);
02485
02486
02487
02488 bc->Instr(asBC_SUSPEND);
02489 bc->InstrWORD(asBC_JitEntry, 0);
02490
02491
02492 bc->AddCode(&expr.bc);
02493 LineInstr(bc, fnode->lastChild->tokenPos);
02494 bc->AddCode(&forBC);
02495 bc->Label((short)continueLabel);
02496 bc->AddCode(&nextBC);
02497 bc->InstrINT(asBC_JMP, beforeLabel);
02498 bc->Label((short)afterLabel);
02499
02500 continueLabels.PopLast();
02501 breakLabels.PopLast();
02502
02503
02504 for( int n = (int)variables->variables.GetLength() - 1; n >= 0; n-- )
02505 {
02506 sVariable *v = variables->variables[n];
02507
02508
02509 CallDestructor(v->type, v->stackOffset, bc);
02510
02511
02512 if( v->stackOffset > 0 )
02513 DeallocateVariable(v->stackOffset);
02514 }
02515
02516 RemoveVariableScope();
02517 }
02518
02519 void asCCompiler::CompileWhileStatement(asCScriptNode *wnode, asCByteCode *bc)
02520 {
02521
02522 AddVariableScope(true, true);
02523
02524
02525 int beforeLabel = nextLabel++;
02526 int afterLabel = nextLabel++;
02527
02528 continueLabels.PushLast(beforeLabel);
02529 breakLabels.PushLast(afterLabel);
02530
02531
02532 bc->Label((short)beforeLabel);
02533
02534
02535 asSExprContext expr(engine);
02536 CompileAssignment(wnode->firstChild, &expr);
02537 if( !expr.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) )
02538 Error(TXT_EXPR_MUST_BE_BOOL, wnode->firstChild);
02539
02540 if( expr.type.dataType.IsReference() ) ConvertToVariable(&expr);
02541 ProcessDeferredParams(&expr);
02542
02543
02544 ConvertToVariable(&expr);
02545 bc->AddCode(&expr.bc);
02546
02547
02548 bc->InstrSHORT(asBC_CpyVtoR4, expr.type.stackOffset);
02549 bc->Instr(asBC_ClrHi);
02550 bc->InstrDWORD(asBC_JZ, afterLabel);
02551 ReleaseTemporaryVariable(expr.type, bc);
02552
02553
02554
02555 bc->Instr(asBC_SUSPEND);
02556 bc->InstrWORD(asBC_JitEntry, 0);
02557
02558
02559 bool hasReturn;
02560 asCByteCode whileBC(engine);
02561 CompileStatement(wnode->lastChild, &hasReturn, &whileBC);
02562
02563
02564 LineInstr(bc, wnode->lastChild->tokenPos);
02565 bc->AddCode(&whileBC);
02566
02567
02568 bc->InstrINT(asBC_JMP, beforeLabel);
02569
02570
02571 bc->Label((short)afterLabel);
02572
02573 continueLabels.PopLast();
02574 breakLabels.PopLast();
02575
02576 RemoveVariableScope();
02577 }
02578
02579 void asCCompiler::CompileDoWhileStatement(asCScriptNode *wnode, asCByteCode *bc)
02580 {
02581
02582 AddVariableScope(true, true);
02583
02584
02585 int beforeLabel = nextLabel++;
02586 int beforeTest = nextLabel++;
02587 int afterLabel = nextLabel++;
02588
02589 continueLabels.PushLast(beforeTest);
02590 breakLabels.PushLast(afterLabel);
02591
02592
02593 bc->Label((short)beforeLabel);
02594
02595
02596 bool hasReturn;
02597 asCByteCode whileBC(engine);
02598 CompileStatement(wnode->firstChild, &hasReturn, &whileBC);
02599
02600
02601 LineInstr(bc, wnode->firstChild->tokenPos);
02602 bc->AddCode(&whileBC);
02603
02604
02605 bc->Label((short)beforeTest);
02606
02607
02608
02609 bc->Instr(asBC_SUSPEND);
02610 bc->InstrWORD(asBC_JitEntry, 0);
02611
02612
02613 LineInstr(bc, wnode->lastChild->tokenPos);
02614
02615
02616 asSExprContext expr(engine);
02617 CompileAssignment(wnode->lastChild, &expr);
02618 if( !expr.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) )
02619 Error(TXT_EXPR_MUST_BE_BOOL, wnode->firstChild);
02620
02621 if( expr.type.dataType.IsReference() ) ConvertToVariable(&expr);
02622 ProcessDeferredParams(&expr);
02623
02624
02625 ConvertToVariable(&expr);
02626 bc->AddCode(&expr.bc);
02627
02628
02629 bc->InstrSHORT(asBC_CpyVtoR4, expr.type.stackOffset);
02630 bc->Instr(asBC_ClrHi);
02631 bc->InstrDWORD(asBC_JNZ, beforeLabel);
02632 ReleaseTemporaryVariable(expr.type, bc);
02633
02634
02635 bc->Label((short)afterLabel);
02636
02637 continueLabels.PopLast();
02638 breakLabels.PopLast();
02639
02640 RemoveVariableScope();
02641 }
02642
02643 void asCCompiler::CompileBreakStatement(asCScriptNode *node, asCByteCode *bc)
02644 {
02645 if( breakLabels.GetLength() == 0 )
02646 {
02647 Error(TXT_INVALID_BREAK, node);
02648 return;
02649 }
02650
02651
02652 asCVariableScope *vs = variables;
02653 while( !vs->isBreakScope )
02654 {
02655 for( int n = (int)vs->variables.GetLength() - 1; n >= 0; n-- )
02656 CallDestructor(vs->variables[n]->type, vs->variables[n]->stackOffset, bc);
02657
02658 vs = vs->parent;
02659 }
02660
02661 bc->InstrINT(asBC_JMP, breakLabels[breakLabels.GetLength()-1]);
02662 }
02663
02664 void asCCompiler::CompileContinueStatement(asCScriptNode *node, asCByteCode *bc)
02665 {
02666 if( continueLabels.GetLength() == 0 )
02667 {
02668 Error(TXT_INVALID_CONTINUE, node);
02669 return;
02670 }
02671
02672
02673 asCVariableScope *vs = variables;
02674 while( !vs->isContinueScope )
02675 {
02676 for( int n = (int)vs->variables.GetLength() - 1; n >= 0; n-- )
02677 CallDestructor(vs->variables[n]->type, vs->variables[n]->stackOffset, bc);
02678
02679 vs = vs->parent;
02680 }
02681
02682 bc->InstrINT(asBC_JMP, continueLabels[continueLabels.GetLength()-1]);
02683 }
02684
02685 void asCCompiler::CompileExpressionStatement(asCScriptNode *enode, asCByteCode *bc)
02686 {
02687 if( enode->firstChild )
02688 {
02689
02690 asSExprContext expr(engine);
02691 CompileAssignment(enode->firstChild, &expr);
02692
02693
02694 if( !expr.type.dataType.IsPrimitive() )
02695 expr.bc.Pop(expr.type.dataType.GetSizeOnStackDWords());
02696
02697
02698 ReleaseTemporaryVariable(expr.type, &expr.bc);
02699
02700 ProcessDeferredParams(&expr);
02701
02702 bc->AddCode(&expr.bc);
02703 }
02704 }
02705
02706 void asCCompiler::PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ctx, asCArray<int> *reservedVars)
02707 {
02708
02709 if( ctx->type.isTemporary ) return;
02710
02711
02712 asCDataType dt = ctx->type.dataType;
02713 dt.MakeReference(false);
02714 dt.MakeReadOnly(false);
02715
02716 int offset = AllocateVariableNotIn(dt, true, reservedVars);
02717
02718
02719 CallDefaultConstructor(dt, offset, &ctx->bc, node);
02720
02721
02722 asCTypeInfo lvalue;
02723 dt.MakeReference(true);
02724 lvalue.Set(dt);
02725 lvalue.isTemporary = true;
02726 lvalue.stackOffset = (short)offset;
02727 lvalue.isVariable = true;
02728 lvalue.isExplicitHandle = ctx->type.isExplicitHandle;
02729
02730 PrepareForAssignment(&lvalue.dataType, ctx, node);
02731
02732 ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
02733 PerformAssignment(&lvalue, &ctx->type, &ctx->bc, node);
02734
02735
02736 ctx->bc.Pop(AS_PTR_SIZE);
02737
02738
02739 ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
02740 lvalue.dataType.MakeReference(true);
02741
02742 ctx->type = lvalue;
02743 }
02744
02745 void asCCompiler::CompileReturnStatement(asCScriptNode *rnode, asCByteCode *bc)
02746 {
02747
02748 sVariable *v = variables->GetVariable("return");
02749 if( v->type.GetSizeOnStackDWords() > 0 )
02750 {
02751
02752 if( rnode->firstChild )
02753 {
02754
02755 asSExprContext expr(engine);
02756 int r = CompileAssignment(rnode->firstChild, &expr);
02757 if( r >= 0 )
02758 {
02759
02760 IsVariableInitialized(&expr.type, rnode->firstChild);
02761
02762 if( v->type.IsPrimitive() )
02763 {
02764 if( expr.type.dataType.IsReference() ) ConvertToVariable(&expr);
02765
02766
02767 ImplicitConversion(&expr, v->type, rnode->firstChild, asIC_IMPLICIT_CONV);
02768
02769
02770 if( expr.type.dataType != v->type )
02771 {
02772 asCString str;
02773 str.Format(TXT_NO_CONVERSION_s_TO_s, expr.type.dataType.Format().AddressOf(), v->type.Format().AddressOf());
02774 Error(str.AddressOf(), rnode);
02775 r = -1;
02776 }
02777 else
02778 {
02779 ConvertToVariable(&expr);
02780 ReleaseTemporaryVariable(expr.type, &expr.bc);
02781
02782
02783 if( v->type.GetSizeOnStackDWords() == 1 )
02784 expr.bc.InstrSHORT(asBC_CpyVtoR4, expr.type.stackOffset);
02785 else
02786 expr.bc.InstrSHORT(asBC_CpyVtoR8, expr.type.stackOffset);
02787 }
02788 }
02789 else if( v->type.IsObject() )
02790 {
02791 PrepareArgument(&v->type, &expr, rnode->firstChild);
02792
02793
02794 expr.bc.Pop(AS_PTR_SIZE);
02795
02796
02797
02798 expr.bc.InstrSHORT(asBC_LOADOBJ, expr.type.stackOffset);
02799
02800
02801
02802
02803
02804
02805 }
02806
02807
02808 ReleaseTemporaryVariable(expr.type, &expr.bc);
02809
02810 bc->AddCode(&expr.bc);
02811 }
02812 }
02813 else
02814 Error(TXT_MUST_RETURN_VALUE, rnode);
02815 }
02816 else
02817 if( rnode->firstChild )
02818 Error(TXT_CANT_RETURN_VALUE, rnode);
02819
02820
02821 asCVariableScope *vs = variables;
02822 while( vs )
02823 {
02824 for( int n = (int)vs->variables.GetLength() - 1; n >= 0; n-- )
02825 if( vs->variables[n]->stackOffset > 0 )
02826 CallDestructor(vs->variables[n]->type, vs->variables[n]->stackOffset, bc);
02827
02828 vs = vs->parent;
02829 }
02830
02831
02832 bc->InstrINT(asBC_JMP, 0);
02833 }
02834
02835 void asCCompiler::AddVariableScope(bool isBreakScope, bool isContinueScope)
02836 {
02837 variables = asNEW(asCVariableScope)(variables);
02838 variables->isBreakScope = isBreakScope;
02839 variables->isContinueScope = isContinueScope;
02840 }
02841
02842 void asCCompiler::RemoveVariableScope()
02843 {
02844 if( variables )
02845 {
02846 asCVariableScope *var = variables;
02847 variables = variables->parent;
02848 asDELETE(var,asCVariableScope);
02849 }
02850 }
02851
02852 void asCCompiler::Error(const char *msg, asCScriptNode *node)
02853 {
02854 asCString str;
02855
02856 int r, c;
02857 script->ConvertPosToRowCol(node->tokenPos, &r, &c);
02858
02859 builder->WriteError(script->name.AddressOf(), msg, r, c);
02860
02861 hasCompileErrors = true;
02862 }
02863
02864 void asCCompiler::Warning(const char *msg, asCScriptNode *node)
02865 {
02866 asCString str;
02867
02868 int r, c;
02869 script->ConvertPosToRowCol(node->tokenPos, &r, &c);
02870
02871 builder->WriteWarning(script->name.AddressOf(), msg, r, c);
02872 }
02873
02874 void asCCompiler::PrintMatchingFuncs(asCArray<int> &funcs, asCScriptNode *node)
02875 {
02876 int r, c;
02877 script->ConvertPosToRowCol(node->tokenPos, &r, &c);
02878
02879 for( unsigned int n = 0; n < funcs.GetLength(); n++ )
02880 {
02881 asIScriptFunction *func = engine->scriptFunctions[funcs[n]];
02882
02883 builder->WriteInfo(script->name.AddressOf(), func->GetDeclaration(true), r, c, false);
02884 }
02885 }
02886
02887 int asCCompiler::AllocateVariable(const asCDataType &type, bool isTemporary)
02888 {
02889 return AllocateVariableNotIn(type, isTemporary, 0);
02890 }
02891
02892 int asCCompiler::AllocateVariableNotIn(const asCDataType &type, bool isTemporary, asCArray<int> *vars)
02893 {
02894 asCDataType t(type);
02895
02896 if( t.IsPrimitive() && t.GetSizeOnStackDWords() == 1 )
02897 t.SetTokenType(ttInt);
02898
02899 if( t.IsPrimitive() && t.GetSizeOnStackDWords() == 2 )
02900 t.SetTokenType(ttDouble);
02901
02902
02903 for( asUINT n = 0; n < freeVariables.GetLength(); n++ )
02904 {
02905 int slot = freeVariables[n];
02906 if( variableAllocations[slot].IsEqualExceptConst(t) && variableIsTemporary[slot] == isTemporary )
02907 {
02908
02909 int offset = GetVariableOffset(slot);
02910
02911
02912 bool isUsed = false;
02913 if( vars )
02914 {
02915 for( asUINT m = 0; m < vars->GetLength(); m++ )
02916 {
02917 if( offset == (*vars)[m] )
02918 {
02919 isUsed = true;
02920 break;
02921 }
02922 }
02923 }
02924
02925 if( !isUsed )
02926 {
02927 if( n != freeVariables.GetLength() - 1 )
02928 freeVariables[n] = freeVariables.PopLast();
02929 else
02930 freeVariables.PopLast();
02931
02932 if( isTemporary )
02933 tempVariables.PushLast(offset);
02934
02935 return offset;
02936 }
02937 }
02938 }
02939
02940 variableAllocations.PushLast(t);
02941 variableIsTemporary.PushLast(isTemporary);
02942
02943 int offset = GetVariableOffset((int)variableAllocations.GetLength()-1);
02944
02945 if( isTemporary )
02946 tempVariables.PushLast(offset);
02947
02948 return offset;
02949 }
02950
02951 int asCCompiler::GetVariableOffset(int varIndex)
02952 {
02953
02954 int varOffset = 1;
02955 for( int n = 0; n < varIndex; n++ )
02956 varOffset += variableAllocations[n].GetSizeOnStackDWords();
02957
02958 if( varIndex < (int)variableAllocations.GetLength() )
02959 {
02960 int size = variableAllocations[varIndex].GetSizeOnStackDWords();
02961 if( size > 1 )
02962 varOffset += size-1;
02963 }
02964
02965 return varOffset;
02966 }
02967
02968 int asCCompiler::GetVariableSlot(int offset)
02969 {
02970 int varOffset = 1;
02971 for( asUINT n = 0; n < variableAllocations.GetLength(); n++ )
02972 {
02973 varOffset += -1 + variableAllocations[n].GetSizeOnStackDWords();
02974 if( varOffset == offset )
02975 {
02976 return n;
02977 }
02978 varOffset++;
02979 }
02980
02981 return -1;
02982 }
02983
02984 void asCCompiler::DeallocateVariable(int offset)
02985 {
02986
02987 int n;
02988 for( n = 0; n < (int)tempVariables.GetLength(); n++ )
02989 {
02990 if( offset == tempVariables[n] )
02991 {
02992 if( n == (int)tempVariables.GetLength()-1 )
02993 tempVariables.PopLast();
02994 else
02995 tempVariables[n] = tempVariables.PopLast();
02996 break;
02997 }
02998 }
02999
03000 n = GetVariableSlot(offset);
03001 if( n != -1 )
03002 {
03003 freeVariables.PushLast(n);
03004 return;
03005 }
03006
03007
03008
03009
03010
03011 asASSERT(offset == 0x7FFF);
03012 }
03013
03014 void asCCompiler::ReleaseTemporaryVariable(asCTypeInfo &t, asCByteCode *bc)
03015 {
03016 if( t.isTemporary )
03017 {
03018 if( bc )
03019 {
03020
03021 int n = GetVariableSlot(t.stackOffset);
03022 asCDataType dt = variableAllocations[n];
03023
03024
03025 CallDestructor(dt, t.stackOffset, bc);
03026 }
03027
03028 DeallocateVariable(t.stackOffset);
03029 t.isTemporary = false;
03030 }
03031 }
03032
03033 void asCCompiler::ReleaseTemporaryVariable(int offset, asCByteCode *bc)
03034 {
03035 if( bc )
03036 {
03037
03038 int n = GetVariableSlot(offset);
03039 asCDataType dt = variableAllocations[n];
03040
03041
03042 CallDestructor(dt, offset, bc);
03043 }
03044
03045 DeallocateVariable(offset);
03046 }
03047
03048 void asCCompiler::Dereference(asSExprContext *ctx, bool generateCode)
03049 {
03050 if( ctx->type.dataType.IsReference() )
03051 {
03052 if( ctx->type.dataType.IsObject() )
03053 {
03054 ctx->type.dataType.MakeReference(false);
03055 if( generateCode )
03056 {
03057 ctx->bc.Instr(asBC_CHKREF);
03058 ctx->bc.Instr(asBC_RDSPTR);
03059 }
03060 }
03061 else
03062 {
03063
03064 asASSERT(false);
03065 }
03066 }
03067 }
03068
03069
03070 bool asCCompiler::IsVariableInitialized(asCTypeInfo *type, asCScriptNode *node)
03071 {
03072
03073 if( type->isTemporary ) return true;
03074
03075
03076 if( !type->isVariable ) return true;
03077
03078
03079 sVariable *v = variables->GetVariableByOffset(type->stackOffset);
03080
03081
03082 if( v == 0 ) return true;
03083
03084 if( v->isInitialized ) return true;
03085
03086
03087 if( v->type.IsObject() ) return true;
03088
03089
03090 v->isInitialized = true;
03091
03092
03093 asCString str;
03094 str.Format(TXT_s_NOT_INITIALIZED, (const char *)v->name.AddressOf());
03095 Warning(str.AddressOf(), node);
03096
03097 return false;
03098 }
03099
03100 void asCCompiler::PrepareOperand(asSExprContext *ctx, asCScriptNode *node)
03101 {
03102
03103 IsVariableInitialized(&ctx->type, node);
03104
03105 asCDataType to = ctx->type.dataType;
03106 to.MakeReference(false);
03107
03108 ImplicitConversion(ctx, to, node, asIC_IMPLICIT_CONV);
03109
03110 ProcessDeferredParams(ctx);
03111 }
03112
03113 void asCCompiler::PrepareForAssignment(asCDataType *lvalue, asSExprContext *rctx, asCScriptNode *node, asSExprContext *lvalueExpr)
03114 {
03115 ProcessPropertyGetAccessor(rctx, node);
03116
03117
03118 IsVariableInitialized(&rctx->type, node);
03119
03120 if( lvalue->IsPrimitive() )
03121 {
03122 if( rctx->type.dataType.IsPrimitive() )
03123 {
03124 if( rctx->type.dataType.IsReference() )
03125 {
03126
03127 ConvertToVariableNotIn(rctx, lvalueExpr);
03128 }
03129 }
03130
03131
03132 asCArray<int> usedVars;
03133 if( lvalueExpr ) lvalueExpr->bc.GetVarsUsed(usedVars);
03134 ImplicitConversion(rctx, *lvalue, node, asIC_IMPLICIT_CONV, true, &usedVars);
03135
03136
03137 if( !lvalue->IsEqualExceptRefAndConst(rctx->type.dataType) )
03138 {
03139 asCString str;
03140 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, rctx->type.dataType.Format().AddressOf(), lvalue->Format().AddressOf());
03141 Error(str.AddressOf(), node);
03142
03143 rctx->type.SetDummy();
03144 }
03145
03146
03147 if( !rctx->type.isVariable )
03148 ConvertToVariableNotIn(rctx, lvalueExpr);
03149 }
03150 else
03151 {
03152 asCDataType to = *lvalue;
03153 to.MakeReference(false);
03154
03155
03156
03157 if( !lvalue->IsObjectHandle() &&
03158 (lvalue->GetObjectType()->flags & asOBJ_SCRIPT_OBJECT) )
03159 to.MakeHandle(true);
03160
03161
03162 ImplicitConversion(rctx, to, node, asIC_IMPLICIT_CONV, true, 0, false);
03163
03164 if( !lvalue->IsObjectHandle() &&
03165 (lvalue->GetObjectType()->flags & asOBJ_SCRIPT_OBJECT) )
03166 {
03167
03168 to.MakeHandle(false);
03169 ImplicitConversion(rctx, to, node, asIC_IMPLICIT_CONV, true, 0, false);
03170 }
03171
03172
03173 if( !lvalue->IsEqualExceptRefAndConst(rctx->type.dataType) )
03174 {
03175 asCString str;
03176 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, rctx->type.dataType.Format().AddressOf(), lvalue->Format().AddressOf());
03177 Error(str.AddressOf(), node);
03178 }
03179 else
03180 {
03181
03182 if( lvalue->IsObject() )
03183 asASSERT(!rctx->type.dataType.IsReference());
03184 }
03185 }
03186 }
03187
03188 bool asCCompiler::IsLValue(asCTypeInfo &type)
03189 {
03190 if( type.dataType.IsReadOnly() ) return false;
03191 if( !type.dataType.IsObject() && !type.isVariable && !type.dataType.IsReference() ) return false;
03192 if( type.isTemporary ) return false;
03193 return true;
03194 }
03195
03196 void asCCompiler::PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asCByteCode *bc, asCScriptNode *node)
03197 {
03198 if( lvalue->dataType.IsReadOnly() )
03199 Error(TXT_REF_IS_READ_ONLY, node);
03200
03201 if( lvalue->dataType.IsPrimitive() )
03202 {
03203 if( lvalue->isVariable )
03204 {
03205
03206 if( lvalue->dataType.GetSizeInMemoryDWords() == 1 )
03207 bc->InstrW_W(asBC_CpyVtoV4, lvalue->stackOffset, rvalue->stackOffset);
03208 else
03209 bc->InstrW_W(asBC_CpyVtoV8, lvalue->stackOffset, rvalue->stackOffset);
03210
03211
03212 sVariable *v = variables->GetVariableByOffset(lvalue->stackOffset);
03213 if( v ) v->isInitialized = true;
03214 }
03215 else if( lvalue->dataType.IsReference() )
03216 {
03217
03218 int s = lvalue->dataType.GetSizeInMemoryBytes();
03219 if( s == 1 )
03220 bc->InstrSHORT(asBC_WRTV1, rvalue->stackOffset);
03221 else if( s == 2 )
03222 bc->InstrSHORT(asBC_WRTV2, rvalue->stackOffset);
03223 else if( s == 4 )
03224 bc->InstrSHORT(asBC_WRTV4, rvalue->stackOffset);
03225 else if( s == 8 )
03226 bc->InstrSHORT(asBC_WRTV8, rvalue->stackOffset);
03227 }
03228 else
03229 {
03230 Error(TXT_NOT_VALID_LVALUE, node);
03231 return;
03232 }
03233 }
03234 else if( !lvalue->isExplicitHandle )
03235 {
03236
03237
03238 asSExprContext ctx(engine);
03239 ctx.type = *lvalue;
03240 Dereference(&ctx, true);
03241 *lvalue = ctx.type;
03242 bc->AddCode(&ctx.bc);
03243
03244
03245
03246
03247
03248 asSTypeBehaviour *beh = lvalue->dataType.GetBehaviour();
03249 if( beh->copy )
03250 {
03251
03252 bc->Call(asBC_CALLSYS, (asDWORD)beh->copy, 2*AS_PTR_SIZE);
03253 bc->Instr(asBC_PshRPtr);
03254 }
03255 else
03256 {
03257
03258 if( lvalue->dataType.GetSizeInMemoryDWords() == 0 ||
03259 !(lvalue->dataType.GetObjectType()->flags & asOBJ_POD) )
03260 {
03261 Error(TXT_NO_DEFAULT_COPY_OP, node);
03262 }
03263
03264
03265 bc->InstrWORD(asBC_COPY, (asWORD)lvalue->dataType.GetSizeInMemoryDWords());
03266 }
03267 }
03268 else
03269 {
03270
03271 if( !lvalue->dataType.IsReference() )
03272 {
03273 Error(TXT_NOT_VALID_REFERENCE, node);
03274 return;
03275 }
03276
03277
03278 bc->InstrPTR(asBC_REFCPY, lvalue->dataType.GetObjectType());
03279
03280
03281 if( variables )
03282 {
03283 sVariable *v = variables->GetVariableByOffset(lvalue->stackOffset);
03284 if( v ) v->isInitialized = true;
03285 }
03286 }
03287 }
03288
03289 bool asCCompiler::CompileRefCast(asSExprContext *ctx, const asCDataType &to, bool isExplicit, asCScriptNode *node, bool generateCode)
03290 {
03291 bool conversionDone = false;
03292
03293 asCArray<int> ops;
03294 asUINT n;
03295
03296 if( ctx->type.dataType.GetObjectType()->flags & asOBJ_SCRIPT_OBJECT )
03297 {
03298
03299 if( !ctx->type.dataType.IsReference() )
03300 {
03301 asCDataType to = ctx->type.dataType;
03302 to.MakeReference(true);
03303 ImplicitConversion(ctx, to, 0, isExplicit ? asIC_EXPLICIT_REF_CAST : asIC_IMPLICIT_CONV, generateCode);
03304 }
03305
03306 if( isExplicit )
03307 {
03308
03309
03310
03311 conversionDone = true;
03312 if( generateCode )
03313 {
03314 ctx->bc.InstrDWORD(asBC_Cast, engine->GetTypeIdFromDataType(to));
03315
03316
03317 int returnOffset = AllocateVariable(to, true);
03318
03319
03320 ctx->bc.InstrSHORT(asBC_STOREOBJ, (short)returnOffset);
03321
03322 ctx->bc.InstrSHORT(asBC_PSF, (short)returnOffset);
03323
03324 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03325
03326 ctx->type.SetVariable(to, returnOffset, true);
03327 ctx->type.dataType.MakeReference(true);
03328 }
03329 else
03330 {
03331 ctx->type.dataType = to;
03332 ctx->type.dataType.MakeReference(true);
03333 }
03334 }
03335 else
03336 {
03337 if( ctx->type.dataType.GetObjectType()->DerivesFrom(to.GetObjectType()) )
03338 {
03339 conversionDone = true;
03340 ctx->type.dataType.SetObjectType(to.GetObjectType());
03341 }
03342 }
03343 }
03344 else
03345 {
03346
03347 asSTypeBehaviour *beh = &ctx->type.dataType.GetObjectType()->beh;
03348 for( n = 0; n < beh->operators.GetLength(); n+= 2 )
03349 {
03350 if( (isExplicit && asBEHAVE_REF_CAST == beh->operators[n]) ||
03351 asBEHAVE_IMPLICIT_REF_CAST == beh->operators[n] )
03352 {
03353 int funcId = beh->operators[n+1];
03354
03355
03356 asCScriptFunction *func = engine->scriptFunctions[funcId];
03357 if( func->returnType.GetObjectType() != to.GetObjectType() )
03358 continue;
03359
03360 ops.PushLast(funcId);
03361 }
03362 }
03363
03364
03365 if( ops.GetLength() == 1 )
03366 {
03367 if( generateCode )
03368 {
03369
03370 asCTypeInfo objType = ctx->type;
03371 asCArray<asSExprContext *> args;
03372 MakeFunctionCall(ctx, ops[0], objType.dataType.GetObjectType(), args, node);
03373
03374
03375 ReleaseTemporaryVariable(objType, &ctx->bc);
03376 }
03377 else
03378 {
03379 asCScriptFunction *func = engine->scriptFunctions[ops[0]];
03380 ctx->type.Set(func->returnType);
03381 }
03382 }
03383 else if( ops.GetLength() > 1 )
03384 {
03385
03386 asASSERT( false );
03387 }
03388 #ifdef AS_DEPRECATED
03389
03390 else
03391 {
03392
03393 for( n = 0; n < engine->globalBehaviours.operators.GetLength(); n+= 2 )
03394 {
03395 if( (isExplicit && asBEHAVE_REF_CAST == engine->globalBehaviours.operators[n]) ||
03396 asBEHAVE_IMPLICIT_REF_CAST == engine->globalBehaviours.operators[n] )
03397 {
03398 int funcId = engine->globalBehaviours.operators[n+1];
03399
03400
03401 asCScriptFunction *func = engine->scriptFunctions[funcId];
03402 if( func->parameterTypes[0].GetObjectType() != ctx->type.dataType.GetObjectType() )
03403 continue;
03404
03405
03406 if( func->returnType.GetObjectType() != to.GetObjectType() )
03407 continue;
03408
03409
03410 asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
03411 if( !group || group->HasModuleAccess(builder->module->name.AddressOf()) )
03412 ops.PushLast(funcId);
03413 }
03414 }
03415
03416
03417 asCArray<int> ops1;
03418 MatchArgument(ops, ops1, &ctx->type, 0);
03419
03420
03421 if( ops1.GetLength() == 1 )
03422 {
03423 conversionDone = true;
03424 asCScriptFunction *descr = engine->scriptFunctions[ops1[0]];
03425
03426 if( generateCode )
03427 {
03428
03429 asSExprContext expr(engine);
03430 MergeExprContexts(&expr, ctx);
03431 expr.type = ctx->type;
03432 PrepareArgument2(ctx, &expr, &descr->parameterTypes[0], true, descr->inOutFlags[0]);
03433
03434 asCArray<asSExprContext*> args(1);
03435 args.PushLast(&expr);
03436
03437 MoveArgsToStack(descr->id, &ctx->bc, args, false);
03438
03439 PerformFunctionCall(descr->id, ctx, false, &args);
03440 }
03441 else
03442 {
03443 ctx->type.Set(descr->returnType);
03444 }
03445 }
03446 }
03447 #endif
03448 }
03449
03450 return conversionDone;
03451 }
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476
03477 void asCCompiler::ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, asCArray<int> *reservedVars)
03478 {
03479
03480 if( ctx->type.isConstant )
03481 ImplicitConversionConstant(ctx, to, node, convType);
03482
03483 if( to == ctx->type.dataType )
03484 return;
03485
03486
03487
03488
03489 if( generateCode )
03490 {
03491
03492 int s = ctx->type.dataType.GetSizeInMemoryBytes();
03493 if( s < 4 )
03494 {
03495 ConvertToTempVariableNotIn(ctx, reservedVars);
03496 if( ctx->type.dataType.IsIntegerType() )
03497 {
03498 if( s == 1 )
03499 ctx->bc.InstrSHORT(asBC_sbTOi, ctx->type.stackOffset);
03500 else if( s == 2 )
03501 ctx->bc.InstrSHORT(asBC_swTOi, ctx->type.stackOffset);
03502 ctx->type.dataType.SetTokenType(ttInt);
03503 }
03504 else if( ctx->type.dataType.IsUnsignedType() )
03505 {
03506 if( s == 1 )
03507 ctx->bc.InstrSHORT(asBC_ubTOi, ctx->type.stackOffset);
03508 else if( s == 2 )
03509 ctx->bc.InstrSHORT(asBC_uwTOi, ctx->type.stackOffset);
03510 ctx->type.dataType.SetTokenType(ttUInt);
03511 }
03512 }
03513
03514 if( (to.IsIntegerType() && to.GetSizeInMemoryDWords() == 1) ||
03515 (to.IsEnumType() && convType == asIC_EXPLICIT_VAL_CAST) )
03516 {
03517 if( ctx->type.dataType.IsIntegerType() ||
03518 ctx->type.dataType.IsUnsignedType() ||
03519 ctx->type.dataType.IsEnumType() )
03520 {
03521 if( ctx->type.dataType.GetSizeInMemoryDWords() == 1 )
03522 {
03523 ctx->type.dataType.SetTokenType(to.GetTokenType());
03524 ctx->type.dataType.SetObjectType(to.GetObjectType());
03525 }
03526 else
03527 {
03528 ConvertToTempVariableNotIn(ctx, reservedVars);
03529 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03530 int offset = AllocateVariableNotIn(to, true, reservedVars);
03531 ctx->bc.InstrW_W(asBC_i64TOi, offset, ctx->type.stackOffset);
03532 ctx->type.SetVariable(to, offset, true);
03533 }
03534 }
03535 else if( ctx->type.dataType.IsFloatType() )
03536 {
03537 ConvertToTempVariableNotIn(ctx, reservedVars);
03538 ctx->bc.InstrSHORT(asBC_fTOi, ctx->type.stackOffset);
03539 ctx->type.dataType.SetTokenType(to.GetTokenType());
03540 ctx->type.dataType.SetObjectType(to.GetObjectType());
03541 }
03542 else if( ctx->type.dataType.IsDoubleType() )
03543 {
03544 ConvertToTempVariableNotIn(ctx, reservedVars);
03545 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03546 int offset = AllocateVariableNotIn(to, true, reservedVars);
03547 ctx->bc.InstrW_W(asBC_dTOi, offset, ctx->type.stackOffset);
03548 ctx->type.SetVariable(to, offset, true);
03549 }
03550
03551
03552 int s = to.GetSizeInMemoryBytes();
03553 if( s < 4 )
03554 {
03555 ConvertToTempVariableNotIn(ctx, reservedVars);
03556 if( s == 1 )
03557 ctx->bc.InstrSHORT(asBC_iTOb, ctx->type.stackOffset);
03558 else if( s == 2 )
03559 ctx->bc.InstrSHORT(asBC_iTOw, ctx->type.stackOffset);
03560 }
03561 }
03562 if( to.IsIntegerType() && to.GetSizeInMemoryDWords() == 2 )
03563 {
03564 if( ctx->type.dataType.IsIntegerType() ||
03565 ctx->type.dataType.IsUnsignedType() ||
03566 ctx->type.dataType.IsEnumType() )
03567 {
03568 if( ctx->type.dataType.GetSizeInMemoryDWords() == 2 )
03569 {
03570 ctx->type.dataType.SetTokenType(to.GetTokenType());
03571 ctx->type.dataType.SetObjectType(to.GetObjectType());
03572 }
03573 else
03574 {
03575 ConvertToTempVariableNotIn(ctx, reservedVars);
03576 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03577 int offset = AllocateVariableNotIn(to, true, reservedVars);
03578 if( ctx->type.dataType.IsUnsignedType() )
03579 ctx->bc.InstrW_W(asBC_uTOi64, offset, ctx->type.stackOffset);
03580 else
03581 ctx->bc.InstrW_W(asBC_iTOi64, offset, ctx->type.stackOffset);
03582 ctx->type.SetVariable(to, offset, true);
03583 }
03584 }
03585 else if( ctx->type.dataType.IsFloatType() )
03586 {
03587 ConvertToTempVariableNotIn(ctx, reservedVars);
03588 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03589 int offset = AllocateVariableNotIn(to, true, reservedVars);
03590 ctx->bc.InstrW_W(asBC_fTOi64, offset, ctx->type.stackOffset);
03591 ctx->type.SetVariable(to, offset, true);
03592 }
03593 else if( ctx->type.dataType.IsDoubleType() )
03594 {
03595 ConvertToTempVariableNotIn(ctx, reservedVars);
03596 ctx->bc.InstrSHORT(asBC_dTOi64, ctx->type.stackOffset);
03597 ctx->type.dataType.SetTokenType(to.GetTokenType());
03598 ctx->type.dataType.SetObjectType(to.GetObjectType());
03599 }
03600 }
03601 else if( to.IsUnsignedType() && to.GetSizeInMemoryDWords() == 1 )
03602 {
03603 if( ctx->type.dataType.IsIntegerType() ||
03604 ctx->type.dataType.IsUnsignedType() ||
03605 ctx->type.dataType.IsEnumType() )
03606 {
03607 if( ctx->type.dataType.GetSizeInMemoryDWords() == 1 )
03608 {
03609 ctx->type.dataType.SetTokenType(to.GetTokenType());
03610 ctx->type.dataType.SetObjectType(to.GetObjectType());
03611 }
03612 else
03613 {
03614 ConvertToTempVariableNotIn(ctx, reservedVars);
03615 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03616 int offset = AllocateVariableNotIn(to, true, reservedVars);
03617 ctx->bc.InstrW_W(asBC_i64TOi, offset, ctx->type.stackOffset);
03618 ctx->type.SetVariable(to, offset, true);
03619 }
03620 }
03621 else if( ctx->type.dataType.IsFloatType() )
03622 {
03623 ConvertToTempVariableNotIn(ctx, reservedVars);
03624 ctx->bc.InstrSHORT(asBC_fTOu, ctx->type.stackOffset);
03625 ctx->type.dataType.SetTokenType(to.GetTokenType());
03626 ctx->type.dataType.SetObjectType(to.GetObjectType());
03627 }
03628 else if( ctx->type.dataType.IsDoubleType() )
03629 {
03630 ConvertToTempVariableNotIn(ctx, reservedVars);
03631 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03632 int offset = AllocateVariableNotIn(to, true, reservedVars);
03633 ctx->bc.InstrW_W(asBC_dTOu, offset, ctx->type.stackOffset);
03634 ctx->type.SetVariable(to, offset, true);
03635 }
03636
03637
03638 int s = to.GetSizeInMemoryBytes();
03639 if( s < 4 )
03640 {
03641 ConvertToTempVariableNotIn(ctx, reservedVars);
03642 if( s == 1 )
03643 ctx->bc.InstrSHORT(asBC_iTOb, ctx->type.stackOffset);
03644 else if( s == 2 )
03645 ctx->bc.InstrSHORT(asBC_iTOw, ctx->type.stackOffset);
03646 }
03647 }
03648 if( to.IsUnsignedType() && to.GetSizeInMemoryDWords() == 2 )
03649 {
03650 if( ctx->type.dataType.IsIntegerType() ||
03651 ctx->type.dataType.IsUnsignedType() ||
03652 ctx->type.dataType.IsEnumType() )
03653 {
03654 if( ctx->type.dataType.GetSizeInMemoryDWords() == 2 )
03655 {
03656 ctx->type.dataType.SetTokenType(to.GetTokenType());
03657 ctx->type.dataType.SetObjectType(to.GetObjectType());
03658 }
03659 else
03660 {
03661 ConvertToTempVariableNotIn(ctx, reservedVars);
03662 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03663 int offset = AllocateVariableNotIn(to, true, reservedVars);
03664 if( ctx->type.dataType.IsUnsignedType() )
03665 ctx->bc.InstrW_W(asBC_uTOi64, offset, ctx->type.stackOffset);
03666 else
03667 ctx->bc.InstrW_W(asBC_iTOi64, offset, ctx->type.stackOffset);
03668 ctx->type.SetVariable(to, offset, true);
03669 }
03670 }
03671 else if( ctx->type.dataType.IsFloatType() )
03672 {
03673 ConvertToTempVariableNotIn(ctx, reservedVars);
03674 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03675 int offset = AllocateVariableNotIn(to, true, reservedVars);
03676 ctx->bc.InstrW_W(asBC_fTOu64, offset, ctx->type.stackOffset);
03677 ctx->type.SetVariable(to, offset, true);
03678 }
03679 else if( ctx->type.dataType.IsDoubleType() )
03680 {
03681 ConvertToTempVariableNotIn(ctx, reservedVars);
03682 ctx->bc.InstrSHORT(asBC_dTOu64, ctx->type.stackOffset);
03683 ctx->type.dataType.SetTokenType(to.GetTokenType());
03684 ctx->type.dataType.SetObjectType(to.GetObjectType());
03685 }
03686 }
03687 else if( to.IsFloatType() )
03688 {
03689 if( (ctx->type.dataType.IsIntegerType() || ctx->type.dataType.IsEnumType()) && ctx->type.dataType.GetSizeInMemoryDWords() == 1 )
03690 {
03691 ConvertToTempVariableNotIn(ctx, reservedVars);
03692 ctx->bc.InstrSHORT(asBC_iTOf, ctx->type.stackOffset);
03693 ctx->type.dataType.SetTokenType(to.GetTokenType());
03694 ctx->type.dataType.SetObjectType(to.GetObjectType());
03695 }
03696 else if( ctx->type.dataType.IsIntegerType() && ctx->type.dataType.GetSizeInMemoryDWords() == 2 )
03697 {
03698 ConvertToTempVariableNotIn(ctx, reservedVars);
03699 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03700 int offset = AllocateVariableNotIn(to, true, reservedVars);
03701 ctx->bc.InstrW_W(asBC_i64TOf, offset, ctx->type.stackOffset);
03702 ctx->type.SetVariable(to, offset, true);
03703 }
03704 else if( ctx->type.dataType.IsUnsignedType() && ctx->type.dataType.GetSizeInMemoryDWords() == 1 )
03705 {
03706 ConvertToTempVariableNotIn(ctx, reservedVars);
03707 ctx->bc.InstrSHORT(asBC_uTOf, ctx->type.stackOffset);
03708 ctx->type.dataType.SetTokenType(to.GetTokenType());
03709 ctx->type.dataType.SetObjectType(to.GetObjectType());
03710 }
03711 else if( ctx->type.dataType.IsUnsignedType() && ctx->type.dataType.GetSizeInMemoryDWords() == 2 )
03712 {
03713 ConvertToTempVariableNotIn(ctx, reservedVars);
03714 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03715 int offset = AllocateVariableNotIn(to, true, reservedVars);
03716 ctx->bc.InstrW_W(asBC_u64TOf, offset, ctx->type.stackOffset);
03717 ctx->type.SetVariable(to, offset, true);
03718 }
03719 else if( ctx->type.dataType.IsDoubleType() )
03720 {
03721 ConvertToTempVariableNotIn(ctx, reservedVars);
03722 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03723 int offset = AllocateVariableNotIn(to, true, reservedVars);
03724 ctx->bc.InstrW_W(asBC_dTOf, offset, ctx->type.stackOffset);
03725 ctx->type.SetVariable(to, offset, true);
03726 }
03727 }
03728 else if( to.IsDoubleType() )
03729 {
03730 if( (ctx->type.dataType.IsIntegerType() || ctx->type.dataType.IsEnumType()) && ctx->type.dataType.GetSizeInMemoryDWords() == 1 )
03731 {
03732 ConvertToTempVariableNotIn(ctx, reservedVars);
03733 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03734 int offset = AllocateVariableNotIn(to, true, reservedVars);
03735 ctx->bc.InstrW_W(asBC_iTOd, offset, ctx->type.stackOffset);
03736 ctx->type.SetVariable(to, offset, true);
03737 }
03738 else if( ctx->type.dataType.IsIntegerType() && ctx->type.dataType.GetSizeInMemoryDWords() == 2 )
03739 {
03740 ConvertToTempVariableNotIn(ctx, reservedVars);
03741 ctx->bc.InstrSHORT(asBC_i64TOd, ctx->type.stackOffset);
03742 ctx->type.dataType.SetTokenType(to.GetTokenType());
03743 ctx->type.dataType.SetObjectType(to.GetObjectType());
03744 }
03745 else if( ctx->type.dataType.IsUnsignedType() && ctx->type.dataType.GetSizeInMemoryDWords() == 1 )
03746 {
03747 ConvertToTempVariableNotIn(ctx, reservedVars);
03748 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03749 int offset = AllocateVariableNotIn(to, true, reservedVars);
03750 ctx->bc.InstrW_W(asBC_uTOd, offset, ctx->type.stackOffset);
03751 ctx->type.SetVariable(to, offset, true);
03752 }
03753 else if( ctx->type.dataType.IsUnsignedType() && ctx->type.dataType.GetSizeInMemoryDWords() == 2 )
03754 {
03755 ConvertToTempVariableNotIn(ctx, reservedVars);
03756 ctx->bc.InstrSHORT(asBC_u64TOd, ctx->type.stackOffset);
03757 ctx->type.dataType.SetTokenType(to.GetTokenType());
03758 ctx->type.dataType.SetObjectType(to.GetObjectType());
03759 }
03760 else if( ctx->type.dataType.IsFloatType() )
03761 {
03762 ConvertToTempVariableNotIn(ctx, reservedVars);
03763 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
03764 int offset = AllocateVariableNotIn(to, true, reservedVars);
03765 ctx->bc.InstrW_W(asBC_fTOd, offset, ctx->type.stackOffset);
03766 ctx->type.SetVariable(to, offset, true);
03767 }
03768 }
03769 }
03770 else
03771 {
03772 if( (to.IsIntegerType() || to.IsUnsignedType() ||
03773 to.IsFloatType() || to.IsDoubleType() ||
03774 (to.IsEnumType() && convType == asIC_EXPLICIT_VAL_CAST)) &&
03775 (ctx->type.dataType.IsIntegerType() || ctx->type.dataType.IsUnsignedType() ||
03776 ctx->type.dataType.IsFloatType() || ctx->type.dataType.IsDoubleType() ||
03777 ctx->type.dataType.IsEnumType()) )
03778 {
03779 ctx->type.dataType.SetTokenType(to.GetTokenType());
03780 ctx->type.dataType.SetObjectType(to.GetObjectType());
03781 }
03782 }
03783
03784
03785 ctx->type.dataType.MakeReadOnly(to.IsReadOnly());
03786 }
03787
03788 void asCCompiler::ImplicitConversion(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, asCArray<int> *reservedVars, bool allowObjectConstruct)
03789 {
03790
03791 if( ctx->type.dataType.GetTokenType() == ttVoid )
03792 return;
03793
03794
03795 if( to.GetTokenType() == ttQuestion )
03796 {
03797
03798 asASSERT( !generateCode );
03799
03800 ctx->type.dataType = to;
03801
03802 return;
03803 }
03804
03805 else if( to.IsPrimitive() )
03806 {
03807 if( !ctx->type.dataType.IsPrimitive() )
03808 ImplicitConvObjectToPrimitive(ctx, to, node, convType, generateCode, reservedVars);
03809 else
03810 ImplicitConvPrimitiveToPrimitive(ctx, to, node, convType, generateCode, reservedVars);
03811 }
03812 else
03813 {
03814 if( ctx->type.dataType.IsPrimitive() )
03815 ImplicitConvPrimitiveToObject(ctx, to, node, convType, generateCode, reservedVars, allowObjectConstruct);
03816 else
03817 ImplicitConvObjectToObject(ctx, to, node, convType, generateCode, reservedVars, allowObjectConstruct);
03818 }
03819 }
03820
03821 void asCCompiler::ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, asCArray<int> *reservedVars)
03822 {
03823 if( ctx->type.isExplicitHandle )
03824 {
03825
03826 if( convType != asIC_IMPLICIT_CONV && node )
03827 {
03828 asCString str;
03829 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, ctx->type.dataType.Format().AddressOf(), to.Format().AddressOf());
03830 Error(str.AddressOf(), node);
03831 }
03832 return;
03833 }
03834
03835
03836
03837
03838
03839 asCArray<int> funcs;
03840 asSTypeBehaviour *beh = ctx->type.dataType.GetBehaviour();
03841 if( beh )
03842 {
03843 if( convType == asIC_EXPLICIT_VAL_CAST )
03844 {
03845 for( unsigned int n = 0; n < beh->operators.GetLength(); n += 2 )
03846 {
03847
03848 if( (beh->operators[n] == asBEHAVE_VALUE_CAST ||
03849 beh->operators[n] == asBEHAVE_IMPLICIT_VALUE_CAST) &&
03850 builder->GetFunctionDescription(beh->operators[n+1])->returnType.IsPrimitive() )
03851 funcs.PushLast(beh->operators[n+1]);
03852 }
03853 }
03854 else
03855 {
03856 for( unsigned int n = 0; n < beh->operators.GetLength(); n += 2 )
03857 {
03858
03859 if( beh->operators[n] == asBEHAVE_IMPLICIT_VALUE_CAST &&
03860 builder->GetFunctionDescription(beh->operators[n+1])->returnType.IsPrimitive() )
03861 funcs.PushLast(beh->operators[n+1]);
03862 }
03863 }
03864 }
03865
03866
03867
03868 eTokenType matchMtx[10][10] =
03869 {
03870 {ttDouble, ttFloat, ttInt64, ttUInt64, ttInt, ttUInt, ttInt16, ttUInt16, ttInt8, ttUInt8},
03871 {ttFloat, ttDouble, ttInt64, ttUInt64, ttInt, ttUInt, ttInt16, ttUInt16, ttInt8, ttUInt8},
03872 {ttInt64, ttUInt64, ttInt, ttUInt, ttInt16, ttUInt16, ttInt8, ttUInt8, ttDouble, ttFloat},
03873 {ttUInt64, ttInt64, ttUInt, ttInt, ttUInt16, ttInt16, ttUInt8, ttInt8, ttDouble, ttFloat},
03874 {ttInt, ttUInt, ttInt64, ttUInt64, ttInt16, ttUInt16, ttInt8, ttUInt8, ttDouble, ttFloat},
03875 {ttUInt, ttInt, ttUInt64, ttInt64, ttUInt16, ttInt16, ttUInt8, ttInt8, ttDouble, ttFloat},
03876 {ttInt16, ttUInt16, ttInt, ttUInt, ttInt64, ttUInt64, ttInt8, ttUInt8, ttDouble, ttFloat},
03877 {ttUInt16, ttInt16, ttUInt, ttInt, ttUInt64, ttInt64, ttUInt8, ttInt8, ttDouble, ttFloat},
03878 {ttInt8, ttUInt8, ttInt16, ttUInt16, ttInt, ttUInt, ttInt64, ttUInt64, ttDouble, ttFloat},
03879 {ttUInt8, ttInt8, ttUInt16, ttInt16, ttUInt, ttInt, ttUInt64, ttInt64, ttDouble, ttFloat},
03880 };
03881
03882
03883 eTokenType *row = 0;
03884 for( unsigned int type = 0; type < 10; type++ )
03885 {
03886 if( to.GetTokenType() == matchMtx[type][0] )
03887 {
03888 row = &matchMtx[type][0];
03889 break;
03890 }
03891 }
03892
03893
03894 int funcId = 0;
03895 if( row )
03896 {
03897 asCDataType target(to);
03898
03899
03900 for( unsigned int attempt = 0; attempt < 10 && funcId == 0; attempt++ )
03901 {
03902 target.SetTokenType(row[attempt]);
03903 for( unsigned int n = 0; n < funcs.GetLength(); n++ )
03904 {
03905 asCScriptFunction *descr = builder->GetFunctionDescription(funcs[n]);
03906 if( descr->returnType.IsEqualExceptConst(target) )
03907 {
03908 funcId = funcs[n];
03909 break;
03910 }
03911 }
03912 }
03913 }
03914
03915
03916 if( funcId != 0 )
03917 {
03918 asCScriptFunction *descr = builder->GetFunctionDescription(funcId);
03919 if( generateCode )
03920 {
03921 asCTypeInfo objType = ctx->type;
03922
03923 Dereference(ctx, true);
03924
03925 PerformFunctionCall(funcId, ctx);
03926
03927 ReleaseTemporaryVariable(objType, &ctx->bc);
03928 }
03929 else
03930 ctx->type.Set(descr->returnType);
03931
03932
03933 ImplicitConversion(ctx, to, node, convType, generateCode, reservedVars, false);
03934 }
03935 else
03936 {
03937 if( convType != asIC_IMPLICIT_CONV && node )
03938 {
03939 asCString str;
03940 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, ctx->type.dataType.Format().AddressOf(), to.Format().AddressOf());
03941 Error(str.AddressOf(), node);
03942 }
03943 }
03944 }
03945
03946 void asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, asCArray<int> *reservedVars, bool allowObjectConstruct)
03947 {
03948
03949 if( ctx->type.IsNullConstant() )
03950 {
03951 if( to.IsObjectHandle() )
03952 ctx->type.dataType = to;
03953
03954 return;
03955 }
03956
03957
03958 if( to.GetObjectType() != ctx->type.dataType.GetObjectType() )
03959 {
03960
03961 if( ctx->type.dataType.GetObjectType()->Implements(to.GetObjectType()) )
03962 {
03963 ctx->type.dataType.SetObjectType(to.GetObjectType());
03964 }
03965
03966
03967 if( ctx->type.dataType.GetObjectType()->DerivesFrom(to.GetObjectType()) )
03968 {
03969 ctx->type.dataType.SetObjectType(to.GetObjectType());
03970 }
03971
03972
03973 if( ctx->type.dataType.GetObjectType() != to.GetObjectType() )
03974 {
03975
03976 bool isConst = false;
03977 if( (ctx->type.dataType.IsObjectHandle() && ctx->type.dataType.IsHandleToConst()) ||
03978 (!ctx->type.dataType.IsObjectHandle() && ctx->type.dataType.IsReadOnly()) )
03979 isConst = true;
03980
03981
03982 CompileRefCast(ctx, to, convType == asIC_EXPLICIT_REF_CAST, node, generateCode);
03983
03984 ctx->type.dataType.MakeHandleToConst(isConst);
03985 }
03986 }
03987
03988
03989
03990 if( to.GetObjectType() != ctx->type.dataType.GetObjectType() && allowObjectConstruct )
03991 {
03992
03993
03994 asCArray<int> funcs;
03995 asSTypeBehaviour *beh = ctx->type.dataType.GetBehaviour();
03996 if( beh )
03997 {
03998 if( convType == asIC_EXPLICIT_VAL_CAST )
03999 {
04000 for( unsigned int n = 0; n < beh->operators.GetLength(); n += 2 )
04001 {
04002
04003 if( (beh->operators[n] == asBEHAVE_VALUE_CAST ||
04004 beh->operators[n] == asBEHAVE_IMPLICIT_VALUE_CAST) &&
04005 builder->GetFunctionDescription(beh->operators[n+1])->returnType.GetObjectType() == to.GetObjectType() )
04006 funcs.PushLast(beh->operators[n+1]);
04007 }
04008 }
04009 else
04010 {
04011 for( unsigned int n = 0; n < beh->operators.GetLength(); n += 2 )
04012 {
04013
04014 if( beh->operators[n] == asBEHAVE_IMPLICIT_VALUE_CAST &&
04015 builder->GetFunctionDescription(beh->operators[n+1])->returnType.GetObjectType() == to.GetObjectType() )
04016 funcs.PushLast(beh->operators[n+1]);
04017 }
04018 }
04019 }
04020
04021
04022 asASSERT( funcs.GetLength() <= 1 );
04023
04024 if( funcs.GetLength() == 1 )
04025 {
04026 asCScriptFunction *f = builder->GetFunctionDescription(funcs[0]);
04027 if( generateCode )
04028 {
04029 asCTypeInfo objType = ctx->type;
04030 Dereference(ctx, true);
04031 PerformFunctionCall(funcs[0], ctx);
04032 ReleaseTemporaryVariable(objType, &ctx->bc);
04033 }
04034 else
04035 ctx->type.Set(f->returnType);
04036 }
04037 }
04038
04039
04040 if( to.GetObjectType() != ctx->type.dataType.GetObjectType() )
04041 return;
04042
04043
04044
04045
04046
04047 if( to.IsObjectHandle() )
04048 {
04049
04050 if( ctx->type.dataType.SupportHandles() )
04051 {
04052 ctx->type.dataType.MakeHandle(true);
04053 }
04054
04055 if( ctx->type.dataType.IsObjectHandle() )
04056 ctx->type.dataType.MakeReadOnly(to.IsReadOnly());
04057
04058 if( to.IsHandleToConst() && ctx->type.dataType.IsObjectHandle() )
04059 ctx->type.dataType.MakeHandleToConst(true);
04060 }
04061
04062 if( !to.IsReference() )
04063 {
04064 if( ctx->type.dataType.IsReference() )
04065 {
04066 Dereference(ctx, generateCode);
04067
04068
04069 }
04070
04071 if( to.IsObjectHandle() )
04072 {
04073
04074
04075
04076
04077 if( ctx->type.dataType.IsReadOnly() && !to.IsReadOnly() )
04078 {
04079 if( convType != asIC_IMPLICIT_CONV )
04080 {
04081 asASSERT(node);
04082 asCString str;
04083 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, ctx->type.dataType.Format().AddressOf(), to.Format().AddressOf());
04084 Error(str.AddressOf(), node);
04085 }
04086 }
04087 }
04088 else
04089 {
04090 if( ctx->type.dataType.IsObjectHandle() && !ctx->type.isExplicitHandle )
04091 {
04092 if( generateCode )
04093 ctx->bc.Instr(asBC_CHKREF);
04094
04095 ctx->type.dataType.MakeHandle(false);
04096 }
04097
04098
04099 if( ctx->type.dataType.IsReadOnly() && !to.IsReadOnly() &&
04100 allowObjectConstruct )
04101 {
04102
04103 if( ctx->type.dataType.CanBeCopied() )
04104 {
04105 if( generateCode )
04106 {
04107
04108 PrepareTemporaryObject(node, ctx, reservedVars);
04109 }
04110 else
04111 ctx->type.dataType.MakeReadOnly(false);
04112 }
04113 }
04114
04115
04116 if( !ctx->type.dataType.IsReadOnly() && to.IsReadOnly() )
04117 {
04118 ctx->type.dataType.MakeReadOnly(true);
04119 }
04120 }
04121 }
04122 else
04123 {
04124 if( ctx->type.dataType.IsReference() )
04125 {
04126
04127
04128 if( !to.IsObjectHandle() && ctx->type.dataType.IsObjectHandle() && !ctx->type.isExplicitHandle )
04129 {
04130 ctx->type.dataType.MakeHandle(false);
04131 if( generateCode )
04132 ctx->bc.Instr(asBC_ChkRefS);
04133 }
04134
04135
04136 if( to.IsReadOnly() )
04137 ctx->type.dataType.MakeReadOnly(true);
04138 else if( ctx->type.dataType.IsReadOnly() )
04139 {
04140
04141
04142 ctx->type.dataType.MakeReadOnly(false);
04143
04144 if( generateCode )
04145 {
04146
04147 asSExprContext lctx(engine);
04148 asCDataType dt = ctx->type.dataType;
04149 dt.MakeReference(false);
04150 int offset = AllocateVariableNotIn(dt, true, reservedVars);
04151 lctx.type = ctx->type;
04152 lctx.type.isTemporary = true;
04153 lctx.type.stackOffset = (short)offset;
04154
04155 CallDefaultConstructor(lctx.type.dataType, offset, &lctx.bc, node);
04156
04157
04158 asSExprContext rctx(engine);
04159 rctx.type = ctx->type;
04160 rctx.bc.AddCode(&lctx.bc);
04161 rctx.bc.AddCode(&ctx->bc);
04162
04163
04164 lctx.bc.InstrSHORT(asBC_PSF, (short)offset);
04165
04166
04167
04168 lctx.type.isTemporary = false;
04169
04170 DoAssignment(ctx, &lctx, &rctx, node, node, ttAssignment, node);
04171
04172
04173
04174 ProcessDeferredParams(ctx);
04175
04176 ctx->type = lctx.type;
04177 ctx->type.isTemporary = true;
04178 }
04179 }
04180 }
04181 else
04182 {
04183 if( generateCode )
04184 {
04185 asCTypeInfo type;
04186 type.Set(ctx->type.dataType);
04187
04188
04189 int offset = AllocateVariableNotIn(type.dataType, true, reservedVars);
04190 type.isTemporary = true;
04191 type.stackOffset = (short)offset;
04192 if( type.dataType.IsObjectHandle() )
04193 type.isExplicitHandle = true;
04194
04195 CallDefaultConstructor(type.dataType, offset, &ctx->bc, node);
04196 type.dataType.MakeReference(true);
04197
04198 PrepareForAssignment(&type.dataType, ctx, node);
04199
04200 ctx->bc.InstrSHORT(asBC_PSF, type.stackOffset);
04201
04202
04203
04204 bool typeIsReadOnly = type.dataType.IsReadOnly();
04205 type.dataType.MakeReadOnly(false);
04206 PerformAssignment(&type, &ctx->type, &ctx->bc, node);
04207 type.dataType.MakeReadOnly(typeIsReadOnly);
04208
04209 ctx->bc.Pop(ctx->type.dataType.GetSizeOnStackDWords());
04210
04211 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
04212
04213 ctx->bc.InstrSHORT(asBC_PSF, type.stackOffset);
04214
04215 ctx->type = type;
04216 }
04217
04218
04219
04220 ctx->type.dataType.MakeReference(true);
04221
04222
04223 ctx->type.dataType.MakeReadOnly(to.IsReadOnly());
04224 }
04225 }
04226 }
04227
04228 void asCCompiler::ImplicitConvPrimitiveToObject(asSExprContext * , const asCDataType & , asCScriptNode * , EImplicitConv , bool , asCArray<int> * , bool )
04229 {
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320 }
04321
04322 void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCDataType &to, asCScriptNode *node, EImplicitConv convType)
04323 {
04324 asASSERT(from->type.isConstant);
04325
04326
04327
04328
04329
04330
04331 if( to.IsEqualExceptRefAndConst(from->type.dataType) ) return;
04332
04333
04334 if( from->type.dataType.IsReference() ) return;
04335
04336
04337 if( to.IsArrayType() ) return;
04338
04339 if( (to.IsIntegerType() && to.GetSizeInMemoryDWords() == 1) ||
04340 (to.IsEnumType() && convType == asIC_EXPLICIT_VAL_CAST) )
04341 {
04342 if( from->type.dataType.IsFloatType() ||
04343 from->type.dataType.IsDoubleType() ||
04344 from->type.dataType.IsUnsignedType() ||
04345 from->type.dataType.IsIntegerType() ||
04346 from->type.dataType.IsEnumType() )
04347 {
04348
04349
04350 if( from->type.dataType.IsFloatType() )
04351 {
04352 float fc = from->type.floatValue;
04353 int ic = int(fc);
04354
04355 if( float(ic) != fc )
04356 {
04357 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04358 }
04359
04360 from->type.intValue = ic;
04361 }
04362
04363 else if( from->type.dataType.IsDoubleType() )
04364 {
04365 double fc = from->type.doubleValue;
04366 int ic = int(fc);
04367
04368 if( double(ic) != fc )
04369 {
04370 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04371 }
04372
04373 from->type.intValue = ic;
04374 }
04375 else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 1 )
04376 {
04377
04378 if( from->type.intValue < 0 )
04379 {
04380 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node);
04381 }
04382
04383
04384 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04385 from->type.intValue = from->type.byteValue;
04386 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04387 from->type.intValue = from->type.wordValue;
04388 }
04389 else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 2 )
04390 {
04391
04392 from->type.intValue = int(from->type.qwordValue);
04393 }
04394 else if( from->type.dataType.IsIntegerType() &&
04395 from->type.dataType.GetSizeInMemoryBytes() < 4 )
04396 {
04397
04398 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04399 from->type.intValue = (signed char)from->type.byteValue;
04400 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04401 from->type.intValue = (short)from->type.wordValue;
04402 }
04403 else if( from->type.dataType.IsEnumType() )
04404 {
04405
04406 }
04407
04408
04409 if( to.IsEnumType() )
04410 from->type.dataType = to;
04411 else
04412 from->type.dataType = asCDataType::CreatePrimitive(ttInt, true);
04413 }
04414
04415
04416 if( to.IsIntegerType() &&
04417 from->type.dataType.IsIntegerType() &&
04418 from->type.dataType.GetSizeInMemoryBytes() > to.GetSizeInMemoryBytes() )
04419 {
04420
04421 if( to.GetSizeInMemoryBytes() == 1 )
04422 {
04423 if( char(from->type.intValue) != from->type.intValue )
04424 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
04425
04426 from->type.byteValue = char(from->type.intValue);
04427 }
04428 else if( to.GetSizeInMemoryBytes() == 2 )
04429 {
04430 if( short(from->type.intValue) != from->type.intValue )
04431 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
04432
04433 from->type.wordValue = short(from->type.intValue);
04434 }
04435
04436 from->type.dataType.SetTokenType(to.GetTokenType());
04437 }
04438 }
04439 else if( to.IsIntegerType() && to.GetSizeInMemoryDWords() == 2 )
04440 {
04441
04442 if( from->type.dataType.IsFloatType() )
04443 {
04444 float fc = from->type.floatValue;
04445 asINT64 ic = asINT64(fc);
04446
04447 if( float(ic) != fc )
04448 {
04449 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04450 }
04451
04452 from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true);
04453 from->type.qwordValue = ic;
04454 }
04455
04456 else if( from->type.dataType.IsDoubleType() )
04457 {
04458 double fc = from->type.doubleValue;
04459 asINT64 ic = asINT64(fc);
04460
04461 if( double(ic) != fc )
04462 {
04463 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04464 }
04465
04466 from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true);
04467 from->type.qwordValue = ic;
04468 }
04469 else if( from->type.dataType.IsUnsignedType() )
04470 {
04471
04472 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04473 from->type.qwordValue = from->type.byteValue;
04474 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04475 from->type.qwordValue = from->type.wordValue;
04476 else if( from->type.dataType.GetSizeInMemoryBytes() == 4 )
04477 from->type.qwordValue = from->type.dwordValue;
04478 else if( from->type.dataType.GetSizeInMemoryBytes() == 8 )
04479 {
04480 if( asINT64(from->type.qwordValue) < 0 )
04481 {
04482 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node);
04483 }
04484 }
04485
04486 from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true);
04487 }
04488 else if( from->type.dataType.IsEnumType() )
04489 {
04490 from->type.qwordValue = from->type.intValue;
04491 from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true);
04492 }
04493 else if( from->type.dataType.IsIntegerType() )
04494 {
04495
04496 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04497 from->type.qwordValue = (signed char)from->type.byteValue;
04498 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04499 from->type.qwordValue = (short)from->type.wordValue;
04500 else if( from->type.dataType.GetSizeInMemoryBytes() == 4 )
04501 from->type.qwordValue = from->type.intValue;
04502
04503 from->type.dataType = asCDataType::CreatePrimitive(ttInt64, true);
04504 }
04505 }
04506 else if( to.IsUnsignedType() && to.GetSizeInMemoryDWords() == 1 )
04507 {
04508 if( from->type.dataType.IsFloatType() )
04509 {
04510 float fc = from->type.floatValue;
04511 int uic = int(fc);
04512
04513 if( float(uic) != fc )
04514 {
04515 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04516 }
04517 else if( uic < 0 )
04518 {
04519 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node);
04520 }
04521
04522 from->type.dataType = asCDataType::CreatePrimitive(ttInt, true);
04523 from->type.intValue = uic;
04524
04525
04526 ImplicitConversionConstant(from, to, node, convType);
04527 }
04528 else if( from->type.dataType.IsDoubleType() )
04529 {
04530 double fc = from->type.doubleValue;
04531 int uic = int(fc);
04532
04533 if( double(uic) != fc )
04534 {
04535 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04536 }
04537
04538 from->type.dataType = asCDataType::CreatePrimitive(ttInt, true);
04539 from->type.intValue = uic;
04540
04541
04542 ImplicitConversionConstant(from, to, node, convType);
04543 }
04544 else if( from->type.dataType.IsEnumType() )
04545 {
04546 from->type.dataType = asCDataType::CreatePrimitive(ttUInt, true);
04547
04548
04549 ImplicitConversionConstant(from, to, node, convType);
04550 }
04551 else if( from->type.dataType.IsIntegerType() )
04552 {
04553
04554 if( from->type.intValue < 0 )
04555 {
04556 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node);
04557 }
04558
04559
04560 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04561 from->type.intValue = (signed char)from->type.byteValue;
04562 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04563 from->type.intValue = (short)from->type.wordValue;
04564
04565 from->type.dataType = asCDataType::CreatePrimitive(ttUInt, true);
04566
04567
04568 ImplicitConversionConstant(from, to, node, convType);
04569 }
04570 else if( from->type.dataType.IsUnsignedType() &&
04571 from->type.dataType.GetSizeInMemoryBytes() < 4 )
04572 {
04573
04574 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04575 from->type.dwordValue = from->type.byteValue;
04576 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04577 from->type.dwordValue = from->type.wordValue;
04578
04579 from->type.dataType = asCDataType::CreatePrimitive(ttUInt, true);
04580
04581
04582 ImplicitConversionConstant(from, to, node, convType);
04583 }
04584 else if( from->type.dataType.IsUnsignedType() &&
04585 from->type.dataType.GetSizeInMemoryBytes() > to.GetSizeInMemoryBytes() )
04586 {
04587
04588 if( to.GetSizeInMemoryBytes() == 1 )
04589 {
04590 if( asBYTE(from->type.dwordValue) != from->type.dwordValue )
04591 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
04592
04593 from->type.byteValue = asBYTE(from->type.dwordValue);
04594 }
04595 else if( to.GetSizeInMemoryBytes() == 2 )
04596 {
04597 if( asWORD(from->type.dwordValue) != from->type.dwordValue )
04598 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
04599
04600 from->type.wordValue = asWORD(from->type.dwordValue);
04601 }
04602
04603 from->type.dataType.SetTokenType(to.GetTokenType());
04604 }
04605 }
04606 else if( to.IsUnsignedType() && to.GetSizeInMemoryDWords() == 2 )
04607 {
04608 if( from->type.dataType.IsFloatType() )
04609 {
04610 float fc = from->type.floatValue;
04611
04612 asQWORD uic = asQWORD(asINT64(fc));
04613
04614
04615 if( float((signed)uic) != fc )
04616 {
04617 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04618 }
04619
04620 from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true);
04621 from->type.qwordValue = uic;
04622 }
04623 else if( from->type.dataType.IsDoubleType() )
04624 {
04625 double fc = from->type.doubleValue;
04626
04627 asQWORD uic = asQWORD(asINT64(fc));
04628
04629
04630 if( double((signed)uic) != fc )
04631 {
04632 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04633 }
04634
04635 from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true);
04636 from->type.qwordValue = uic;
04637 }
04638 else if( from->type.dataType.IsEnumType() )
04639 {
04640 from->type.qwordValue = (asINT64)from->type.intValue;
04641 from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true);
04642 }
04643 else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 1 )
04644 {
04645
04646 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04647 from->type.qwordValue = (asINT64)(signed char)from->type.byteValue;
04648 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04649 from->type.qwordValue = (asINT64)(short)from->type.wordValue;
04650 else if( from->type.dataType.GetSizeInMemoryBytes() == 4 )
04651 from->type.qwordValue = (asINT64)from->type.intValue;
04652
04653
04654 if( asINT64(from->type.qwordValue) < 0 )
04655 {
04656 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node);
04657 }
04658
04659 from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true);
04660 }
04661 else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 2 )
04662 {
04663
04664 if( asINT64(from->type.qwordValue) < 0 )
04665 {
04666 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node);
04667 }
04668
04669 from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true);
04670 }
04671 else if( from->type.dataType.IsUnsignedType() )
04672 {
04673
04674 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04675 from->type.qwordValue = from->type.byteValue;
04676 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04677 from->type.qwordValue = from->type.wordValue;
04678 else if( from->type.dataType.GetSizeInMemoryBytes() == 4 )
04679 from->type.qwordValue = from->type.dwordValue;
04680
04681 from->type.dataType = asCDataType::CreatePrimitive(ttUInt64, true);
04682 }
04683 }
04684 else if( to.IsFloatType() )
04685 {
04686 if( from->type.dataType.IsDoubleType() )
04687 {
04688 double ic = from->type.doubleValue;
04689 float fc = float(ic);
04690
04691 if( double(fc) != ic )
04692 {
04693 asCString str;
04694 str.Format(TXT_POSSIBLE_LOSS_OF_PRECISION);
04695 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(str.AddressOf(), node);
04696 }
04697
04698 from->type.dataType.SetTokenType(to.GetTokenType());
04699 from->type.floatValue = fc;
04700 }
04701 else if( from->type.dataType.IsEnumType() )
04702 {
04703 float fc = float(from->type.intValue);
04704
04705 if( int(fc) != from->type.intValue )
04706 {
04707 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04708 }
04709
04710 from->type.dataType.SetTokenType(to.GetTokenType());
04711 from->type.floatValue = fc;
04712 }
04713 else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 1 )
04714 {
04715
04716 int ic;
04717 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04718 ic = (signed char)from->type.byteValue;
04719 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04720 ic = (short)from->type.wordValue;
04721 else
04722 ic = from->type.intValue;
04723 float fc = float(ic);
04724
04725 if( int(fc) != ic )
04726 {
04727 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04728 }
04729
04730 from->type.dataType.SetTokenType(to.GetTokenType());
04731 from->type.floatValue = fc;
04732 }
04733 else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 2 )
04734 {
04735 float fc = float(asINT64(from->type.qwordValue));
04736 if( asINT64(fc) != asINT64(from->type.qwordValue) )
04737 {
04738 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04739 }
04740
04741 from->type.dataType.SetTokenType(to.GetTokenType());
04742 from->type.floatValue = fc;
04743 }
04744 else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 1 )
04745 {
04746
04747 unsigned int uic;
04748 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04749 uic = from->type.byteValue;
04750 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04751 uic = from->type.wordValue;
04752 else
04753 uic = from->type.dwordValue;
04754 float fc = float(uic);
04755
04756 if( (unsigned int)(fc) != uic )
04757 {
04758 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04759 }
04760
04761 from->type.dataType.SetTokenType(to.GetTokenType());
04762 from->type.floatValue = fc;
04763 }
04764 else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 2 )
04765 {
04766
04767 float fc = float((signed)from->type.qwordValue);
04768
04769 if( asQWORD(fc) != from->type.qwordValue )
04770 {
04771 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04772 }
04773
04774 from->type.dataType.SetTokenType(to.GetTokenType());
04775 from->type.floatValue = fc;
04776 }
04777 }
04778 else if( to.IsDoubleType() )
04779 {
04780 if( from->type.dataType.IsFloatType() )
04781 {
04782 float ic = from->type.floatValue;
04783 double fc = double(ic);
04784
04785
04786
04787
04788
04789
04790
04791
04792
04793 from->type.dataType.SetTokenType(to.GetTokenType());
04794 from->type.doubleValue = fc;
04795 }
04796 else if( from->type.dataType.IsEnumType() )
04797 {
04798 double fc = double(from->type.intValue);
04799
04800 if( int(fc) != from->type.intValue )
04801 {
04802 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04803 }
04804
04805 from->type.dataType.SetTokenType(to.GetTokenType());
04806 from->type.doubleValue = fc;
04807 }
04808 else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 1 )
04809 {
04810
04811 int ic;
04812 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04813 ic = (signed char)from->type.byteValue;
04814 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04815 ic = (short)from->type.wordValue;
04816 else
04817 ic = from->type.intValue;
04818 double fc = double(ic);
04819
04820 if( int(fc) != ic )
04821 {
04822 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04823 }
04824
04825 from->type.dataType.SetTokenType(to.GetTokenType());
04826 from->type.doubleValue = fc;
04827 }
04828 else if( from->type.dataType.IsIntegerType() && from->type.dataType.GetSizeInMemoryDWords() == 2 )
04829 {
04830 double fc = double(asINT64(from->type.qwordValue));
04831
04832 if( asINT64(fc) != asINT64(from->type.qwordValue) )
04833 {
04834 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04835 }
04836
04837 from->type.dataType.SetTokenType(to.GetTokenType());
04838 from->type.doubleValue = fc;
04839 }
04840 else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 1 )
04841 {
04842
04843 unsigned int uic;
04844 if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
04845 uic = from->type.byteValue;
04846 else if( from->type.dataType.GetSizeInMemoryBytes() == 2 )
04847 uic = from->type.wordValue;
04848 else
04849 uic = from->type.dwordValue;
04850 double fc = double(uic);
04851
04852 if( (unsigned int)(fc) != uic )
04853 {
04854 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04855 }
04856
04857 from->type.dataType.SetTokenType(to.GetTokenType());
04858 from->type.doubleValue = fc;
04859 }
04860 else if( from->type.dataType.IsUnsignedType() && from->type.dataType.GetSizeInMemoryDWords() == 2 )
04861 {
04862
04863 double fc = double((signed)from->type.qwordValue);
04864
04865 if( asQWORD(fc) != from->type.qwordValue )
04866 {
04867 if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_NOT_EXACT, node);
04868 }
04869
04870 from->type.dataType.SetTokenType(to.GetTokenType());
04871 from->type.doubleValue = fc;
04872 }
04873 }
04874 }
04875
04876 int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, int op, asCScriptNode *opNode)
04877 {
04878
04879 if (lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE) )
04880 {
04881 lctx->type.dataType.MakeHandle(true);
04882 lctx->type.isExplicitHandle = true;
04883 }
04884
04885
04886
04887
04888
04889 if( (lctx->property_get || lctx->property_set) &&
04890 !(lctx->type.dataType.IsObjectHandle() && !lctx->type.isExplicitHandle) )
04891 {
04892 if( op != ttAssignment )
04893 {
04894
04895
04896
04897
04898
04899 Error(TXT_COMPOUND_ASGN_WITH_PROP, opNode);
04900 return -1;
04901 }
04902
04903 MergeExprContexts(ctx, lctx);
04904 ctx->property_get = lctx->property_get;
04905 ctx->property_set = lctx->property_set;
04906 ctx->property_const = lctx->property_const;
04907
04908 return ProcessPropertySetAccessor(ctx, rctx, opNode);
04909 }
04910
04911 if( lctx->type.dataType.IsPrimitive() )
04912 {
04913 if( op != ttAssignment )
04914 {
04915
04916 asCTypeInfo lvalue = lctx->type;
04917
04918 if( lctx->type.isTemporary && !lctx->type.isVariable )
04919 {
04920
04921
04922
04923 lctx->type.isTemporary = false;
04924 }
04925
04926 asSExprContext o(engine);
04927 CompileOperator(opNode, lctx, rctx, &o);
04928 MergeExprContexts(rctx, &o);
04929 rctx->type = o.type;
04930
04931
04932 PrepareForAssignment(&lvalue.dataType, rctx, rexpr);
04933
04934 MergeExprContexts(ctx, rctx);
04935 lctx->type = lvalue;
04936
04937
04938 }
04939 else
04940 {
04941
04942 PrepareForAssignment(&lctx->type.dataType, rctx, rexpr, lctx);
04943
04944 MergeExprContexts(ctx, rctx);
04945 MergeExprContexts(ctx, lctx);
04946 }
04947
04948 ReleaseTemporaryVariable(rctx->type, &ctx->bc);
04949
04950 PerformAssignment(&lctx->type, &rctx->type, &ctx->bc, opNode);
04951
04952 ctx->type = lctx->type;
04953 }
04954 else if( lctx->type.isExplicitHandle )
04955 {
04956
04957 if( lctx->type.isTemporary )
04958 {
04959 Error(TXT_REF_IS_TEMP, lexpr);
04960 return -1;
04961 }
04962
04963
04964 if( op != ttAssignment )
04965 {
04966 asCString str;
04967 str.Format(TXT_ILLEGAL_OPERATION_ON_s, lctx->type.dataType.Format().AddressOf());
04968 Error(str.AddressOf(), lexpr);
04969 return -1;
04970 }
04971
04972 asCDataType dt = lctx->type.dataType;
04973 dt.MakeReference(false);
04974
04975 PrepareArgument(&dt, rctx, rexpr, true, 1);
04976 if( !dt.IsEqualExceptRefAndConst(rctx->type.dataType) )
04977 {
04978 asCString str;
04979 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, rctx->type.dataType.Format().AddressOf(), lctx->type.dataType.Format().AddressOf());
04980 Error(str.AddressOf(), rexpr);
04981 return -1;
04982 }
04983
04984 MergeExprContexts(ctx, rctx);
04985 MergeExprContexts(ctx, lctx);
04986
04987 ctx->bc.InstrWORD(asBC_GETOBJREF, AS_PTR_SIZE);
04988
04989 PerformAssignment(&lctx->type, &rctx->type, &ctx->bc, opNode);
04990
04991 ReleaseTemporaryVariable(rctx->type, &ctx->bc);
04992
04993 ctx->type = rctx->type;
04994 }
04995 else
04996 {
04997
04998 if( lctx->type.isTemporary )
04999 {
05000 Error(TXT_REF_IS_TEMP, lexpr);
05001 return -1;
05002 }
05003
05004 if( lctx->type.dataType.IsObjectHandle() && !lctx->type.isExplicitHandle )
05005 {
05006
05007 asCDataType to;
05008 to = lctx->type.dataType;
05009 to.MakeHandle(false);
05010 ImplicitConversion(lctx, to, lexpr, asIC_IMPLICIT_CONV);
05011 }
05012
05013
05014 if( CompileOverloadedDualOperator(opNode, lctx, rctx, ctx) )
05015 {
05016
05017 return 0;
05018 }
05019
05020 #ifdef AS_DEPRECATED
05021
05022
05023
05024
05025
05026
05027 asSTypeBehaviour *beh = lctx->type.dataType.GetBehaviour();
05028 asASSERT(beh);
05029
05030 int behaviour = TokenToBehaviour(op);
05031
05032
05033 asCArray<int> ops;
05034 asUINT n;
05035 for( n = 0; n < beh->operators.GetLength(); n += 2 )
05036 {
05037 if( behaviour == beh->operators[n] )
05038 ops.PushLast(beh->operators[n+1]);
05039 }
05040
05041 asCArray<int> match;
05042 MatchArgument(ops, match, &rctx->type, 0);
05043
05044 if( match.GetLength() == 1 )
05045 {
05046
05047 if( lctx->type.dataType.IsReadOnly() )
05048 {
05049 Error(TXT_REF_IS_READ_ONLY, lexpr);
05050 return -1;
05051 }
05052
05053
05054 asCScriptFunction *descr = engine->scriptFunctions[match[0]];
05055 PrepareArgument(&descr->parameterTypes[0], rctx, rexpr, true, descr->inOutFlags[0]);
05056
05057 if( rctx->type.isTemporary && lctx->bc.IsVarUsed(rctx->type.stackOffset) )
05058 {
05059
05060 ReleaseTemporaryVariable(rctx->type, 0);
05061
05062 asCArray<int> usedVars;
05063 lctx->bc.GetVarsUsed(usedVars);
05064 rctx->bc.GetVarsUsed(usedVars);
05065
05066 asCDataType dt = rctx->type.dataType;
05067 dt.MakeReference(false);
05068 int newOffset = AllocateVariableNotIn(dt, true, &usedVars);
05069
05070 rctx->bc.ExchangeVar(rctx->type.stackOffset, newOffset);
05071 rctx->type.stackOffset = (short)newOffset;
05072 rctx->type.isTemporary = true;
05073 rctx->type.isVariable = true;
05074 }
05075
05076
05077 MergeExprContexts(ctx, rctx);
05078
05079
05080 Dereference(lctx, true);
05081 MergeExprContexts(ctx, lctx);
05082
05083 asCArray<asSExprContext*> args;
05084 args.PushLast(rctx);
05085 MoveArgsToStack(match[0], &ctx->bc, args, true);
05086
05087 PerformFunctionCall(match[0], ctx, false, &args);
05088
05089 return 0;
05090 }
05091 else if( match.GetLength() > 1 )
05092 {
05093 Error(TXT_MORE_THAN_ONE_MATCHING_OP, opNode);
05094
05095 ctx->type.Set(lctx->type.dataType);
05096
05097 return -1;
05098 }
05099 #endif
05100
05101
05102
05103
05104
05105 if( op != ttAssignment )
05106 {
05107 asCString str;
05108 str.Format(TXT_ILLEGAL_OPERATION_ON_s, lctx->type.dataType.Format().AddressOf());
05109 Error(str.AddressOf(), lexpr);
05110 return -1;
05111 }
05112
05113
05114 asCDataType dt = lctx->type.dataType;
05115 PrepareArgument(&dt, rctx, rexpr, true, 1);
05116 if( !dt.IsEqualExceptRefAndConst(rctx->type.dataType) )
05117 {
05118 asCString str;
05119 str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, rctx->type.dataType.Format().AddressOf(), lctx->type.dataType.Format().AddressOf());
05120 Error(str.AddressOf(), rexpr);
05121 return -1;
05122 }
05123
05124 MergeExprContexts(ctx, rctx);
05125 MergeExprContexts(ctx, lctx);
05126
05127 ctx->bc.InstrWORD(asBC_GETOBJREF, AS_PTR_SIZE);
05128
05129 PerformAssignment(&lctx->type, &rctx->type, &ctx->bc, opNode);
05130
05131 ReleaseTemporaryVariable(rctx->type, &ctx->bc);
05132
05133 ctx->type = lctx->type;
05134 }
05135
05136 return 0;
05137 }
05138
05139 int asCCompiler::CompileAssignment(asCScriptNode *expr, asSExprContext *ctx)
05140 {
05141 asCScriptNode *lexpr = expr->firstChild;
05142 if( lexpr->next )
05143 {
05144 if( globalExpression )
05145 {
05146 Error(TXT_ASSIGN_IN_GLOBAL_EXPR, expr);
05147 ctx->type.SetDummy();
05148 return -1;
05149 }
05150
05151
05152 asSExprContext lctx(engine), rctx(engine);
05153 int rr = CompileAssignment(lexpr->next->next, &rctx);
05154 int lr = CompileCondition(lexpr, &lctx);
05155
05156 if( lr >= 0 && rr >= 0 )
05157 return DoAssignment(ctx, &lctx, &rctx, lexpr, lexpr->next->next, lexpr->next->tokenType, lexpr->next);
05158
05159
05160 ctx->type.SetDummy();
05161 return -1;
05162 }
05163
05164 return CompileCondition(lexpr, ctx);
05165 }
05166
05167 int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx)
05168 {
05169 asCTypeInfo ctype;
05170
05171
05172 asCScriptNode *cexpr = expr->firstChild;
05173 if( cexpr->next )
05174 {
05175
05176
05177 asSExprContext e(engine);
05178 int r = CompileExpression(cexpr, &e);
05179 if( r < 0 )
05180 e.type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), true);
05181 if( r >= 0 && !e.type.dataType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, true)) )
05182 {
05183 Error(TXT_EXPR_MUST_BE_BOOL, cexpr);
05184 e.type.SetConstantB(asCDataType::CreatePrimitive(ttBool, true), true);
05185 }
05186 ctype = e.type;
05187
05188 ProcessPropertyGetAccessor(&e, cexpr);
05189
05190 if( e.type.dataType.IsReference() ) ConvertToVariable(&e);
05191 ProcessDeferredParams(&e);
05192
05193
05194
05195 asSExprContext le(engine);
05196 int lr = CompileAssignment(cexpr->next, &le);
05197
05198
05199
05200 asSExprContext re(engine);
05201 int rr = CompileAssignment(cexpr->next->next, &re);
05202
05203 if( lr >= 0 && rr >= 0 )
05204 {
05205 ProcessPropertyGetAccessor(&le, cexpr->next);
05206 ProcessPropertyGetAccessor(&re, cexpr->next->next);
05207
05208 bool isExplicitHandle = le.type.isExplicitHandle || re.type.isExplicitHandle;
05209
05210
05211 if( le.type.isConstant && le.type.intValue == 0 && le.type.dataType.IsUnsignedType() )
05212 {
05213 asCDataType to = re.type.dataType;
05214 to.MakeReference(false);
05215 to.MakeReadOnly(true);
05216 ImplicitConversionConstant(&le, to, cexpr->next, asIC_IMPLICIT_CONV);
05217 }
05218
05219
05220
05221 int afterLabel = nextLabel++;
05222 int elseLabel = nextLabel++;
05223
05224
05225 if( le.type.dataType.IsEqualExceptConst(asCDataType::CreatePrimitive(ttVoid, false)) )
05226 {
05227
05228 MergeExprContexts(ctx, &e);
05229
05230
05231 ctx->type = e.type;
05232 ConvertToVariable(ctx);
05233 ctx->bc.InstrSHORT(asBC_CpyVtoR4, ctx->type.stackOffset);
05234 ctx->bc.Instr(asBC_ClrHi);
05235 ctx->bc.InstrDWORD(asBC_JZ, elseLabel);
05236 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
05237
05238
05239 MergeExprContexts(ctx, &le);
05240 ctx->bc.InstrINT(asBC_JMP, afterLabel);
05241
05242
05243 ctx->bc.Label((short)elseLabel);
05244 MergeExprContexts(ctx, &re);
05245 ctx->bc.Label((short)afterLabel);
05246
05247
05248 if( le.type.dataType != re.type.dataType )
05249 Error(TXT_BOTH_MUST_BE_SAME, expr);
05250
05251
05252 ctx->type = le.type;
05253 }
05254 else
05255 {
05256
05257 asCTypeInfo temp;
05258 temp = le.type;
05259 temp.dataType.MakeReference(false);
05260 temp.dataType.MakeReadOnly(false);
05261
05262 asCArray<int> vars;
05263 e.bc.GetVarsUsed(vars);
05264 int offset = AllocateVariableNotIn(temp.dataType, true, &vars);
05265 temp.SetVariable(temp.dataType, offset, true);
05266
05267 CallDefaultConstructor(temp.dataType, offset, &ctx->bc, expr);
05268
05269
05270 MergeExprContexts(ctx, &e);
05271
05272
05273 ctx->type = e.type;
05274 ConvertToVariable(ctx);
05275 ctx->bc.InstrSHORT(asBC_CpyVtoR4, ctx->type.stackOffset);
05276 ctx->bc.Instr(asBC_ClrHi);
05277 ctx->bc.InstrDWORD(asBC_JZ, elseLabel);
05278 ReleaseTemporaryVariable(ctx->type, &ctx->bc);
05279
05280
05281 asCTypeInfo rtemp;
05282 rtemp = temp;
05283 if( rtemp.dataType.IsObjectHandle() )
05284 rtemp.isExplicitHandle = true;
05285
05286 PrepareForAssignment(&rtemp.dataType, &le, cexpr->next);
05287 MergeExprContexts(ctx, &le);
05288
05289 if( !rtemp.dataType.IsPrimitive() )
05290 {
05291 ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
05292 rtemp.dataType.MakeReference(true);
05293 }
05294 PerformAssignment(&rtemp, &le.type, &ctx->bc, cexpr->next);
05295 if( !rtemp.dataType.IsPrimitive() )
05296 ctx->bc.Pop(le.type.dataType.GetSizeOnStackDWords());
05297
05298
05299 ReleaseTemporaryVariable(le.type, &ctx->bc);
05300
05301 ctx->bc.InstrINT(asBC_JMP, afterLabel);
05302
05303
05304 ctx->bc.Label((short)elseLabel);
05305
05306
05307 PrepareForAssignment(&rtemp.dataType, &re, cexpr->next);
05308 MergeExprContexts(ctx, &re);
05309
05310 if( !rtemp.dataType.IsPrimitive() )
05311 {
05312 ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
05313 rtemp.dataType.MakeReference(true);
05314 }
05315 PerformAssignment(&rtemp, &re.type, &ctx->bc, cexpr->next);
05316 if( !rtemp.dataType.IsPrimitive() )
05317 ctx->bc.Pop(le.type.dataType.GetSizeOnStackDWords());
05318
05319
05320 ReleaseTemporaryVariable(re.type, &ctx->bc);
05321
05322 ctx->bc.Label((short)afterLabel);
05323
05324
05325 if( le.type.dataType != re.type.dataType )
05326 Error(TXT_BOTH_MUST_BE_SAME, expr);
05327
05328
05329 ctx->type = rtemp;
05330 ctx->type.isExplicitHandle = isExplicitHandle;
05331
05332 if( !ctx->type.dataType.IsPrimitive() )
05333 {
05334 ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
05335 ctx->type.dataType.MakeReference(true);
05336 }
05337
05338
05339 ctx->type.isConstant = false;
05340 }
05341 }
05342 else
05343 {
05344 ctx->type.SetDummy();
05345 return -1;
05346 }
05347 }
05348 else
05349 return CompileExpression(cexpr, ctx);
05350
05351 return 0;
05352 }
05353
05354 int asCCompiler::CompileExpression(asCScriptNode *expr, asSExprContext *ctx)
05355 {
05356 asASSERT(expr->nodeType == snExpression);
05357
05358
05359 int count = 0;
05360 asCScriptNode *node = expr->firstChild;
05361 while( node )
05362 {
05363 count++;
05364 node = node->next;
05365 }
05366
05367
05368 asCArray<asCScriptNode *> stack(count);
05369 asCArray<asCScriptNode *> stack2(count);
05370 asCArray<asCScriptNode *> postfix(count);
05371
05372 node = expr->firstChild;
05373 while( node )
05374 {
05375 int precedence = GetPrecedence(node);
05376
05377 while( stack.GetLength() > 0 &&
05378 precedence <= GetPrecedence(stack[stack.GetLength()-1]) )
05379 stack2.PushLast(stack.PopLast());
05380
05381 stack.PushLast(node);
05382
05383 node = node->next;
05384 }
05385
05386 while( stack.GetLength() > 0 )
05387 stack2.PushLast(stack.PopLast());
05388
05389
05390
05391 SwapPostFixOperands(stack2, postfix);
05392
05393
05394 return CompilePostFixExpression(&postfix, ctx);
05395 }
05396
05397 void asCCompiler::SwapPostFixOperands(asCArray<asCScriptNode *> &postfix, asCArray<asCScriptNode *> &target)
05398 {
05399 if( postfix.GetLength() == 0 ) return;
05400
05401 asCScriptNode *node = postfix.PopLast();
05402 if( node->nodeType == snExprTerm )
05403 {
05404 target.PushLast(node);
05405 return;
05406 }
05407
05408 SwapPostFixOperands(postfix, target);
05409 SwapPostFixOperands(postfix, target);
05410
05411 target.PushLast(node);
05412 }
05413
05414 int asCCompiler::CompilePostFixExpression(asCArray<asCScriptNode *> *postfix, asSExprContext *ctx)
05415 {
05416
05417 asASSERT(ctx->bc.GetLastInstr() == -1);
05418
05419
05420 asCScriptNode *node = postfix->PopLast();
05421 ctx->exprNode = node;
05422
05423
05424 if( node->nodeType == snExprTerm )
05425 return CompileExpressionTerm(node, ctx);
05426
05427
05428 asSExprContext r(engine), l(engine);
05429
05430 int ret;
05431 ret = CompilePostFixExpression(postfix, &l); if( ret < 0 ) return ret;
05432 ret = CompilePostFixExpression(postfix, &r); if( ret < 0 ) return ret;
05433
05434
05435 return CompileOperator(node, &l, &r, ctx);
05436 }
05437
05438 int asCCompiler::CompileExpressionTerm(asCScriptNode *node, asSExprContext *ctx)
05439 {
05440
05441 asASSERT(ctx->bc.GetLastInstr() == -1);
05442
05443
05444 ctx->type.SetDummy();
05445
05446
05447 asCScriptNode *vnode = node->firstChild;
05448 while( vnode->nodeType != snExprValue )
05449 vnode = vnode->next;
05450
05451 asSExprContext v(engine);
05452 int r = CompileExpressionValue(vnode, &v); if( r < 0 ) return r;
05453
05454
05455 asCScriptNode *pnode = vnode->next;
05456 while( pnode )
05457 {
05458
05459
05460 r = CompileExpressionPostOp(pnode, &v); if( r < 0 ) return r;
05461 pnode = pnode->next;
05462 }
05463
05464
05465 pnode = vnode->prev;
05466 while( pnode )
05467 {
05468
05469
05470 r = CompileExpressionPreOp(pnode, &v); if( r < 0 ) return r;
05471 pnode = pnode->prev;
05472 }
05473
05474
05475 MergeExprContexts(ctx, &v);
05476
05477 ctx->type = v.type;
05478 ctx->property_get = v.property_get;
05479 ctx->property_set = v.property_set;
05480 ctx->property_const = v.property_const;
05481
05482 return 0;
05483 }
05484
05485 int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx)
05486 {
05487
05488 asASSERT(ctx->bc.GetLastInstr() == -1);
05489
05490 asCScriptNode *vnode = node->firstChild;
05491 if( vnode->nodeType == snVariableAccess )
05492 {
05493
05494 asCString scope = GetScopeFromNode(vnode);
05495
05496
05497 vnode = vnode->lastChild;
05498 asASSERT(vnode->nodeType == snIdentifier );
05499 asCString name(&script->code[vnode->tokenPos], vnode->tokenLength);
05500
05501 sVariable *v = 0;
05502 if( scope == "" )
05503 v = variables->GetVariable(name.AddressOf());
05504 if( v == 0 )
05505 {
05506
05507 bool found = false;
05508
05509
05510 if( outFunc && outFunc->objectType && scope == "" )
05511 {
05512 if( name == THIS_TOKEN )
05513 {
05514 asCDataType dt = asCDataType::CreateObject(outFunc->objectType, outFunc->isReadOnly);
05515
05516
05517 ctx->bc.InstrSHORT(asBC_PSF, 0);
05518 ctx->type.SetVariable(dt, 0, false);
05519 ctx->type.dataType.MakeReference(true);
05520
05521 found = true;
05522 }
05523
05524 if( !found )
05525 {
05526
05527 asSExprContext access(engine);
05528 access.type.Set(asCDataType::CreateObject(outFunc->objectType, outFunc->isReadOnly));
05529 int r = FindPropertyAccessor(name, &access, node);
05530 if( r < 0 ) return -1;
05531 if( access.property_get || access.property_set )
05532 {
05533
05534 ctx->bc.InstrSHORT(asBC_PSF, 0);
05535 ctx->type.SetVariable(asCDataType::CreateObject(outFunc->objectType, outFunc->isReadOnly), 0, false);
05536 ctx->type = access.type;
05537 ctx->property_get = access.property_get;
05538 ctx->property_set = access.property_set;
05539 ctx->property_const = access.property_const;
05540
05541 found = true;
05542 }
05543 }
05544
05545 if( !found )
05546 {
05547 asCDataType dt = asCDataType::CreateObject(outFunc->objectType, false);
05548 asCObjectProperty *prop = builder->GetObjectProperty(dt, name.AddressOf());
05549 if( prop )
05550 {
05551
05552 ctx->bc.InstrSHORT(asBC_PSF, 0);
05553 ctx->type.SetVariable(dt, 0, false);
05554 ctx->type.dataType.MakeReference(true);
05555
05556 Dereference(ctx, true);
05557
05558
05559
05560 ctx->bc.InstrINT(asBC_ADDSi, prop->byteOffset);
05561
05562 if( prop->type.IsReference() )
05563 ctx->bc.Instr(asBC_RDSPTR);
05564
05565
05566 if( prop->type.IsPrimitive() )
05567 {
05568
05569 ctx->bc.Instr(asBC_PopRPtr);
05570 }
05571
05572
05573 ctx->type.dataType = prop->type;
05574 ctx->type.dataType.MakeReference(true);
05575 ctx->type.isVariable = false;
05576
05577 if( ctx->type.dataType.IsObject() && !ctx->type.dataType.IsObjectHandle() )
05578 {
05579
05580 ctx->type.dataType.MakeReference(false);
05581 }
05582
05583
05584 ctx->type.dataType.MakeReadOnly(outFunc->isReadOnly);
05585
05586 found = true;
05587 }
05588 }
05589 }
05590
05591
05592 if( !found && (scope == "" || scope == "::") )
05593 {
05594 bool isCompiled = true;
05595 bool isPureConstant = false;
05596 asQWORD constantValue;
05597 asCGlobalProperty *prop = builder->GetGlobalProperty(name.AddressOf(), &isCompiled, &isPureConstant, &constantValue);
05598 if( prop )
05599 {
05600 found = true;
05601
05602
05603 if( isCompiled )
05604 {
05605 if( ctx->type.dataType.GetObjectType() && (ctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE) )
05606 {
05607 ctx->type.dataType.MakeHandle(true);
05608 ctx->type.isExplicitHandle = true;
05609 }
05610
05611
05612
05613
05614
05615 if( isPureConstant )
05616 ctx->type.SetConstantQW(prop->type, constantValue);
05617 else
05618 {
05619 ctx->type.Set(prop->type);
05620 ctx->type.dataType.MakeReference(true);
05621
05622
05623 if( ctx->type.dataType.IsPrimitive() )
05624 ctx->bc.InstrWORD(asBC_LDG, (asWORD)builder->module->GetGlobalVarPtrIndex(prop->id));
05625 else
05626 ctx->bc.InstrWORD(asBC_PGA, (asWORD)builder->module->GetGlobalVarPtrIndex(prop->id));
05627 }
05628 }
05629 else
05630 {
05631 asCString str;
05632 str.Format(TXT_UNINITIALIZED_GLOBAL_VAR_s, prop->name.AddressOf());
05633 Error(str.AddressOf(), vnode);
05634 return -1;
05635 }
05636 }
05637 }
05638
05639 if( !found )
05640 {
05641 asCObjectType *scopeType = 0;
05642 if( scope != "" )
05643 {
05644
05645 scopeType = builder->GetObjectType( scope.AddressOf() );
05646 }
05647
05648
05649 asDWORD value = 0;
05650 asCDataType dt;
05651 if( scopeType && builder->GetEnumValueFromObjectType(scopeType, name.AddressOf(), dt, value) )
05652 {
05653
05654 found = true;
05655 }
05656 else if( scope == "" && !engine->ep.requireEnumScope )
05657 {
05658
05659 int e = builder->GetEnumValue(name.AddressOf(), dt, value);
05660 if( e )
05661 {
05662 found = true;
05663 if( e == 2 )
05664 {
05665 Error(TXT_FOUND_MULTIPLE_ENUM_VALUES, vnode);
05666 }
05667 }
05668 }
05669
05670 if( found )
05671 {
05672
05673 ctx->type.SetConstantDW(dt, value);
05674 }
05675 }
05676
05677 if( !found )
05678 {
05679
05680 if( scope != "" && scope != "::" )
05681 scope += "::";
05682 scope += name;
05683
05684 asCString str;
05685 str.Format(TXT_s_NOT_DECLARED, scope.AddressOf());
05686 Error(str.AddressOf(), vnode);
05687
05688
05689 ctx->type.SetDummy();
05690
05691
05692 variables->DeclareVariable(name.AddressOf(), asCDataType::CreatePrimitive(ttInt, false), 0x7FFF);
05693
05694
05695 sVariable *v = variables->GetVariable(name.AddressOf());
05696 asASSERT(v);
05697 if( v ) v->isInitialized = true;
05698
05699 return -1;
05700 }
05701 }
05702 else
05703 {
05704
05705
05706 if( v->isPureConstant )
05707 ctx->type.SetConstantQW(v->type, v->constantValue);
05708 else
05709 {
05710 if( v->type.IsPrimitive() )
05711 {
05712 if( v->type.IsReference() )
05713 {
05714
05715 #if AS_PTR_SIZE == 1
05716 ctx->bc.InstrSHORT(asBC_CpyVtoR4, (short)v->stackOffset);
05717 #else
05718 ctx->bc.InstrSHORT(asBC_CpyVtoR8, (short)v->stackOffset);
05719 #endif
05720 ctx->type.Set(v->type);
05721 }
05722 else
05723 ctx->type.SetVariable(v->type, v->stackOffset, false);
05724 }
05725 else
05726 {
05727 ctx->bc.InstrSHORT(asBC_PSF, (short)v->stackOffset);
05728 ctx->type.SetVariable(v->type, v->stackOffset, false);
05729 ctx->type.dataType.MakeReference(true);
05730
05731
05732 if( v->type.IsReference() && (!v->type.IsObject() || v->type.IsObjectHandle()) )
05733 ctx->bc.Instr(asBC_RDSPTR);
05734 }
05735 }
05736 }
05737 }
05738 else if( vnode->nodeType == snConstant )
05739 {
05740 if( vnode->tokenType == ttIntConstant )
05741 {
05742 asCString value(&script->code[vnode->tokenPos], vnode->tokenLength);
05743
05744 asQWORD val = asStringScanUInt64(value.AddressOf(), 10, 0);
05745
05746
05747 if( val>>32 )
05748 ctx->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), val);
05749 else
05750 ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), asDWORD(val));
05751 }
05752 else if( vnode->tokenType == ttBitsConstant )
05753 {
05754 asCString value(&script->code[vnode->tokenPos+2], vnode->tokenLength-2);
05755
05756
05757 asQWORD val = asStringScanUInt64(value.AddressOf(), 16, 0);
05758
05759
05760 if( val>>32 )
05761 ctx->type.SetConstantQW(asCDataType::CreatePrimitive(ttUInt64, true), val);
05762 else
05763 ctx->type.SetConstantDW(asCDataType::CreatePrimitive(ttUInt, true), asDWORD(val));
05764 }
05765 else if( vnode->tokenType == ttFloatConstant )
05766 {
05767 asCString value(&script->code[vnode->tokenPos], vnode->tokenLength);
05768
05769
05770
05771 size_t numScanned;
05772 float v = float(