Exemplo n.º 1
0
CBotInstr* CBotFor::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotFor*    inst = new CBotFor();           // creates the object
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    if ( IsOfType( p, TokenTypVar ) &&
         IsOfType( p, ID_DOTS ) )
    {
        inst->m_label = pp->GetString();        // register the name of label
    }

    inst->SetToken(p);
    if (!IsOfType(p, ID_FOR)) return nullptr;      // should never happen

    if ( !IsOfType(p, ID_OPENPAR))              // missing parenthesis ?
    {
        pStack->SetError(TX_OPENPAR, p->GetStart());
        return nullptr;
    }

    CBotCStack* pStk = pStack->TokenStack(pp, true);    // un petit bout de pile svp

    // compiles instructions for initialization
    inst->m_Init = CBotListExpression::Compile( p, pStk );
    if ( pStk->IsOk() )
    {
        if ( !IsOfType(p, ID_SEP))                      // lack the semicolon?
        {
            pStack->SetError(TX_OPENPAR, p->GetStart());
            delete inst;
            return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
        }
        inst->m_Test = CBotBoolExpr::Compile( p, pStk );
        if ( pStk->IsOk() )
        {
            if ( !IsOfType(p, ID_SEP))                      // lack the semicolon?
            {
                pStack->SetError(TX_OPENPAR, p->GetStart());
                delete inst;
                return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
            }
            inst->m_Incr = CBotListExpression::Compile( p, pStk );
            if ( pStk->IsOk() )
            {
                if ( IsOfType(p, ID_CLOSEPAR))              // missing parenthesis ?
                {
                    IncLvl(inst->m_label);
                    inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
                    DecLvl();
                    if ( pStk->IsOk() )
                        return pStack->Return(inst, pStk);;
                }
                pStack->SetError(TX_CLOSEPAR, p->GetStart());
            }
        }
    }

    delete inst;                                // error, frees up
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
Exemplo n.º 2
0
CBotInstr* CBotListInstr::Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal)
{
    CBotCStack* pStk = pStack->TokenStack(p, bLocal);        // variables are local

    CBotListInstr* inst = new CBotListInstr();

    while (true)
    {
        if (p == nullptr) break;

        if (IsOfType(p, ID_SEP)) continue;              // empty statement ignored
        if (p->GetType() == ID_CLBLK) break;

        if (p->GetType() == TokenTypNone)
        {
            pStack->SetError(CBotErrCloseBlock, p->GetStart());
            delete inst;
            return pStack->Return(nullptr, pStk);
        }

        CBotInstr* i = CBotBlock::CompileBlkOrInst(p, pStk);    // compiles next

        if (!pStk->IsOk())
        {
            delete inst;
            return pStack->Return(nullptr, pStk);
        }

        if (inst->m_instr == nullptr) inst->m_instr = i;
        else inst->m_instr->AddNext(i);                            // added a result
    }
    return pStack->Return(inst, pStk);
}
Exemplo n.º 3
0
CBotInstr* CBotTry::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotTry*    inst = new CBotTry();           // creates the object
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    inst->SetToken(p);
    if (!IsOfType(p, ID_TRY)) return nullptr;      // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp

    inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk );
    CBotCatch** pn = &inst->m_ListCatch;

    while (pStk->IsOk() && p->GetType() == ID_CATCH)
    {
        CBotCatch*  i = CBotCatch::Compile(p, pStk);
        *pn = i;
        pn = &i->m_next;
    }

    if (pStk->IsOk() && IsOfType( p, ID_FINALLY) )
    {
        inst->m_FinalInst = CBotBlock::CompileBlkOrInst( p, pStk );
    }

    if (pStk->IsOk())
    {
        return pStack->Return(inst, pStk);  // return an object to the application
    }

    delete inst;                                // error, frees up
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
Exemplo n.º 4
0
CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
{
    bool        first = true;
    CBotInstr*    ret = nullptr;   // to return to the list

    CBotCStack*    pile = pStack;
    int            i = 0;

    if (IsOfType(p, ID_OPENPAR))
    {
        int    start, end;
        if (!IsOfType(p, ID_CLOSEPAR)) while (true)
        {
            start = p->GetStart();
            pile = pile->TokenStack();  // keeps the result on the stack

            if (first) pStack->SetStartError(start);
            first = false;

            CBotInstr*    param = CBotExpression::Compile(p, pile);
            end      = p->GetStart();

            if (!pile->IsOk())
            {
                return pStack->Return(nullptr, pile);
            }

            if (ret == nullptr) ret = param;
            else ret->AddNext(param);   // construct the list

            if (param != nullptr)
            {
                if (pile->GetTypResult().Eq(99))
                {
                    delete pStack->TokenStack();
                    pStack->SetError(CBotErrVoid, p->GetStart());
                    return nullptr;
                }
                ppVars[i] = pile->GetVar();
                ppVars[i]->GetToken()->SetPos(start, end);
                i++;

                if (IsOfType(p, ID_COMMA)) continue;    // skips the comma
                if (IsOfType(p, ID_CLOSEPAR)) break;
            }

            pStack->SetError(CBotErrClosePar, p->GetStart());
            delete pStack->TokenStack();
            return nullptr;
        }
    }
    ppVars[i] = nullptr;
    return    ret;
}
Exemplo n.º 5
0
// used only at compile
CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, bool bBlock)
{
    if (m_next != NULL) return m_next;            // include on an existing stack

    CBotCStack*    p = new CBotCStack(this);
    m_next = p;                                    // channel element
    p->m_bBlock = bBlock;

    if (pToken != NULL) p->SetStartError(pToken->GetStart());

    return    p;
}
Exemplo n.º 6
0
CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack)
{
	CBotToken*	pp = p;							// conserve le ^au token (début instruction)

	if (!IsOfType(p, ID_IF)) return NULL;		// ne doit jamais arriver

	CBotCStack* pStk = pStack->TokenStack(pp);	// un petit bout de pile svp

	CBotIf*	inst = new CBotIf();				// crée l'object
	inst->SetToken( pp );

	if ( NULL != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
	{
		// la condition existe bel et bien

		inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
		if ( pStk->IsOk() )
		{
			// le bloc d'instruction est ok (peut être vide)

			// regarde si l'instruction suivante est le token "else"
			if (IsOfType(p, ID_ELSE))
			{
				// si oui, compile le bloc d'instruction qui suit
				inst->m_BlockElse = CBotBlock::CompileBlkOrInst( p, pStk, TRUE );
				if (!pStk->IsOk())
				{
					// il n'y a pas de bloc correct après le else
					// libère l'objet, et transmet l'erreur qui est sur la pile
					delete inst;
					return pStack->Return(NULL, pStk);
				}
			}

			// rend l'object correct à qui le demande.
			return pStack->Return(inst, pStk);
		}
	}

	// erreur, libère l'objet
	delete inst;
	// et transmet l'erreur qui se trouve sur la pile.
	return pStack->Return(NULL, pStk);
}
Exemplo n.º 7
0
CBotInstr* CBotIf::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotToken*  pp = p;                         // preserves at the ^ token (starting instruction)

    if (!IsOfType(p, ID_IF)) return nullptr;       // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp

    CBotIf* inst = new CBotIf();                // create the object
    inst->SetToken( pp );

    if ( nullptr != (inst->m_condition = CBotCondition::Compile(p, pStk )) )
    {
        // the condition does exist

        inst->m_block = CBotBlock::CompileBlkOrInst(p, pStk, true );
        if ( pStk->IsOk() )
        {
            // the statement block is ok (can be empty)

            // see if the next instruction is the token "else"
            if (IsOfType(p, ID_ELSE))
            {
                // if so, compiles the following statement block
                inst->m_blockElse = CBotBlock::CompileBlkOrInst(p, pStk, true );
                if (!pStk->IsOk())
                {
                    // there is no correct block after the else
                    // frees the object, and transmits the error that is on the stack
                    delete inst;
                    return pStack->Return(nullptr, pStk);
                }
            }

            // return the corrent object to the application
            return pStack->Return(inst, pStk);
        }
    }

    // error, frees the object
    delete inst;
    // and transmits the error that is on the stack.
    return pStack->Return(nullptr, pStk);
}
Exemplo n.º 8
0
CBotInstr* CBotDo::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotDo* inst = new CBotDo();                // creates the object

    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    if ( IsOfType( p, TokenTypVar ) &&
         IsOfType( p, ID_DOTS ) )
    {
        inst->m_label = pp->GetString();        // register the name of label
    }

    inst->SetToken(p);
    if (!IsOfType(p, ID_DO)) return nullptr;       // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp


    // looking for a statement block after the do
    IncLvl(inst->m_label);
    inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
    DecLvl();

    if ( pStk->IsOk() )
    {
        if (IsOfType(p, ID_WHILE))
        {
            if ( nullptr != (inst->m_Condition = CBotCondition::Compile( p, pStk )) )
            {
                // the condition exists
                if (IsOfType(p, ID_SEP))
                {
                    return pStack->Return(inst, pStk);  // return an object to the application
                }
                pStk->SetError(TX_ENDOF, p->GetStart());
            }
        }
        pStk->SetError(TX_WHILE, p->GetStart());
    }

    delete inst;                                // error, frees up
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
Exemplo n.º 9
0
CBotInstr* CBotCompExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotCStack* pStk = pStack->AddStack();

    CBotInstr*  left = CBotAddExpr::Compile( p, pStk );     // expression A + B left
    if (left == NULL) return pStack->Return(NULL, pStk);    // error

    if ( p->GetType() == ID_HI ||
         p->GetType() == ID_LO ||
         p->GetType() == ID_HS ||
         p->GetType() == ID_LS ||
         p->GetType() == ID_EQ ||
         p->GetType() == ID_NE)                             // the various comparisons
    {
        CBotCompExpr* inst = new CBotCompExpr();            // element for operation
        inst->SetToken(p);                                  // stores the operation

        int          type1, type2;
        type1 = pStack->GetType();

        p = p->Next();
        if ( NULL != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) )  // expression A + B right
        {
            type2 = pStack->GetType();
            // are the results compatible
            if ( type1 == type2 )
            {
                inst->m_leftop = left;
                pStk->SetVar(new CBotVar(NULL, CBotTypBoolean));
                                                            // the result is a boolean
                return pStack->Return(inst, pStk);
            }
        }

        delete left;
        delete inst;
        return pStack->Return(NULL, pStk);
    }

    return pStack->Return(left, pStk);
}
Exemplo n.º 10
0
CBotInstr* CBotExprLitNum::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotCStack* pStk = pStack->TokenStack();

    CBotExprLitNum* inst = new CBotExprLitNum();

    inst->SetToken(p);
    std::string    s = p->GetString();

    inst->m_numtype = CBotTypInt;
    if (p->GetType() == TokenTypDef)
    {
        inst->m_valint = p->GetKeywordId();
    }
    else
    {
        if (s.find('.') != std::string::npos || ( s.find('x') == std::string::npos && ( s.find_first_of("eE") != std::string::npos ) ))
        {
            inst->m_numtype = CBotTypFloat;
            inst->m_valfloat = GetNumFloat(s);
        }
        else
        {
            inst->m_valint = GetNumInt(s);
        }
    }

    if (pStk->NextToken(p))
    {
        CBotVar*    var = CBotVar::Create("", inst->m_numtype);
        pStk->SetVar(var);

        return pStack->Return(inst, pStk);
    }
    delete inst;
    return pStack->Return(nullptr, pStk);
}
Exemplo n.º 11
0
CBotInstr* CBotWhile::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotWhile*  inst = new CBotWhile();         // creates the object
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    if ( IsOfType( p, TokenTypVar ) &&
         IsOfType( p, ID_DOTS ) )
    {
        inst->m_label = pp->GetString();        // records the name of the label
    }

    inst->SetToken(p);
    if (!IsOfType(p, ID_WHILE)) return nullptr;    // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp
                                                // a bit of battery please (??)

    if ( nullptr != (inst->m_condition = CBotCondition::Compile(p, pStk )) )
    {
        // the condition exists

        IncLvl(inst->m_label);
        inst->m_block = CBotBlock::CompileBlkOrInst(p, pStk, true );
        DecLvl();

        if ( pStk->IsOk() )
        {
            // the statement block is ok (it may be empty!

            return pStack->Return(inst, pStk);  // return an object to the application
                                                // makes the object to which the application
        }
    }

    delete inst;                                // error, frees the place
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
Exemplo n.º 12
0
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);
}
Exemplo n.º 13
0
// pre-compile a new function
CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClass*  pClass)
{
    CBotFunction* func = new CBotFunction();
    func->m_nFuncIdent = CBotVar::NextUniqNum();
    
    CBotCStack* pStk = pStack->TokenStack(p, true);

    while (true)
    {
        if ( IsOfType(p, ID_PUBLIC) )
        {
        //  func->m_bPublic = true;     // will be done in two passes
            continue;
        }
        if ( IsOfType(p, ID_EXTERN) )
        {
            func->m_bExtern = true;
            continue;
        }
        break;
    }

    func->m_retToken = *p;
    func->m_retTyp = TypeParam(p, pStack);      // type of the result

    if (func->m_retTyp.GetType() >= 0)
    {
        CBotToken*  pp = p;
        func->m_token = *p;
        // un nom de fonction est-il là ?
        if (IsOfType(p, TokenTypVar))
        {
            if ( IsOfType( p, ID_DBLDOTS ) )        // method for a class
            {
                func->m_MasterClass = pp->GetString();
                CBotClass* pClass = CBotClass::Find(pp);
                if ( pClass == NULL )
                {
                    pStk->SetError(TX_NOCLASS, pp);
                    goto bad;
                }

                pp = p;
                func->m_token = *p;
                if (!IsOfType(p, TokenTypVar)) goto bad;

            }
            func->m_Param = CBotDefParam::Compile( p, pStk );
            if (pStk->IsOk())
            {
                // looks if the function exists elsewhere 
                if (( pClass != NULL || !pStack->CheckCall(pp, func->m_Param)) &&
                    ( pClass == NULL || !pClass->CheckCall(pp, func->m_Param)) )
                {
                    if (IsOfType(p, ID_OPBLK))
                    {
                        int level = 1;
                        // and skips the following instruction block
                        do
                        {
                            int type = p->GetType();
                            p = p->GetNext();
                            if (type == ID_OPBLK) level++;
                            if (type == ID_CLBLK) level--;
                        }
                        while (level > 0 && p != NULL);
                    
                        return pStack->ReturnFunc(func, pStk);
                    }
                    pStk->SetError(TX_OPENBLK, p);
                }
            }
            pStk->SetError(TX_REDEF, pp);
        }
bad:
        pStk->SetError(TX_NOFONC, p);
    }
    pStk->SetError(TX_NOTYP, p);
    delete func;
    return pStack->ReturnFunc(NULL, pStk);
}
Exemplo n.º 14
0
CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type)
{
    CBotCStack* pStk = pStack->TokenStack(p);

    CBotToken* pp = p;

    if (IsOfType( p, ID_NULL ) || (IsOfType(p, ID_OPBLK) && IsOfType(p, ID_CLBLK)))
    {
        CBotInstr* inst = new CBotExprLitNull();
        inst->SetToken(pp);
        return pStack->Return(inst, pStk);            // ok with empty element
    }
    p = pp;

    CBotListArray*    inst = new CBotListArray();

    if (IsOfType( p, ID_OPBLK ))
    {
        // each element takes the one after the other
        if (type.Eq( CBotTypArrayPointer ))
        {
            pStk->SetStartError(p->GetStart());
            if (nullptr == ( inst->m_expr = CBotListArray::Compile( p, pStk, type.GetTypElem() ) ))
            {
                if (pStk->IsOk())
                {
                    inst->m_expr = CBotTwoOpExpr::Compile(p, pStk);
                    if (inst->m_expr == nullptr || !pStk->GetTypResult().Compare(type))  // compatible type ?
                    {
                        pStk->SetError(CBotErrBadType1, p->GetStart());
                        goto error;
                    }
                }
            }

            while (IsOfType( p, ID_COMMA ))                                     // other elements?
            {
                pStk->SetStartError(p->GetStart());

                CBotInstr* i = nullptr;
                if (nullptr == ( i = CBotListArray::Compile(p, pStk, type.GetTypElem() ) ))
                {
                    if (pStk->IsOk())
                    {
                        i = CBotTwoOpExpr::Compile(p, pStk);
                        if (i == nullptr || !pStk->GetTypResult().Compare(type))  // compatible type ?
                        {
                            pStk->SetError(CBotErrBadType1, p->GetStart());
                            goto error;
                        }
                    }
                }

                inst->m_expr->AddNext3b(i);

                if ( p->GetType() == ID_COMMA ) continue;
                if ( p->GetType() == ID_CLBLK ) break;

                pStk->SetError(CBotErrClosePar, p);
                goto error;
            }
        }
        else
        {
            pStk->SetStartError(p->GetStart());
            if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
            {
                goto error;
            }

            CBotTypResult valType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);

            if (!TypeCompatible(valType, type, ID_ASS) )
            {
                pStk->SetError(CBotErrBadType1, p->GetStart());
                goto error;
            }

            while (IsOfType( p, ID_COMMA ))                                      // other elements?
            {
                pStk->SetStartError(p->GetStart());

                CBotInstr* i = CBotTwoOpExpr::Compile(p, pStk) ;
                if (nullptr == i)
                {
                    goto error;
                }

                CBotTypResult valType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);

                if (!TypeCompatible(valType, type, ID_ASS) )
                {
                    pStk->SetError(CBotErrBadType1, p->GetStart());
                    goto error;
                }
                inst->m_expr->AddNext3b(i);

                if (p->GetType() == ID_COMMA) continue;
                if (p->GetType() == ID_CLBLK) break;

                pStk->SetError(CBotErrClosePar, p);
                goto error;
            }
        }

        if (!IsOfType(p, ID_CLBLK) )
        {
            pStk->SetError(CBotErrClosePar, p->GetStart());
            goto error;
        }

        return pStack->Return(inst, pStk);
    }

