CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack) { if ( !IsOfType(p, ID_PUBLIC) ) return NULL; if ( !IsOfType(p, ID_CLASS) ) return NULL; CBotString name = p->GetString(); // a name for the class is there? if (IsOfType(p, TokenTypVar)) { // the class was created by Compile1 CBotClass* pOld = CBotClass::Find(name); if ( IsOfType( p, ID_EXTENDS ) ) { IsOfType(p, TokenTypVar); // necessarily } IsOfType( p, ID_OPBLK); // necessarily while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) ) { pOld->CompileDefItem(p, pStack, true); } pOld->m_IsDef = true; // complete definition if (pStack->IsOk()) return pOld; } pStack->SetError(TX_ENDOF, p); return NULL; }
void InitFileFunctions() { // create a class for file management // the use is as follows: // file canal( "NomFichier.txt" ) // canal.open( "r" ); // open for read // s = canal.readln( ); // reads a line // canal.close(); // close the file // create the class FILE CBotClass* bc = CBotClass::Create("file", nullptr); // adds the component ".filename" bc->AddItem("filename", CBotTypString); // adds the component ".handle" bc->AddItem("handle", CBotTypInt, CBotVar::ProtectionLevel::Private); // define a constructor and a destructor bc->AddFunction("file", rfconstruct, cfconstruct); bc->AddFunction("~file", rfdestruct, nullptr); // end of the methods associated bc->AddFunction("open", rfopen, cfopen); bc->AddFunction("close", rfclose, cfclose); bc->AddFunction("writeln", rfwrite, cfwrite); bc->AddFunction("readln", rfread, cfread); bc->AddFunction("eof", rfeof, cfeof ); CBotProgram::AddFunction("deletefile", rDeleteFile, cString); //m_pFuncFile = new CBotProgram( ); //std::stringArray ListFonctions; //m_pFuncFile->Compile( "public file openfile(string name, string mode) {return new file(name, mode);}", ListFonctions); //m_pFuncFile->SetIdent(-2); // restoreState in special identifier for this function }
bool CBotClass::SaveStaticState(FILE* pf) { if (!WriteWord( pf, CBOTVERSION*2)) return false; // saves the state of static variables in classes CBotClass* p = m_ExClass; while ( p != NULL ) { if (!WriteWord( pf, 1)) return false; // save the name of the class if (!WriteString( pf, p->GetName() )) return false; CBotVar* pv = p->GetVar(); while( pv != NULL ) { if ( pv->IsStatic() ) { if (!WriteWord( pf, 1)) return false; if (!WriteString( pf, pv->GetName() )) return false; if ( !pv->Save0State(pf)) return false; // common header if ( !pv->Save1State(pf) ) return false; // saves as the child class if ( !WriteWord( pf, 0)) return false; } pv = pv->GetNext(); } if (!WriteWord( pf, 0)) return false; p = p->m_ExNext; } if (!WriteWord( pf, 0)) return false; return true; }
CBotVarClass::CBotVarClass( const CBotToken* name, const CBotTypResult& type) { /* // int nIdent = 0; InitCBotVarClass( name, type ) //, nIdent ); } CBotVarClass::CBotVarClass( const CBotToken* name, CBotTypResult& type) //, int &nIdent ) { InitCBotVarClass( name, type ); //, nIdent ); } void CBotVarClass::InitCBotVarClass( const CBotToken* name, CBotTypResult& type ) //, int &nIdent ) {*/ if ( !type.Eq(CBotTypClass) && !type.Eq(CBotTypIntrinsic) && // by convenience there accepts these types !type.Eq(CBotTypPointer) && !type.Eq(CBotTypArrayPointer) && !type.Eq(CBotTypArrayBody)) ASM_TRAP(); m_token = new CBotToken(name); m_next = NULL; m_pMyThis = NULL; m_pUserPtr = OBJECTCREATED;//NULL; m_InitExpr = NULL; m_LimExpr = NULL; m_pVar = NULL; m_type = type; if ( type.Eq(CBotTypArrayPointer) ) m_type.SetType( CBotTypArrayBody ); else if ( !type.Eq(CBotTypArrayBody) ) m_type.SetType( CBotTypClass ); // officel type for this object m_pClass = NULL; m_pParent = NULL; m_binit = false; m_bStatic = false; m_mPrivate = 0; m_bConstructor = false; m_CptUse = 0; m_ItemIdent = type.Eq(CBotTypIntrinsic) ? 0 : CBotVar::NextUniqNum(); // se place tout seul dans la liste // TODO stands alone in the list (stands only in a list) if (m_ExClass) m_ExClass->m_ExPrev = this; m_ExNext = m_ExClass; m_ExPrev = NULL; m_ExClass = this; CBotClass* pClass = type.GetClass(); CBotClass* pClass2 = pClass->GetParent(); if ( pClass2 != NULL ) { // also creates an instance of the parent class m_pParent = new CBotVarClass(name, CBotTypResult(type.GetType(),pClass2) ); //, nIdent); } SetClass( pClass ); //, nIdent ); }
CBotVar* CBotVar::GetStaticVar() { // makes the pointer to the variable if it is static if ( m_bStatic == 0 || m_pMyThis == nullptr ) return this; CBotClass* pClass = m_pMyThis->GetClass(); return pClass->GetItem( m_token->GetString() ); }
CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack) { if ( !IsOfType(p, ID_PUBLIC) ) { pStack->SetError(TX_NOPUBLIC, p); return NULL; } if ( !IsOfType(p, ID_CLASS) ) return NULL; CBotString name = p->GetString(); CBotClass* pOld = CBotClass::Find(name); if ( pOld != NULL && pOld->m_IsDef ) { pStack->SetError( TX_REDEFCLASS, p ); return NULL; } // a name of the class is there? if (IsOfType(p, TokenTypVar)) { CBotClass* pPapa = NULL; if ( IsOfType( p, ID_EXTENDS ) ) { CBotString name = p->GetString(); pPapa = CBotClass::Find(name); if (!IsOfType(p, TokenTypVar) || pPapa == NULL ) { pStack->SetError( TX_NOCLASS, p ); return NULL; } } CBotClass* classe = (pOld == NULL) ? new CBotClass(name, pPapa) : pOld; classe->Purge(); // emptythe old definitions classe->m_IsDef = false; // current definition if ( !IsOfType( p, ID_OPBLK) ) { pStack->SetError(TX_OPENBLK, p); return NULL; } while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) ) { classe->CompileDefItem(p, pStack, false); } if (pStack->IsOk()) return classe; } pStack->SetError(TX_ENDOF, p); return NULL; }
CBotClass* CBotClass::Find(const char* name) { CBotClass* p = m_ExClass; while ( p != NULL ) { if ( p->GetName() == name ) return p; p = p->m_ExNext; } return NULL; }
bool CBotVar::IsElemOfClass(const std::string& name) { CBotClass* pc = nullptr; if ( m_type.Eq(CBotTypPointer) ) { pc = (static_cast<CBotVarPointer*>(this))->m_pClass; } if ( m_type.Eq(CBotTypClass) ) { pc = (static_cast<CBotVarClass*>(this))->m_pClass; } while ( pc != nullptr ) { if ( pc->GetName() == name ) return true; pc = pc->GetParent(); } return false; }
bool CBotClass::AddItem(CBotString name, CBotTypResult type, int mPrivate) { CBotToken token(name, CBotString()); CBotClass* pClass = type.GetClass(); CBotVar* pVar = CBotVar::Create( name, type ); /// pVar->SetUniqNum(CBotVar::NextUniqNum()); pVar->SetPrivate( mPrivate ); if ( pClass != NULL ) { // pVar->SetClass(pClass); if ( type.Eq(CBotTypClass) ) { // adds a new statement for the object initialization pVar->m_InitExpr = new CBotNew() ; CBotToken nom( pClass->GetName() ); pVar->m_InitExpr->SetToken(&nom); } } return AddItem( pVar ); }
CBotTypResult TypeParam(CBotToken* &p, CBotCStack* pile) { CBotClass* pClass = nullptr; switch (p->GetType()) { case ID_INT: p = p->GetNext(); return ArrayType(p, pile, CBotTypResult( CBotTypInt )); case ID_FLOAT: p = p->GetNext(); return ArrayType(p, pile, CBotTypResult( CBotTypFloat )); case ID_BOOLEAN: case ID_BOOL: p = p->GetNext(); return ArrayType(p, pile, CBotTypResult( CBotTypBoolean )); case ID_STRING: p = p->GetNext(); return ArrayType(p, pile, CBotTypResult( CBotTypString )); case ID_VOID: p = p->GetNext(); return CBotTypResult( 0 ); case TokenTypVar: pClass = CBotClass::Find(p); if ( pClass != nullptr) { p = p->GetNext(); return ArrayType(p, pile, pClass->IsIntrinsic() ? CBotTypResult( CBotTypIntrinsic, pClass ) : CBotTypResult( CBotTypPointer, pClass ) ); } } return CBotTypResult( -1 ); }
bool CBotClass::RestoreStaticState(FILE* pf) { CBotString ClassName, VarName; CBotClass* pClass; unsigned short w; if (!ReadWord( pf, w )) return false; if ( w != CBOTVERSION*2 ) return false; while (true) { if (!ReadWord( pf, w )) return false; if ( w == 0 ) return true; if (!ReadString( pf, ClassName )) return false; pClass = Find(ClassName); while (true) { if (!ReadWord( pf, w )) return false; if ( w == 0 ) break; CBotVar* pVar = NULL; CBotVar* pv = NULL; if (!ReadString( pf, VarName )) return false; if ( pClass != NULL ) pVar = pClass->GetItem(VarName); if (!CBotVar::RestoreState(pf, pv)) return false; // the temp variable if ( pVar != NULL ) pVar->Copy(pv); delete pv; } } return true; }
void CBotClassInst::RestoreState(CBotStack* &pj, bool bMain) { CBotVar* pThis = NULL; CBotStack* pile = pj; if ( bMain ) pile = pj->RestoreStack(this); if ( pile == NULL ) return; // creates the variable of type pointer to the object { CBotString name = m_var->m_token.GetString(); pThis = pile->FindVar(name); pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute a unique number } CBotToken* pt = &m_token; CBotClass* pClass = CBotClass::Find(pt); bool bIntrincic = pClass->IsIntrinsic(); if ( bMain && pile->GetState()<3) { // is there an assignment or parameters (constructor) // CBotVarClass* pInstance = NULL; if ( m_expr != NULL ) { // evaluates the expression for the assignment m_expr->RestoreState(pile, bMain); return; } else if ( m_hasParams ) { // evaluates the constructor of an instance if ( !bIntrincic && pile->GetState() == 1) { return; } CBotVar* ppVars[1000]; CBotStack* pile2 = pile; int i = 0; CBotInstr* p = m_Parameters; // evaluates the parameters // and the values an the stack // for the ability to be interrupted at any time (\TODO pour pouvoir être interrompu n'importe quand) if ( p != NULL) while ( true ) { pile2 = pile2->RestoreStack(); // place on the stack for the results if ( pile2 == NULL ) return; if ( pile2->GetState() == 0 ) { p->RestoreState(pile2, bMain); // interrupted here? return; } ppVars[i++] = pile2->GetVar(); p = p->GetNext(); if ( p == NULL) break; } ppVars[i] = NULL; // creates a variable for the result // CBotVar* pResult = NULL; // constructor still void pClass->RestoreMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pile2); return; } } if ( m_next2b != NULL ) m_next2b->RestoreState(pile, bMain); // other(s) definition(s) }
CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack) { CBotToken* pp = p; if (!IsOfType(p, ID_NEW)) return nullptr; // verifies that the token is a class name if (p->GetType() != TokenTypVar) { pStack->SetError(CBotErrBadNew, p); return nullptr; } CBotClass* pClass = CBotClass::Find(p); if (pClass == nullptr) { pStack->SetError(CBotErrBadNew, p); return nullptr; } CBotNew* inst = new CBotNew(); inst->SetToken(pp); inst->m_vartoken = *p; p = p->GetNext(); // creates the object on the stack // with a pointer to the object CBotVar* pVar = CBotVar::Create("", pClass); // do the call of the creator CBotCStack* pStk = pStack->TokenStack(); { // check if there are parameters CBotVar* ppVars[1000]; inst->m_parameters = CompileParams(p, pStk, ppVars); if (!pStk->IsOk()) goto error; // constructor exist? CBotTypResult r = pClass->CompileMethode(pClass->GetName(), pVar, ppVars, pStk, inst->m_nMethodeIdent); delete pStk->TokenStack(); // release extra stack int typ = r.GetType(); // if there is no constructor, and no parameters either, it's ok if (typ == CBotErrUndefCall && inst->m_parameters == nullptr) typ = 0; pVar->SetInit(CBotVar::InitType::DEF); // mark the instance as init if (typ>20) { pStk->SetError(static_cast<CBotError>(typ), inst->m_vartoken.GetEnd()); goto error; } // if the constructor does not exist, but there are parameters if (typ<0 && inst->m_parameters != nullptr) { pStk->SetError(CBotErrNoConstruct, &inst->m_vartoken); goto error; } // makes pointer to the object on the stack pStk->SetVar(pVar); pp = p; // chained method ? if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true))) { inst->m_exprRetVar->SetToken(pp); delete pStk->TokenStack(); } if (pStack->IsOk()) return pStack->Return(inst, pStk); } error: delete inst; return pStack->Return(nullptr, pStk); }
void CBotNew::RestoreState(CBotStack* &pj, bool bMain) { if (!bMain) return; CBotStack* pile = pj->RestoreStack(this); //primary stack if (pile == nullptr) return; if (m_exprRetVar != nullptr) // new Class().method() { if (pile->GetState() == 2) { CBotStack* pile3 = pile->RestoreStack(); m_exprRetVar->RestoreState(pile3, bMain); return; } } CBotStack* pile1 = pj->AddStack2(); //secondary stack CBotToken* pt = &m_vartoken; CBotClass* pClass = CBotClass::Find(pt); // create the variable "this" pointer type to the object if ( pile->GetState()==0) { return; } CBotVar* pThis = pile1->GetVar(); // find the pointer pThis->SetUniqNum(-2); // is ther an assignment or parameters (constructor) if ( pile->GetState()==1) { // evaluates the constructor of the instance CBotVar* ppVars[1000]; CBotStack* pile2 = pile; int i = 0; CBotInstr* p = m_parameters; // evaluate the parameters // and places the values on the stack // to be interrupted at any time if (p != nullptr) while ( true) { pile2 = pile2->RestoreStack(); // space on the stack for the result if (pile2 == nullptr) return; if (pile2->GetState() == 0) { p->RestoreState(pile2, bMain); // interrupt here! return; } ppVars[i++] = pile2->GetVar(); p = p->GetNext(); if ( p == nullptr) break; } ppVars[i] = nullptr; pClass->RestoreMethode(m_nMethodeIdent, m_vartoken.GetString(), pThis, ppVars, pile2) ; // interrupt here! } }
bool CBotNew::Execute(CBotStack* &pj) { CBotStack* pile = pj->AddStack(this); //main stack if (m_exprRetVar != nullptr) // new Class().method() { if (pile->GetState() == 2) { CBotStack* pile3 = pile->AddStack(); if (!m_exprRetVar->Execute(pile3)) return false; return pj->Return(pile3); } } if (pile->IfStep()) return false; CBotStack* pile1 = pj->AddStack2(); //secondary stack CBotVar* pThis = nullptr; CBotToken* pt = &m_vartoken; CBotClass* pClass = CBotClass::Find(pt); // create the variable "this" pointer type to the stack if ( pile->GetState()==0) { // create an instance of the requested class // and initialize the pointer to that object pThis = CBotVar::Create("this", pClass); pThis->SetUniqNum(-2) ; pile1->SetVar(pThis); // place on stack1 pile->IncState(); } // fetch the this pointer if it was interrupted if ( pThis == nullptr) { pThis = pile1->GetVar(); // find the pointer } // is there an assignment or parameters (constructor) if ( pile->GetState()==1) { // evaluates the constructor of the instance CBotVar* ppVars[1000]; CBotStack* pile2 = pile; int i = 0; CBotInstr* p = m_parameters; // evaluate the parameters // and places the values on the stack // to be interrupted at any time if (p != nullptr) while ( true) { pile2 = pile2->AddStack(); // space on the stack for the result if (pile2->GetState() == 0) { if (!p->Execute(pile2)) return false; // interrupted here? pile2->SetState(1); } ppVars[i++] = pile2->GetVar(); p = p->GetNext(); if ( p == nullptr) break; } ppVars[i] = nullptr; // create a variable for the result CBotVar* pResult = nullptr; // constructos still void if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pResult, pile2, GetToken())) return false; // interrupt pThis->ConstructorSet(); // indicates that the constructor has been called } if (m_exprRetVar != nullptr) // new Class().method() { pile->AddStack()->Delete(); // release pile2 stack CBotStack* pile3 = pile->AddStack(); // add new stack pile3->SetCopyVar(pThis); // copy the pointer (from pile1) pile1->Delete(); // release secondary stack(pile1) pile->SetState(2); return false; // go back to the top ^^^ } return pj->Return(pile1); // passes below }
BOOL CTestCBotApp::InitInstance() { ////////////////////////////////////////////// // défini les mots clefs supplémentaires // ------------------------------------------- CBotProgram::Init(); ////////////////////////////////////////////// // défini les fonctions "show()" et "print()" // ------------------------------------------- CBotProgram::AddFunction("show", rShow, cShow); CBotProgram::AddFunction("print", rPrint, cPrint); CBotProgram::AddFunction("println", rPrintLn, cPrint); /////////////////////////////////// // définie la classe globale CPoint // -------------------------------- m_pClassPoint = new CBotClass("CPoint", NULL); // ajoute le composant ".x" m_pClassPoint->AddItem("x", CBotTypFloat); // ajoute le composant ".y" m_pClassPoint->AddItem("y", CBotTypFloat); // ajoute le constructeur pour cette classe m_pClassPoint->AddFunction("CPoint", rCPoint, cCPoint); m_pClassPointIntr = new CBotClass("point", NULL, TRUE); // ajoute le composant ".x" m_pClassPointIntr->AddItem("x", CBotTypFloat); // ajoute le composant ".y" m_pClassPointIntr->AddItem("y", CBotTypFloat); // ajoute le composant ".z" m_pClassPointIntr->AddItem("z", CBotTypFloat); // ajoute le constructeur pour cette classe m_pClassPointIntr->AddFunction("point", rCPoint, cCPoint); // défini la classe "object" CBotClass* pClassObject = new CBotClass( "object", NULL ) ; pClassObject->AddItem( "xx", CBotTypFloat ); pClassObject->AddItem( "position", CBotTypResult( CBotTypIntrinsic, "point" ) ); pClassObject->AddItem( "transport", CBotTypResult( CBotTypPointer, "object" ) ); pClassObject->AddUpdateFunc( rMajObject ); InitClassFILE(); AfxEnableControlContainer(); // Standard initialization #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif // Change the registry key under which our settings are stored. SetRegistryKey(_T("Local AppWizard-Generated Applications")); LoadStdProfileSettings(); // Load standard INI file options (including MRU) // Register document templates CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_TESTCBTYPE, RUNTIME_CLASS(CTestCBotDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame RUNTIME_CLASS(CTestCBotView)); AddDocTemplate(pDocTemplate); // create main MDI Frame window CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; // Parse command line for standard shell commands, DDE, file open CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); if (m_lpCmdLine[0] == 0) { CString Filename = GetProfileString(szSection, szFilename); if (Filename.IsEmpty()) Filename = "TstCbot.txt"; else OpenDocumentFile(Filename); } else // Dispatch commands specified on the command line if (!ProcessShellCommand(cmdInfo)) return FALSE; pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); return TRUE; }
bool CBotClassInst::Execute(CBotStack* &pj) { CBotVar* pThis = NULL; CBotStack* pile = pj->AddStack(this);//essential for SetState() // if ( pile == EOX ) return true; CBotToken* pt = &m_token; CBotClass* pClass = CBotClass::Find(pt); bool bIntrincic = pClass->IsIntrinsic(); // creates the variable of type pointer to the object if ( pile->GetState()==0) { CBotString name = m_var->m_token.GetString(); if ( bIntrincic ) { pThis = CBotVar::Create(name, CBotTypResult( CBotTypIntrinsic, pClass )); } else { pThis = CBotVar::Create(name, CBotTypResult( CBotTypPointer, pClass )); } pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute as unique number pile->AddVar(pThis); // place on the stack pile->IncState(); } if ( pThis == NULL ) pThis = pile->FindVar((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); if ( pile->GetState()<3) { // ss there an assignment or parameters (contructor) // CBotVarClass* pInstance = NULL; if ( m_expr != NULL ) { // evaluates the expression for the assignment if (!m_expr->Execute(pile)) return false; if ( bIntrincic ) { CBotVar* pv = pile->GetVar(); if ( pv == NULL || pv->GetPointer() == NULL ) { pile->SetError(TX_NULLPT, &m_token); return pj->Return(pile); } pThis->Copy(pile->GetVar(), false); } else { CBotVarClass* pInstance; pInstance = (static_cast<CBotVarPointer*>(pile->GetVar()))->GetPointer(); // value for the assignment pThis->SetPointer(pInstance); } pThis->SetInit(true); } else if ( m_hasParams ) { // evaluates the constructor of an instance if ( !bIntrincic && pile->GetState() == 1) { CBotToken* pt = &m_token; CBotClass* pClass = CBotClass::Find(pt); // creates an instance of the requested class CBotVarClass* pInstance; pInstance = static_cast<CBotVarClass*>(CBotVar::Create("", pClass)); pThis->SetPointer(pInstance); delete pInstance; pile->IncState(); } CBotVar* ppVars[1000]; CBotStack* pile2 = pile; int i = 0; CBotInstr* p = m_Parameters; // evaluates the parameters // and places the values on the stack // to (can) be interrupted (broken) at any time if ( p != NULL) while ( true ) { pile2 = pile2->AddStack(); // place on the stack for the results if ( pile2->GetState() == 0 ) { if (!p->Execute(pile2)) return false; // interrupted here? pile2->SetState(1); } ppVars[i++] = pile2->GetVar(); p = p->GetNext(); if ( p == NULL) break; } ppVars[i] = NULL; // creates a variable for the result CBotVar* pResult = NULL; // constructor still void if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pResult, pile2, GetToken())) return false; // interrupt pThis->SetInit(true); pThis->ConstructorSet(); // indicates that the constructor has been called pile->Return(pile2); // releases a piece of stack // pInstance = pThis->GetPointer(); } // if ( !bIntrincic ) pThis->SetPointer(pInstance); // a pointer to the instance pile->SetState(3); // finished this part } if ( pile->IfStep() ) return false; if ( m_next2b != NULL && !m_next2b->Execute(pile)) return false; // other (s) definition (s) return pj->Return( pile ); // transmits below (further) }