Logo Search packages:      
Sourcecode: kaya version File versions  Download package

VMState.cc

/**
    Kaya run-time system
    Copyright (C) 2004, 2005 Edwin Brady

    This file is distributed under the terms of the GNU Lesser General
    Public Licence. See COPYING for licence.
*/

#include "VMState.h"
#include "VM.h"
#include "ValueFuns.h"

#include <assert.h>
#include <ext/hash_map>

/// funcion map is global to all threads.
map<int,func> m_funmap;

void addToFunMap(int id, func fn)
{
    m_funmap[id]=fn;
}

func getFn(int id)
{
    return m_funmap[id];
}

int getFnID(func fn)
{
    map<int,func>::iterator it = m_funmap.begin();
    for (;it!=m_funmap.end();it++) {
      if ((*it).second == fn) { return ((*it).first); }
    }
    return -1;
}

VMState::VMState(bool panic) {
    m_stackalloc=100;
    m_globalloc=100;
    if (!panic) {
      m_valstack = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*m_stackalloc);
    }
    else {
      m_valstack = (Value**)malloc(100); // Tiny, if we're panicking.
    }
    m_stackptr=m_valstack;
}

void VMState::finish()
{
    if (!emptyStack()) {
      cerr << "Warning: Stack size is non-zero (" << m_stackptr << "," << m_valstack << ")" << endl;
    }
}

bool VMState::emptyStack()
{
    return m_stackptr==m_valstack;
}

void VMState::push2(Value* val, Value* val2)
{
    // FIXME: Grow stack if necessary? Might be quite an overhead... maybe 
    // make it an option.
    *(m_stackptr++)=val;
    *(m_stackptr++)=val2;
}

void VMState::push3(Value* val, Value* val2, Value* val3)
{
    // FIXME: Grow stack if necessary? Might be quite an overhead... maybe 
    // make it an option.
    *(m_stackptr++)=val;
    *(m_stackptr++)=val2;
    *(m_stackptr++)=val3;
}

void VMState::push4(Value* val, Value* val2, Value* val3, Value* val4)
{
    // FIXME: Grow stack if necessary? Might be quite an overhead... maybe 
    // make it an option.
    *(m_stackptr++)=val;
    *(m_stackptr++)=val2;
    *(m_stackptr++)=val3;
    *(m_stackptr++)=val4;
}

int VMState::tag()
{
    if ((*(m_stackptr-1))->getType()!=UNION) {
      kaya_throw("Attempt to get tag from non-Union",1);
    }

    return (*(m_stackptr-1))->getTag();
}

void VMState::readInt()
{
    Value* v=new Value(NULL,inttable);
    v->readInt();
    push(v);
}

void VMState::readStr()
{
    Value* v=new Value(NULL,stringtable);
    v->readString();
    push(v);
}

void VMState::doAppend()
{
    Value* str2=doPop();
    Value* str1=doPop();
    String* str=new String(str1->getString()->getVal());
    str->append(str2->getString());
    push(new Value((void*)str,stringtable));
}

void VMState::doEqExcept(bool inv)
{
    Value* e2=doPop();
    Value* e1=doPop();
    bool eq = (e2->getExcept()->eq(e1->getExcept()));
    if (inv) { eq = !eq; }
    if (eq) {  push(new Value((void*)1,inttable)); }
    else {  push(new Value((void*)0,inttable)); }
}

void VMState::doEqString(bool inv)
{
    Value* e2=doPop();
    Value* e1=doPop();
    bool eq = (e2->getString()->eq(e1->getString()));
    if (inv) { eq = !eq; }
    if (eq) {  push(new Value((void*)1,inttable)); }
    else {  push(new Value((void*)0,inttable)); }
}

void VMState::int2str()
{
    // Need to do this on a copy or we break types.
    Value* x = new Value(NULL,NULL);
    x->setInt(doPop()->getInt());
    x->int2str();
    push(x);
}

void VMState::real2str()
{
    // Need to do this on a copy or we break types.
    Value* x = new Value(NULL,NULL);
    x->setReal(doPop()->getReal());
    x->real2str();
    push(x);
}

void VMState::str2int()
{
    // Need to do this on a copy or we break types.
    Value* x = new Value(doPop()->getRaw(),inttable);
    x->str2int();
    push(x);
}

void VMState::str2real()
{
    // Need to do this on a copy or we break types.
    Value* x = new Value(doPop()->getRaw(),realtable);
    x->str2real();
    push(x);
}

void VMState::chr2str()
{
    // Need to do this on a copy or we break types.
    Value* x = new Value(doPop()->getRaw(),stringtable);
    x->chr2str();
    push(x);
}

void VMState::bool2str()
{
    // Need to do this on a copy or we break types.
    Value* x = new Value(doPop()->getRaw(),stringtable);
    x->bool2str();
    push(x);
}