error:
    delete inst;
    return pStack->Return(nullptr, pStk);
}
Exemplo n.º 15
0
CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations)
{
    int typeMask;

    if ( pOperations == nullptr ) pOperations = ListOp;
    int* pOp = pOperations;
    while ( *pOp++ != 0 );              // follows the table

    CBotCStack* pStk = pStack->TokenStack();                    // one end of stack please

    // search the intructions that may be suitable to the left of the operation
    CBotInstr*  left = (*pOp == 0) ?
                        CBotParExpr::Compile( p, pStk ) :       // expression (...) left
                        CBotTwoOpExpr::Compile( p, pStk, pOp ); // expression A * B left

    if (left == nullptr) return pStack->Return(nullptr, pStk);        // if error,  transmit

    // did we expected the operand?
    int typeOp = p->GetType();
    if ( IsInList(typeOp, pOperations, typeMask) )
    {
        CBotTypResult    type1, type2;
        type1 = pStk->GetTypResult();                           // what kind of the first operand?

        if (typeOp == ID_LOGIC)       // special case provided for: ? op1: op2;
        {
            if ( !type1.Eq(CBotTypBoolean) )
            {
                pStk->SetError( CBotErrBadType1, p);
                return pStack->Return(nullptr, pStk);
            }
            CBotLogicExpr* inst = new CBotLogicExpr();
            inst->m_condition = left;

            p = p->GetNext();                                       // skip the token of the operation
            inst->m_op1 = CBotExpression::Compile(p, pStk);
            CBotToken* pp = p;
            if ( inst->m_op1 == nullptr || !IsOfType( p, ID_DOTS ) )
            {
                pStk->SetError( CBotErrNoDoubleDots, p->GetStart());
                delete inst;
                return pStack->Return(nullptr, pStk);
            }
            type1 = pStk->GetTypResult();

            inst->m_op2 = CBotExpression::Compile(p, pStk);
            if ( inst->m_op2 == nullptr )
            {
                pStk->SetError( CBotErrNoTerminator, p->GetStart() );
                delete inst;
                return pStack->Return(nullptr, pStk);
            }
            type2 = pStk->GetTypResult();
            if (!TypeCompatible(type1, type2))
            {
                pStk->SetError( CBotErrBadType2, pp );
                delete inst;
                return pStack->Return(nullptr, pStk);
            }

            pStk->SetType(type1);       // the greatest of 2 types

            return pStack->Return(inst, pStk);
        }

        CBotTwoOpExpr* inst = new CBotTwoOpExpr();              // element for operation
        inst->SetToken(p);                                      // stores the operation


        p = p->GetNext();                                           // skip the token of the operation

        // looking statements that may be suitable for right

        if ( nullptr != (inst->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp )) )
                                                                // expression (...) right
        {
            // there is an second operand acceptable

            type2 = pStk->GetTypResult();                       // what kind of results?

            if ( type1.Eq(99) || type2.Eq(99) )                 // operand is void
            {
                pStack->SetError(CBotErrBadType2, &inst->m_token);
                delete inst;
                return nullptr;
            }

            // what kind of result?
            int TypeRes = std::max( type1.GetType(CBotTypResult::GetTypeMode::NULL_AS_POINTER), type2.GetType(CBotTypResult::GetTypeMode::NULL_AS_POINTER) );
            if (typeOp == ID_ADD && type1.Eq(CBotTypString))
            {
                TypeRes = CBotTypString;
                type2 = type1;  // any type convertible chain
            }
            else if (typeOp == ID_ADD && type2.Eq(CBotTypString))
            {
                TypeRes = CBotTypString;
                type1 = type2;  // any type convertible chain
            }
            else if (!TypeOk(TypeRes, typeMask)) type1.SetType(99);// error of type

            switch (typeOp)
            {
            case ID_LOG_OR:
            case ID_LOG_AND:
            case ID_TXT_OR:
            case ID_TXT_AND:
            case ID_EQ:
            case ID_NE:
            case ID_HI:
            case ID_LO:
            case ID_HS:
            case ID_LS:
                TypeRes = CBotTypBoolean;
            }
            if ( TypeCompatible (type1, type2, typeOp) )               // the results are compatible
            {
                // ok so, saves the operand in the object
                inst->m_leftop = left;

                // special for evaluation of the operations of the same level from left to right
                while ( IsInList(p->GetType(), pOperations, typeMask) ) // same operation(s) follows?
                {
                    typeOp = p->GetType();
                    CBotTwoOpExpr* i = new CBotTwoOpExpr();             // element for operation
                    i->SetToken(p);                                     // stores the operation
                    i->m_leftop = inst;                                 // left operand
                    type1 = TypeRes;

                    p = p->GetNext();                                       // advance after
                    i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp );
                    type2 = pStk->GetTypResult();

                    if ( !TypeCompatible (type1, type2, typeOp) )       // the results are compatible
                    {
                        pStk->SetError(CBotErrBadType2, &i->m_token);
                        delete i;
                        return pStack->Return(nullptr, pStk);
                    }

                    if ( TypeRes != CBotTypString )                     // keep string conversion
                        TypeRes = std::max(type1.GetType(), type2.GetType());
                    inst = i;
                }

                CBotTypResult t(type1);
                    t.SetType(TypeRes);
                // is a variable on the stack for the type of result
                pStk->SetVar(CBotVar::Create("", t));

                // and returns the requested object
                return pStack->Return(inst, pStk);
            }
            pStk->SetError(CBotErrBadType2, &inst->m_token);
        }

        // in case of error, releases the elements
        delete left;
        delete inst;
        // and transmits the error to the stack
        return pStack->Return(nullptr, pStk);
    }

    // if we are not dealing with an operation + or -
    // goes to that requested, the operand (left) found
    // instead of the object "addition"
    return pStack->Return(left, pStk);
}
Exemplo n.º 16
0
CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotCStack* pStk = pStack->TokenStack();

    pStk->SetStartError(p->GetStart());

    // is it an expression in parentheses?
    if (IsOfType(p, ID_OPENPAR))
    {
        CBotInstr* inst = CBotExpression::Compile(p, pStk);

        if (nullptr != inst)
        {
            if (IsOfType(p, ID_CLOSEPAR))
            {
                return pStack->Return(inst, pStk);
            }
            pStk->SetError(CBotErrClosePar, p->GetStart());
        }
        delete inst;
        return pStack->Return(nullptr, pStk);
    }

    // is this a unary operation?
    CBotInstr* inst = CBotExprUnaire::Compile(p, pStk);
    if (inst != nullptr || !pStk->IsOk())
        return pStack->Return(inst, pStk);

    // is it a variable name?
    if (p->GetType() == TokenTypVar)
    {
        // this may be a method call without the "this." before
        inst =  CBotExprVar::CompileMethode(p, pStk);
        if (inst != nullptr) return pStack->Return(inst, pStk);


        // is it a procedure call?
        inst =  CBotInstrCall::Compile(p, pStk);
        if (inst != nullptr || !pStk->IsOk())
            return pStack->Return(inst, pStk);


        CBotToken* pvar = p;
        // no, it an "ordinaty" variable
        inst =  CBotExprVar::Compile(p, pStk);

        CBotToken* pp = p;
        // post incremented or decremented?
        if (IsOfType(p, ID_INC, ID_DEC))
        {
            if (pStk->GetType() >= CBotTypBoolean)
            {
                pStk->SetError(CBotErrBadType1, pp);
                delete inst;
                return pStack->Return(nullptr, pStk);
            }

            // recompile the variable for read-only
            delete inst;
            p = pvar;
            inst =  CBotExprVar::Compile(p, pStk, CBotVar::ProtectionLevel::ReadOnly);
            p = p->GetNext();

            CBotPostIncExpr* i = new CBotPostIncExpr();
            i->SetToken(pp);
            i->m_instr = inst;    // associated statement
            return pStack->Return(i, pStk);
        }
        return pStack->Return(inst, pStk);
    }

    // pre increpemted or pre decremented?
    CBotToken* pp = p;
    if (IsOfType(p, ID_INC, ID_DEC))
    {
        CBotPreIncExpr* i = new CBotPreIncExpr();
        i->SetToken(pp);

        if (p->GetType() == TokenTypVar)
        {
            if (nullptr != (i->m_instr =  CBotExprVar::Compile(p, pStk, CBotVar::ProtectionLevel::ReadOnly)))
            {
                if (pStk->GetType() >= CBotTypBoolean)
                {
                    pStk->SetError(CBotErrBadType1, pp);
                    delete inst;
                    return pStack->Return(nullptr, pStk);
                }
                return pStack->Return(i, pStk);
            }
            delete i;
            return pStack->Return(nullptr, pStk);
        }
    }

    // is it a number or DefineNum?
    if (p->GetType() == TokenTypNum ||
        p->GetType() == TokenTypDef )
    {
        CBotInstr* inst = CBotExprLitNum::Compile(p, pStk);
        return pStack->Return(inst, pStk);
    }

    // is this a chaine?
    if (p->GetType() == TokenTypString)
    {
        CBotInstr* inst = CBotExprLitString::Compile(p, pStk);
        return pStack->Return(inst, pStk);
    }

    // is a "true" or "false"
    if (p->GetType() == ID_TRUE ||
        p->GetType() == ID_FALSE )
    {
        CBotInstr* inst = CBotExprLitBool::Compile(p, pStk);
        return pStack->Return(inst, pStk);
    }

    // is an object to be created with new
    if (p->GetType() == ID_NEW)
    {
        CBotInstr* inst = CBotNew::Compile(p, pStk);
        return pStack->Return(inst, pStk);
    }

    // is a null pointer
    if (IsOfType(p, ID_NULL))
    {
        CBotInstr* inst = new CBotExprLitNull();
        inst->SetToken(pp);
        CBotVar* var = CBotVar::Create("", CBotTypNullPointer);
        pStk->SetVar(var);
        return pStack->Return(inst, pStk);
    }

    // is a number nan
    if (IsOfType(p, ID_NAN))
    {
        CBotInstr* inst = new CBotExprLitNan();
        inst->SetToken(pp);
        CBotVar* var = CBotVar::Create("", CBotTypInt);
        var->SetInit(CBotVar::InitType::IS_NAN);
        pStk->SetVar(var);
        return pStack->Return(inst, pStk);
    }


    return pStack->Return(nullptr, pStk);
}
Exemplo n.º 17
0
CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotCStack* pStk = pStack->TokenStack();

    pStk->SetStartError(p->GetStart());

    // is it a variable name?
    if (p->GetType() == TokenTypVar)
    {
        CBotLeftExpr* inst = new CBotLeftExpr();    // creates the object

        inst->SetToken(p);

        CBotVar*     var;

        if (nullptr != (var = pStk->FindVar(p)))   // seek if known variable
        {
            inst->m_nIdent = var->GetUniqNum();
            if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
            {
                if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, CBotVar::ProtectionLevel::ReadOnly))
                {
                    pStk->SetError(CBotErrPrivate, p);
                    goto err;
                }
                // this is an element of the current class
                // adds the equivalent of this. before
                CBotToken pthis("this");
                inst->SetToken(&pthis);
                inst->m_nIdent = -2;    // indent for this

                CBotFieldExpr* i = new CBotFieldExpr();     // new element
                i->SetToken(p);     // keeps the name of the token
                inst->AddNext3(i);  // add after

                var = pStk->FindVar(pthis);
                var = var->GetItem(p->GetString());
                i->SetUniqNum(var->GetUniqNum());
            }
            p = p->GetNext();   // next token

            while (true)
            {
                if (var->GetType() == CBotTypArrayPointer)
                {
                    if (IsOfType( p, ID_OPBRK ))
                    {
                        CBotIndexExpr* i = new CBotIndexExpr();
                        i->m_expr = CBotExpression::Compile(p, pStk);
                        inst->AddNext3(i);  // add to the chain

                        var = (static_cast<CBotVarArray*>(var))->GetItem(0,true);    // gets the component [0]

                        if (i->m_expr == nullptr)
                        {
                            pStk->SetError(CBotErrBadIndex, p->GetStart());
                            goto err;
                        }

                        if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK ))
                        {
                            pStk->SetError(CBotErrCloseIndex, p->GetStart());
                            goto err;
                        }
                        continue;
                    }
                }

                if (var->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypPointer)                // for classes
                {
                    if (IsOfType(p, ID_DOT))
                    {
                        CBotToken* pp = p;

                        CBotFieldExpr* i = new CBotFieldExpr();            // new element
                        i->SetToken(pp);                                // keeps the name of the token
                        inst->AddNext3(i);                                // adds after

                        if (p->GetType() == TokenTypVar)                // must be a name
                        {
                            CBotVar*   preVar = var;
                            var = var->GetItem(p->GetString());            // get item correspondent
                            if (var != nullptr)
                            {
                                if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var,
                                                                        CBotVar::ProtectionLevel::ReadOnly))
                                {
                                    pStk->SetError(CBotErrPrivate, pp);
                                    goto err;
                                }

                                i->SetUniqNum(var->GetUniqNum());
                                p = p->GetNext();                        // skips the name
                                continue;
                            }
                            pStk->SetError(CBotErrUndefItem, p);
                        }
                        pStk->SetError(CBotErrUndefClass, p->GetStart());
                        goto err;
                    }
                }
                break;
            }


            if (pStk->IsOk()) return static_cast<CBotLeftExpr*> (pStack->Return(inst, pStk));
        }
        pStk->SetError(CBotErrUndefVar, p);
