Пример #1
0
bool CBotListArray::Execute(CBotStack* &pj, CBotVar* pVar)
{
    CBotStack*    pile1 = pj->AddStack();
    CBotVar* pVar2;

    CBotInstr* p = m_expr;

    int n = 0;

    for (; p != nullptr ; n++, p = p->GetNext3b())
    {
        if (pile1->GetState() > n) continue;

        pVar2 = pVar->GetItem(n, true);

        if (pVar2 == nullptr)
        {
            pj->SetError(CBotErrOutArray, p->GetToken());
            return false;
        }
        CBotTypResult type = pVar2->GetTypResult();

        if (!p->Execute(pile1, pVar2)) return false;        // evaluate expression

        if (type.Eq(CBotTypPointer)) pVar2->SetType(type);  // keep pointer type

        pile1->IncState();
    }

    return pj->Return(pile1);
}
Пример #2
0
CBotInstr* CBotReturn::Compile(CBotToken* &p, CBotCStack* pStack)
{
    CBotToken*  pp = p;

    if (!IsOfType(p, ID_RETURN)) return NULL;   // should never happen

    CBotReturn* inst = new CBotReturn();        // creates the object
    inst->SetToken( pp );

    CBotTypResult   type = pStack->GetRetType();

    if ( type.GetType() == 0 )                  // returned void ?
    {
        if ( IsOfType( p, ID_SEP ) ) return inst;
        pStack->SetError( TX_BADTYPE, pp );
        return NULL;
    }

    inst->m_Instr = CBotExpression::Compile(p, pStack);
    if ( pStack->IsOk() )
    {
        CBotTypResult   retType = pStack->GetTypResult(2);
        if (TypeCompatible(retType, type, ID_ASS)) 
        {
            if ( IsOfType( p, ID_SEP ) )
                return inst;

            pStack->SetError(TX_ENDOF, p->GetStart());
        }
        pStack->SetError(TX_BADTYPE, p->GetStart());
    }

    delete inst;
    return NULL;                            // no object, the error is on the stack
}
Пример #3
0
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 );

}
Пример #4
0
// compiles a list of parameters
CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
{
    // mainly not pStack->TokenStack here
    // declared variables must remain visible thereafter

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

    if (IsOfType(p, ID_OPENPAR))
    {
        CBotDefParam* list = NULL;
    
        while (!IsOfType(p, ID_CLOSEPAR))
        {
            CBotDefParam* param = new CBotDefParam();
            if (list == NULL) list = param;
            else list->AddNext(param);          // added to the list

//            CBotClass*  pClass = NULL;//= CBotClass::Find(p);
            param->m_typename = p->GetString();
            CBotTypResult type = param->m_type = TypeParam(p, pStack);
//          if ( type == CBotTypPointer ) type = CBotTypClass;          // we must create a new object

            if (param->m_type.GetType() > 0)
            {
                CBotToken*  pp = p;
                param->m_token = *p;
                if (pStack->IsOk() && IsOfType(p, TokenTypVar) )
                {

                    // variable already declared?
                    if (pStack->CheckVarLocal(pp))
                    {
                        pStack->SetError(TX_REDEFVAR, pp);
                        break;
                    }

                    if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody);
                    CBotVar*    var = CBotVar::Create(pp->GetString(), type);       // creates the variable
//                  if ( pClass ) var->SetClass(pClass);
                    var->SetInit(2);                                    // mark initialized
                    param->m_nIdent = CBotVar::NextUniqNum();
                    var->SetUniqNum(param->m_nIdent);
                    pStack->AddVar(var);                                // place on the stack

                    if (IsOfType(p, ID_COMMA) || p->GetType() == ID_CLOSEPAR)
                        continue;
                }
                pStack->SetError(TX_CLOSEPAR, p->GetStart());
            }
            pStack->SetError(TX_NOTYP, p);
            delete list;
            return NULL;
        }
        return list;
    }
    pStack->SetError(TX_OPENPAR, p->GetStart());
    return NULL;
}
Пример #5
0
CBotTypResult CBotVar::GetTypResult(GetTypeMode mode)
{
    CBotTypResult    r = m_type;

    if ( mode == GetTypeMode::CLASS_AS_POINTER && m_type.Eq(CBotTypClass) )
        r.SetType(CBotTypPointer);
    if ( mode == GetTypeMode::CLASS_AS_INTRINSIC && m_type.Eq(CBotTypClass) )
        r.SetType(CBotTypIntrinsic);

    return r;
}
Пример #6
0
CBotTypResult CBotVar::GetTypResult(int mode)
{
    CBotTypResult    r = m_type;

    if ( mode == 1 && m_type.Eq(CBotTypClass) )
        r.SetType(CBotTypPointer);
    if ( mode == 2 && m_type.Eq(CBotTypClass) )
        r.SetType(CBotTypIntrinsic);

    return r;
}
Пример #7
0
CBotVarArray::CBotVarArray(const CBotToken& name, CBotTypResult& type) : CBotVar(name)
{
    if ( !type.Eq(CBotTypArrayPointer) &&
         !type.Eq(CBotTypArrayBody)) assert(0);

    m_next        = nullptr;
    m_pMyThis    = nullptr;
    m_pUserPtr    = nullptr;

    m_type        = type;
    m_type.SetType(CBotTypArrayPointer);
    m_binit        = CBotVar::InitType::UNDEF;

    m_pInstance    = nullptr;                        // the list of the array elements
}
Пример #8
0
CBotTypResult CBotClass::CompileMethode(const char* name,
                                        CBotVar* pThis, CBotVar** ppParams,
                                        CBotCStack* pStack, long& nIdent)
{
    nIdent = 0; // forget the previous one if necessary

    // find the methods declared by AddFunction

    CBotTypResult r = m_pCalls->CompileCall(name, pThis, ppParams, pStack, nIdent);
    if ( r.GetType() >= 0) return r;

    // find the methods declared by user

    r = m_pMethod->CompileCall(name, ppParams, nIdent);
    if ( r.Eq(TX_UNDEFCALL) && m_pParent != NULL )
        return m_pParent->m_pMethod->CompileCall(name, ppParams, nIdent);
    return r;
}
Пример #9
0
bool TypesCompatibles(const CBotTypResult& type1, const CBotTypResult& type2)
{
    int    t1 = type1.GetType();
    int    t2 = type2.GetType();

    if (t1 == CBotTypIntrinsic) t1 = CBotTypClass;
    if (t2 == CBotTypIntrinsic) t2 = CBotTypClass;

    int max = (t1 > t2) ? t1 : t2;

    if (max == 99) return false;                    // result is void?

    if (max >= CBotTypBoolean)
    {
        if (t2 != t1) return false;

        if (max == CBotTypArrayPointer)
            return TypesCompatibles(type1.GetTypElem(), type2.GetTypElem());

        if (max == CBotTypClass || max == CBotTypPointer)
            return type1.GetClass() == type2.GetClass() ;

        return true ;
    }
    return true;
}
Пример #10
0
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 );
}
Пример #11
0
CBotTypResult   cSpace(CBotVar* &var, void* user)
{
    CBotTypResult       ret;

    if ( var == 0 )  return CBotTypResult( CBotTypIntrinsic, "point" );
    ret = cPoint(var, user);
    if ( !ret.Eq(0) )  return ret;

    if ( var == 0 )  return CBotTypIntrinsic;
    if ( var->GivType() > CBotTypDouble )  return CBotTypResult( CBotErrBadNum );
    var = var->GivNext();

    if ( var == 0 )  return CBotTypIntrinsic;
    if ( var->GivType() > CBotTypDouble )  return CBotTypResult( CBotErrBadNum );
    var = var->GivNext();

    if ( var == 0 )  return CBotTypIntrinsic;
    if ( var->GivType() > CBotTypDouble )  return CBotTypResult( CBotErrBadNum );
    var = var->GivNext();

    if ( var != 0 )  return CBotErrOverParam;
    return CBotTypResult( CBotTypIntrinsic, "point" );
}
Пример #12
0
bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
{
    int    t1 = type1.GetType();
    int    t2 = type2.GetType();

    int max = (t1 > t2) ? t1 : t2;

    if (max == 99) return false;    // result is void?

    // special case for strin concatenation
    if (op == ID_ADD && max >= CBotTypString) return true;
    if (op == ID_ASSADD && max >= CBotTypString) return true;
    if (op == ID_ASS && t1 == CBotTypString) return true;

    if (max >= CBotTypBoolean)
    {
        if ( (op == ID_EQ || op == ID_NE) &&
             (t1 == CBotTypPointer && t2 == CBotTypNullPointer)) return true;
        if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
             (t2 == CBotTypPointer && t1 == CBotTypNullPointer)) return true;
        if ( (op == ID_EQ || op == ID_NE) &&
             (t1 == CBotTypArrayPointer && t2 == CBotTypNullPointer)) return true;
        if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
             (t2 == CBotTypArrayPointer && t1 == CBotTypNullPointer)) return true;
        if (t2 != t1) return false;
        if (t1 == CBotTypArrayPointer) return type1.Compare(type2);
        if (t1 == CBotTypPointer ||
            t1 == CBotTypClass   ||
            t1 == CBotTypIntrinsic )
        {
            CBotClass*    c1 = type1.GetClass();
            CBotClass*    c2 = type2.GetClass();

            return c1->IsChildOf(c2) || c2->IsChildOf(c1);
            // accept the case in reverse
            // the transaction will be denied at runtime if the pointer is not
            // compatible
        }

        return true;
    }

    type1.SetType(max);
    type2.SetType(max);
    return true;
}
Пример #13
0
bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, CBotTypResult& rettype)
{
    CBotTypResult        res;

    // first looks by the identifier

    res = CBotCall::DoCall(nIdent, NULL, ppVar, this, rettype );
    if (res.GetType() >= 0) return res.GetType();

    res = m_prog->GetFunctions()->DoCall(nIdent, NULL, ppVar, this, token );
    if (res.GetType() >= 0) return res.GetType();

    // if not found (recompile?) seeks by name

    nIdent = 0;
    res = CBotCall::DoCall(nIdent, token, ppVar, this, rettype );
    if (res.GetType() >= 0) return res.GetType();

    res = m_prog->GetFunctions()->DoCall(nIdent, token->GetString(), ppVar, this, token );
    if (res.GetType() >= 0) return res.GetType();

    SetError(TX_NOCALL, token);
    return true;
}
Пример #14
0
CBotVarPointer::CBotVarPointer(const CBotToken& name, CBotTypResult& type)
{
    if ( !type.Eq(CBotTypPointer) &&
         !type.Eq(CBotTypNullPointer) &&
         !type.Eq(CBotTypClass)   &&                    // for convenience accepts Class and Intrinsic
         !type.Eq(CBotTypIntrinsic) ) assert(0);

    m_token        = new CBotToken(name);
    m_next        = nullptr;
    m_pMyThis    = nullptr;
    m_pUserPtr    = nullptr;

    m_type        = type;
    if ( !type.Eq(CBotTypNullPointer) )
        m_type.SetType(CBotTypPointer);                    // anyway, this is a pointer
    m_binit        = CBotVar::InitType::UNDEF;
    m_pClass    = nullptr;
    m_pVarClass = nullptr;                                    // will be defined by a SetPointer()

    SetClass(type.GetClass());
}
Пример #15
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);
}
Пример #16
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);
}