void VMState::str2chr()
{
//    valstack[stacksize-1]->str2chr();
    assert(false);
}

void VMState::real2int()
{
    // Need to do this on a copy or we break types.
    Value* x = new Value(NULL,NULL);
    x->setReal(doPop()->getReal());
    x->real2int();
    push(x);
}

void VMState::int2real()
{
    // Need to do this on a copy or we break types.
    Value* x = new Value(NULL,NULL);
    x->setInt(doPop()->getInt());
    x->int2real();
    push(x);
}

void VMState::mkArray(int i)
{
    Array* array = new Array(i);
    while(i>0) {
      Value* v= doPop();
      array->push_back(v);
      i--;
    }

    push(new Value(array,arraytable));
}

void VMState::projarg(int i, int t)
{
    if ((*(m_stackptr-1))->getType()!=UNION) {
      kaya_throw("Attempt to project from non-Union",1);
    }
    Union* top = (Union*)doPop()->getRaw();

    if (top->tag!=t) {
      kaya_throw("Wrong constructor used for projection",1);
    }
    Value* arg=top->args[i];
    push(arg);
}

void VMState::goToIndex()
{
    --m_stackptr;
    int idx = (*m_stackptr)->getInt();
    (*(m_stackptr-1)) = (*(m_stackptr-1))->lookup(this,idx);
}

/// Replace the top stack item with the contents of the second stack item.
void VMState::setTop()
{
    (*(m_stackptr-1))->setPtr((*(m_stackptr-2)));
    (*(m_stackptr-2)) = (*(m_stackptr-1));
    *(m_stackptr-1)=NULL;
    m_stackptr-=2;
}

void VMState::addTop()
{
    (*(m_stackptr-2))->addVal(*(m_stackptr-1));
    *(m_stackptr-1)=NULL;
    m_stackptr-=2;
}

void VMState::subTop()
{
    (*(m_stackptr-2))->subVal(*(m_stackptr-1));
    *(m_stackptr-1)=NULL;
    m_stackptr-=2;
}

void VMState::mulTop()
{
    (*(m_stackptr-2))->mulVal(*(m_stackptr-1));
    *(m_stackptr-1)=NULL;
    m_stackptr-=2;
}

void VMState::divTop()
{
    (*(m_stackptr-2))->divVal(*(m_stackptr-1));
    *(m_stackptr-1)=NULL;
    m_stackptr-=2;
}

void VMState::pushglobal(Value**& globtable, int i)
{
    if (globtable == NULL) {
      globtable = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*m_globalloc);
      for(int i=0;i<m_globalloc;i++) { //TMP HACK
          globtable[i]=new Value(0,NULL);
      }
    }

    push(globtable[i]);
}

void VMState::createglobal(char* modid, int i)
{
    cerr << "Do not run this function again" << endl;
    exit(1);
//     Value** mglobs;
//     if (m_globs.find(modid)==m_globs.end()) {
//    mglobs = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*m_globalloc);
//    for(int i=0;i<m_globalloc;i++) { //TMP HACK
//        mglobs[i]=new Value(0,NULL);
//    }
//    m_globs[modid]=mglobs;
//     }
//     else {
//    mglobs = m_globs[modid];
//     }
//     if (i>=m_globalloc)
//     {
//    Value** newglobs = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*m_globalloc*2);
//    for(int i=0;i<m_globalloc;i++)
//        newglobs[i]=mglobs[i];
//    mglobs=newglobs;
//    m_globalloc*=2;
//    m_globs[modid]=mglobs;
//     }
}

void VMState::newjmp_buf()
{
    jmp_buf* b = new jmp_buf[1];
    m_except_stack.push(b);
//    stackdata *s = new stackdata();
//    s->data = valstack;
//    s->size = stacksize;
    m_stack_stack.push(m_stackptr);

//    cout << "Inside " << except_stack.size() << " tries" << endl;
}

void VMState::kaya_throw(char* msg,int code)
{
    push(mkstr(msg));
    push(mkint((void*)code));
    push(new Value((void*)(new Exception(this)),exceptiontable));
    throw_ex();
}

void VMState::throw_ex()
{
    longjmp(*(m_except_stack.top()),2);
}

jmp_buf* VMState::top_ex()
{
    return m_except_stack.top();
}

void VMState::tried()
{
    delete m_except_stack.top(); 
    m_except_stack.pop(); 
    m_stack_stack.pop();
}

void VMState::restore()
{
    m_stackptr = m_stack_stack.top();
}

void VMState::getindex()
{
    int idx = doPop()->getInt();
    Value* array = doPop();
    Value* el = array->lookup(this,idx);
    push(el);
}

Value* VMState::mkstr(char* str)
{
    return new Value((void*)(new String(str)),stringtable);
}

Value* VMState::mkint(void* i)
{
    return new Value(i,inttable);
}

Generated by  Doxygen 1.6.0   Back to index