err:
        delete inst;
        return static_cast<CBotLeftExpr*> ( pStack->Return(nullptr, pStk));
    }

    return static_cast<CBotLeftExpr*> ( pStack->Return(nullptr, pStk));
}
Exemplo n.º 18
0
CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResult type)
{
    CBotCStack* pStk = pStack->TokenStack(p);

    CBotDefArray*    inst = new CBotDefArray();

    CBotToken*    vartoken = p;
    inst->SetToken(vartoken);

    // determinse the expression is valid for the item on the left side
    if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
    {
        if (pStk->CheckVarLocal(vartoken))                              // redefinition of the variable?
        {
            pStk->SetError(CBotErrRedefVar, vartoken);
            goto error;
        }

        CBotInstr*    i;
        while (IsOfType(p,  ID_OPBRK))
        {
            pStk->SetStartError(p->GetStart());
            if (p->GetType() != ID_CLBRK)
            {
                i = CBotExpression::Compile(p, pStk);                  // expression for the value
                if (i == nullptr || pStk->GetType() != CBotTypInt)     // must be a number
                {
                    pStk->SetError(CBotErrBadIndex, p->GetStart());
                    goto error;
                }
            }
            else
                i = new CBotEmpty();                                    // if no special formula

            inst->AddNext3b(i);                                         // construct a list
            type = CBotTypResult(CBotTypArrayPointer, type);

            if (IsOfType(p, ID_CLBRK)) continue;

            pStk->SetError(CBotErrCloseIndex, p->GetStart());
            goto error;
        }

        CBotVar*   var = CBotVar::Create(*vartoken, type);               // create an instance
        inst->m_typevar = type;

        var->SetUniqNum(
            (static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
        pStack->AddVar(var);                                            // place it on the stack

        if (IsOfType(p, ID_ASS))                                        // with an assignment
        {
            pStk->SetStartError(p->GetStart());
            if ( IsOfType(p, ID_SEP) )
            {
                pStk->SetError(CBotErrNoExpression, p->GetPrev());
                goto error;
            }
            if ( nullptr == (inst->m_listass = CBotListArray::Compile(p, pStk, type.GetTypElem())) )
            {
                if (pStk->IsOk())
                {
                    inst->m_listass = CBotTwoOpExpr::Compile(p, pStk);
                    if (inst->m_listass == nullptr || !pStk->GetTypResult().Compare(type))  // compatible type ?
                    {
                        pStk->SetError(CBotErrBadType1, p->GetStart());
                        goto error;
                    }
                }
            }

            if (pStk->IsOk()) while (true)       // mark initialized
            {
                var = var->GetItem(0, true);
                if (var == nullptr) break;
                if (var->GetType() == CBotTypArrayPointer) continue;
                if (var->GetType() <= CBotTypString) var->SetInit(CBotVar::InitType::DEF);
                break;
            }
        }

        if (pStk->IsOk()) return pStack->Return(inst, pStk);
    }

error:
    delete inst;
    return pStack->Return(nullptr, pStk);
}
Exemplo n.º 19
0
CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMethodsOnly)
{
    if (p->GetType() == ID_DOT)
    {
        CBotVar*     var = pStack->GetVar();

        if (var == nullptr) return nullptr;

        CBotCStack* pStk = pStack->TokenStack();
        CBotInstr* inst = new CBotExprRetVar();

        while (true)
        {
            pStk->SetStartError(p->GetStart());
            if (var->GetType() == CBotTypArrayPointer)
            {
                if (bMethodsOnly) goto err;

                if (IsOfType( p, ID_OPBRK ))
                {
                    CBotIndexExpr* i = new CBotIndexExpr();
                    i->m_expr = CBotExpression::Compile(p, pStk);
                    inst->AddNext3(i);

                    var = var->GetItem(0,true);

                    if (i->m_expr == nullptr || pStk->GetType() != CBotTypInt)
                    {
                        pStk->SetError(CBotErrBadIndex, p->GetStart());
                        goto err;
                    }
                    if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK ))
                    {
                        pStk->SetError(CBotErrCloseIndex, p->GetStart());
                        goto err;
                    }
                    continue;
                }
            }
            if (var->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypPointer)
            {
                if (IsOfType(p, ID_DOT))
                {
                    CBotToken* pp = p;

                    if (p->GetType() == TokenTypVar)
                    {
                        if (p->GetNext()->GetType() == ID_OPENPAR)
                        {
                            CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var, bMethodsOnly);
                            if (!pStk->IsOk()) goto err;
                            inst->AddNext3(i);
                            return pStack->Return(inst, pStk);
                        }
                        else if (bMethodsOnly)
                        {
                            p = p->GetPrev();
                            goto err;
                        }
                        else
                        {
                            CBotFieldExpr* i = new CBotFieldExpr();
                            i->SetToken(pp);
                            inst->AddNext3(i);
                            CBotVar*   preVar = var;
                            var = var->GetItem(p->GetString());
                            if (var != nullptr)
                            {
                                i->SetUniqNum(var->GetUniqNum());
                                if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var))
                                {
                                    pStk->SetError(CBotErrPrivate, pp);
                                    goto err;
                                }
                            }
                        }

                        if (var != nullptr)
                        {
                            p = p->GetNext();
                            continue;
                        }
                        pStk->SetError(CBotErrUndefItem, p);
                        goto err;
                    }
                    pStk->SetError(CBotErrUndefClass, p);
                    goto err;
                }
            }
            break;
        }

        pStk->SetCopyVar(var);
        if (pStk->IsOk()) return pStack->Return(inst, pStk);

        pStk->SetError(CBotErrUndefVar, p);
err:
        delete inst;
        return pStack->Return(nullptr, pStk);
    }
    return nullptr;
}
Exemplo n.º 20
0
bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
{
    bool    bStatic = false;
    int     mProtect = PR_PUBLIC;
    bool    bSynchro = false;

    while (IsOfType(p, ID_SEP)) ;

    CBotTypResult   type( -1 );

    if ( IsOfType(p, ID_SYNCHO) ) bSynchro = true;
    CBotToken*      pBase = p;

    if ( IsOfType(p, ID_STATIC) ) bStatic = true;
    if ( IsOfType(p, ID_PUBLIC) ) mProtect = PR_PUBLIC;
    if ( IsOfType(p, ID_PRIVATE) ) mProtect = PR_PRIVATE;
    if ( IsOfType(p, ID_PROTECTED) ) mProtect = PR_PROTECT;
    if ( IsOfType(p, ID_STATIC) ) bStatic = true;

//  CBotClass* pClass = NULL;
    type = TypeParam(p, pStack);        // type of the result

    if ( type.Eq(-1) )
    {
        pStack->SetError(TX_NOTYP, p);
        return false;
    }

    while (pStack->IsOk()) 
    {
        CBotToken*  pp = p;
        IsOfType(p, ID_NOT);    // skips ~ eventual (destructor)

        if (IsOfType(p, TokenTypVar))
        {
            CBotInstr* limites = NULL;
            while ( IsOfType( p, ID_OPBRK ) )   // a table?
            {
                CBotInstr* i = NULL;

                if ( p->GetType() != ID_CLBRK )
                    i = CBotExpression::Compile( p, pStack );           // expression for the value
                else
                    i = new CBotEmpty();                            // special if not a formula

                type = CBotTypResult(CBotTypArrayPointer, type);

                if (!pStack->IsOk() || !IsOfType( p, ID_CLBRK ) )
                {
                    pStack->SetError(TX_CLBRK, p->GetStart());
                    return false;
                }

/*              CBotVar* pv = pStack->GetVar();
                if ( pv->GetType()>= CBotTypBoolean )
                {
                    pStack->SetError(TX_BADTYPE, p->GetStart());
                    return false;
                }*/

                if (limites == NULL) limites = i;
                else limites->AddNext3(i);
            }

            if ( p->GetType() == ID_OPENPAR )
            {
                if ( !bSecond )
                {
                    p = pBase;
                    CBotFunction* f = 
                    CBotFunction::Compile1(p, pStack, this);

                    if ( f == NULL ) return false;

                    if (m_pMethod == NULL) m_pMethod = f;
                    else m_pMethod->AddNext(f);
                }
                else
                {
                    // return a method precompiled in pass 1
                    CBotFunction*   pf = m_pMethod;
                    CBotFunction*   prev = NULL;
                    while ( pf != NULL ) 
                    {
                        if (pf->GetName() == pp->GetString()) break;
                        prev = pf;
                        pf = pf->Next();
                    }

                    bool bConstructor = (pp->GetString() == GetName());
                    CBotCStack* pile = pStack->TokenStack(NULL, true);

                    // make "this" known
                    CBotToken TokenThis(CBotString("this"), CBotString());
                    CBotVar* pThis = CBotVar::Create(&TokenThis, CBotTypResult( CBotTypClass, this ) );
                    pThis->SetUniqNum(-2);
                    pile->AddVar(pThis);

                    if ( m_pParent )
                    {
                        // makes "super" known
                        CBotToken TokenSuper(CBotString("super"), CBotString());
                        CBotVar* pThis = CBotVar::Create(&TokenSuper, CBotTypResult( CBotTypClass, m_pParent ) );
                        pThis->SetUniqNum(-3);
                        pile->AddVar(pThis);
                    }

//                  int num = 1;
                    CBotClass*  my = this;
                    while (my != NULL)
                    {
                        // places a copy of variables of a class (this) on a stack
                        CBotVar* pv = my->m_pVar;
                        while (pv != NULL)
                        {
                            CBotVar* pcopy = CBotVar::Create(pv);
                            pcopy->SetInit(!bConstructor || pv->IsStatic());
                            pcopy->SetUniqNum(pv->GetUniqNum());
                            pile->AddVar(pcopy);
                            pv = pv->GetNext();
                        }
                        my = my->m_pParent;
                    }

                    // compiles a method
                    p = pBase;
                    CBotFunction* f = 
                    CBotFunction::Compile(p, pile, NULL/*, false*/);

                    if ( f != NULL )
                    {
                        f->m_pProg = pStack->GetBotCall();
                        f->m_bSynchro = bSynchro;
                        // replaces the element in the chain
                        f->m_next = pf->m_next;
                        pf->m_next = NULL;
                        delete pf;
                        if (prev == NULL) m_pMethod = f;
                        else prev->m_next = f;
                    }
                    pStack->Return(NULL, pile);
                }

                return pStack->IsOk();
            }

            // definition of an element
            if (type.Eq(0))
            {
                pStack->SetError(TX_ENDOF, p);
                return false;
            }

            CBotInstr* i = NULL;
            if ( IsOfType(p, ID_ASS ) )
            {
                if ( type.Eq(CBotTypArrayPointer) )
                {
                    i = CBotListArray::Compile(p, pStack, type.GetTypElem());
                }
                else
                {
                    // it has an assignmet to calculate
                    i = CBotTwoOpExpr::Compile(p, pStack);
                }
                if ( !pStack->IsOk() ) return false;
            }


            if ( !bSecond )
            {
                CBotVar*    pv = CBotVar::Create(pp->GetString(), type);
                pv -> SetStatic( bStatic );
                pv -> SetPrivate( mProtect );

                AddItem( pv );

                pv->m_InitExpr = i;
                pv->m_LimExpr = limites;


                if ( pv->IsStatic() && pv->m_InitExpr != NULL )
                {
                    CBotStack* pile = CBotStack::FirstStack();              // independent stack
                    while(pile->IsOk() && !pv->m_InitExpr->Execute(pile));  // evaluates the expression without timer
                    pv->SetVal( pile->GetVar() ) ;
                    pile->Delete();
                }
            }
            else
                delete i;

            if ( IsOfType(p, ID_COMMA) ) continue;
            if ( IsOfType(p, ID_SEP) ) break;
        }
        pStack->SetError(TX_ENDOF, p);
    }
    return pStack->IsOk();
}
Exemplo n.º 21
0
CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotSwitch* inst = new CBotSwitch();        // creates the object
    CBotToken*  pp = p;                         // preserves at the ^ token (starting position)

    inst->SetToken(p);
    if (!IsOfType(p, ID_SWITCH)) return nullptr;   // should never happen

    CBotCStack* pStk = pStack->TokenStack(pp);  // un petit bout de pile svp

    if ( IsOfType(p, ID_OPENPAR ) )
    {
        if ( nullptr != (inst->m_Value = CBotExpression::Compile( p, pStk )) )
        {
            if ( pStk->GetType() < CBotTypLong )
            {
                if ( IsOfType(p, ID_CLOSEPAR ) )
                {
                    if ( IsOfType(p, ID_OPBLK ) )
                    {
                        IncLvl();

                        while( !IsOfType( p, ID_CLBLK ) )
                        {
                            if ( p->GetType() == ID_CASE || p->GetType() == ID_DEFAULT)
                            {
                                CBotCStack* pStk2 = pStk->TokenStack(p);    // un petit bout de pile svp

                                CBotInstr* i = CBotCase::Compile( p, pStk2 );
                                if (i == nullptr)
                                {
                                    delete inst;
                                    return pStack->Return(nullptr, pStk2);
                                }
                                delete pStk2;
                                if ( inst->m_Block == nullptr ) inst->m_Block = i;
                                else inst->m_Block->AddNext(i);
                                continue;
                            }

                            if ( inst->m_Block == nullptr )
                            {
                                pStk->SetError(TX_NOCASE, p->GetStart());
                                delete inst;
                                return pStack->Return(nullptr, pStk);
                            }

                            CBotInstr* i = CBotBlock::CompileBlkOrInst( p, pStk, true );
                            if ( !pStk->IsOk() )
                            {
                                delete inst;
                                return pStack->Return(nullptr, pStk);
                            }
                            inst->m_Block->AddNext(i);

                            if ( p == nullptr )
                            {
                                pStk->SetError(TX_CLOSEBLK, -1);
                                delete inst;
                                return pStack->Return(nullptr, pStk);
                            }
                        }
                        DecLvl();

                        if ( inst->m_Block == nullptr )
                        {
                            pStk->SetError(TX_NOCASE, p->GetStart());
                            delete inst;
                            return pStack->Return(nullptr, pStk);
                        }
                        // the statement block is ok
                        return pStack->Return(inst, pStk);  // return an object to the application
                    }
                    pStk->SetError( TX_OPENBLK, p->GetStart() );
                }
                pStk->SetError( TX_CLOSEPAR, p->GetStart() );
            }
            pStk->SetError( TX_BADTYPE, p->GetStart() );
        }
    }
    pStk->SetError( TX_OPENPAR, p->GetStart());

    delete inst;                                // error, frees up
    return pStack->Return(nullptr, pStk);          // no object, the error is on the stack
}
Exemplo n.º 22
0
// compiles a new function
// bLocal allows of the declaration of parameters on the same level
// as the elements belonging to the class for methods
CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunction* finput, bool bLocal)
{
    CBotToken*      pp;
    CBotFunction* func = finput;
    if ( func == NULL ) func = new CBotFunction();

    CBotCStack* pStk = pStack->TokenStack(p, bLocal);

//  func->m_nFuncIdent = CBotVar::NextUniqNum();

    while (true)
    {
        if ( IsOfType(p, ID_PUBLIC) )
        {
            func->m_bPublic = true;
            continue;
        }
        pp = p;
        if ( IsOfType(p, ID_EXTERN) )
        {
            func->m_extern = pp;        // for the position of the word "extern"
            func->m_bExtern = true;
//          func->m_bPublic = true;     // therefore also public!
            continue;
        }
        break;
    }

    func->m_retToken = *p;
//  CBotClass*  pClass;
    func->m_retTyp = TypeParam(p, pStk);        // type of the result

    if (func->m_retTyp.GetType() >= 0)
    {
        CBotToken*  pp = p;
        func->m_token = *p;

        if ( IsOfType(p, ID_NOT) )
        {
            CBotToken d("~" + p->GetString());
            func->m_token = d;
        }

        // un nom de fonction est-il là ?
        if (IsOfType(p, TokenTypVar))
        {
            if ( IsOfType( p, ID_DBLDOTS ) )        // method for a class
            {
                func->m_MasterClass = pp->GetString();
                CBotClass* pClass = CBotClass::Find(pp);
                if ( pClass == NULL ) goto bad;

//              pp = p;
                func->m_token = *p;
                if (!IsOfType(p, TokenTypVar)) goto bad;

            }
            func->m_openpar = p;
            func->m_Param = CBotDefParam::Compile( p, pStk );
            func->m_closepar = p->GetPrev();
            if (pStk->IsOk())
            {
                pStk->SetRetType(func->m_retTyp);   // for knowledge what type returns

                if (!func->m_MasterClass.IsEmpty())
                {
                    // return "this" known
                    CBotVar* pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, func->m_MasterClass ));
                    pThis->SetInit(2);
//                  pThis->SetUniqNum(func->m_nThisIdent = -2); //CBotVar::NextUniqNum() will not
                    pThis->SetUniqNum(-2);
                    pStk->AddVar(pThis);

                    // initialize variables acording to This
                    // only saves the pointer to the first,
                    // the rest is chained
                    CBotVar* pv = pThis->GetItemList();
//                  int num = 1;
                    while (pv != NULL)
                    {
                        CBotVar* pcopy = CBotVar::Create(pv);
//                      pcopy->SetInit(2);
                        pcopy->Copy(pv);
                        pcopy->SetPrivate(pv->GetPrivate());
//                      pcopy->SetUniqNum(pv->GetUniqNum()); //num++);
                        pStk->AddVar(pcopy);
                        pv = pv->GetNext();
                    }
                }

                // and compiles the following instruction block 
                func->m_openblk = p;
                func->m_Block   = CBotBlock::Compile(p, pStk, false);
                func->m_closeblk = p->GetPrev();
                if ( pStk->IsOk() )
                {
                    if ( func->m_bPublic )  // public function, return known for all
                    {
                        CBotFunction::AddPublic(func);
                    }
                    return pStack->ReturnFunc(func, pStk);
                }
            }
        }
bad:
        pStk->SetError(TX_NOFONC, p);
    }
    pStk->SetError(TX_NOTYP, p);
    if ( finput == NULL ) delete func;
    return pStack->ReturnFunc(NULL, pStk);
}
Exemplo n.º 23
0
CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotVar*    ppVars[1000];

    int         i = 0;

    CBotToken*  pp = p; 
    p = p->GetNext();

    pStack->SetStartError(p->GetStart());
    CBotCStack* pile = pStack;

    if ( IsOfType(p, ID_OPENPAR) )
    {
        int start, end;
        CBotInstrCall* inst = new CBotInstrCall();
        inst->SetToken(pp);

        // compile la list of parameters
        if (!IsOfType(p, ID_CLOSEPAR)) while (true)
        {
            start = p->GetStart();
            pile = pile->TokenStack();                      // keeps the results on the stack

            CBotInstr*  param = CBotExpression::Compile(p, pile);
            end   = p->GetStart();
            if ( inst->m_Parameters == NULL ) inst->m_Parameters = param;
            else inst->m_Parameters->AddNext(param);            // constructs the list

            if ( !pile->IsOk() )
            {
                delete inst;
                return pStack->Return(NULL, pile);
            }

            if ( param != NULL )
            {
                if ( pile->GetTypResult().Eq(99) )
                {
                    delete pStack->TokenStack();
                    pStack->SetError(TX_VOID, p->GetStart());
                    delete inst;
                    return NULL;
                }
                ppVars[i] = pile->GetVar();
                ppVars[i]->GetToken()->SetPos(start, end);
                i++;

                if (IsOfType(p, ID_COMMA)) continue;            // skips the comma
                if (IsOfType(p, ID_CLOSEPAR)) break;
            }

            pStack->SetError(TX_CLOSEPAR, p->GetStart());
            delete pStack->TokenStack();
            delete inst;
            return NULL;
        }
        ppVars[i] = NULL;

        // the routine is known?
//      CBotClass*  pClass = NULL;
        inst->m_typRes = pStack->CompileCall(pp, ppVars, inst->m_nFuncIdent);
        if ( inst->m_typRes.GetType() >= 20 )
        {
//          if (pVar2!=NULL) pp = pVar2->RetToken();
            pStack->SetError( inst->m_typRes.GetType(), pp );
            delete pStack->TokenStack();
            delete inst;
            return NULL;
        }

        delete pStack->TokenStack();
        if ( inst->m_typRes.GetType() > 0 )
        {
            CBotVar* pRes = CBotVar::Create("", inst->m_typRes);
            pStack->SetVar(pRes);   // for knowing the type of the result
        }
        else pStack->SetVar(NULL);          // routine returns void

        return inst;
    }
    p = pp;
    delete pStack->TokenStack();
    return NULL;
}
Exemplo n.º 24
0
CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass)
{
    // seeks the corresponding classes
    if ( pClass == NULL )
    {
        pStack->SetStartError(p->GetStart());
        pClass = CBotClass::Find(p);
        if ( pClass == NULL )
        {
            // not found? is bizare
            pStack->SetError(TX_NOCLASS, p);
            return NULL;
        }
        p = p->GetNext();
    }

    bool        bIntrinsic = pClass->IsIntrinsic();
    CBotTypResult type = CBotTypResult( bIntrinsic ? CBotTypIntrinsic : CBotTypPointer, pClass );
    CBotClassInst*  inst = static_cast<CBotClassInst*>(CompileArray(p, pStack, type));
    if ( inst != NULL || !pStack->IsOk() ) return inst;

    CBotCStack* pStk = pStack->TokenStack();

    inst = new CBotClassInst();
    /// \TODO Need to be revised and fixed after adding unit tests
    CBotToken token(pClass->GetName(), CBotString(), p->GetStart(), p->GetEnd());
    inst->SetToken(&token);
    CBotToken*  vartoken = p;

    if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
    {
        (static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = type;
        if (pStk->CheckVarLocal(vartoken))                  // redefinition of the variable
        {
            pStk->SetStartError(vartoken->GetStart());
            pStk->SetError(TX_REDEFVAR, vartoken->GetEnd());
            goto error;
        }

        if (IsOfType(p,  ID_OPBRK))                         // with any clues?
        {
            delete inst;                                    // is not type CBotInt
            p = vartoken;                                   // returns to the variable name

            // compiles declaration an array

            inst = static_cast<CBotClassInst*>(CBotInstArray::Compile( p, pStk, type ));

            if (!pStk->IsOk() )
            {
                pStk->SetError(TX_CLBRK, p->GetStart());
                goto error;
            }
            goto suite;         // no assignment, variable already created
        }


        CBotVar*    var;
        var = CBotVar::Create(vartoken->GetString(), type); // creates the instance
//      var->SetClass(pClass);
        var->SetUniqNum(
            (static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
                                                            // its attribute a unique number
        pStack->AddVar(var);                                // placed on the stack

        // look if there are parameters
        inst->m_hasParams = (p->GetType() == ID_OPENPAR);

        CBotVar*    ppVars[1000];
        inst->m_Parameters = CompileParams(p, pStk, ppVars);
        if ( !pStk->IsOk() ) goto error;

        // if there are parameters, is the equivalent to the stament "new"
        // CPoint A ( 0, 0 ) is equivalent to
        // CPoint A = new CPoint( 0, 0 )

//      if ( NULL != inst->m_Parameters )
        if ( inst->m_hasParams )
        {
            // the constructor is there?
//          CBotString  noname;
            CBotTypResult r = pClass->CompileMethode(pClass->GetName(), var, ppVars, pStk, inst->m_nMethodeIdent);
            delete pStk->TokenStack();                          // releases the supplement stack
            int typ = r.GetType();

            if (typ == TX_UNDEFCALL)
            {
                // si le constructeur n'existe pas
                if (inst->m_Parameters != NULL)                 // with parameters
                {
                    pStk->SetError(TX_NOCONST, vartoken);
                    goto error;
                }
                typ = 0;
            }

            if (typ>20)
            {
                pStk->SetError(typ, vartoken->GetEnd());
                goto error;
            }

        }

        if (IsOfType(p,  ID_ASS))                           // with a assignment?
        {
            if (inst->m_hasParams)
            {
                pStk->SetError(TX_ENDOF, p->GetStart());
                goto error;
            }

            if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
            {
                goto error;
            }
            CBotClass* result = pStk->GetClass();
            if ( !pStk->GetTypResult(1).Eq(CBotTypNullPointer) &&
               ( !pStk->GetTypResult(1).Eq(CBotTypPointer) ||
                 ( result != NULL && !pClass->IsChildOf(result) )))     // type compatible ?
            {
                pStk->SetError(TX_BADTYPE, p->GetStart());
                goto error;
            }
//          if ( !bIntrinsic ) var->SetPointer(pStk->GetVar()->GetPointer());
            if ( !bIntrinsic )
            {
                // does not use the result on the stack, to impose the class
                CBotVar* pvar = CBotVar::Create("", pClass);
                var->SetPointer( pvar );                    // variable already declared instance pointer
                delete pvar;                                // removes the second pointer
            }
            var->SetInit(true);                         // marks the pointer as init
        }
        else if (inst->m_hasParams)
        {
            // creates the object on the "job" (\TODO "tas")
            // with a pointer to the object
            if ( !bIntrinsic )
            {
                CBotVar* pvar = CBotVar::Create("", pClass);
                var->SetPointer( pvar );                    // variable already declared instance pointer
                delete pvar;                                // removes the second pointer
            }
            var->SetInit(2);                            // marks the pointer as init
        }
suite:
        if (IsOfType(p,  ID_COMMA))                         // several chained definitions
        {
            if ( NULL != ( inst->m_next = CBotClassInst::Compile(p, pStk, pClass) ))    // compiles the following
            {
                return pStack->Return(inst, pStk);
            }
        }

        if (IsOfType(p,  ID_SEP))                           // complete instruction
        {
            return pStack->Return(inst, pStk);
        }

        pStk->SetError(TX_ENDOF, p->GetStart());
    }

error:
    delete inst;
    return pStack->Return(NULL, pStk);
}