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

VM.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.
*/

#ifndef WIN32
#include <pthread.h>
#define GC_PTHREADS
#else
#define GC_WIN32_THREADS
#endif
#include <gc/gc_cpp.h>
#include <setjmp.h>

#include <gc/gc_allocator.h>
#include <assert.h>
#include <stack>
#include <iostream>
#include <map>

using namespace std;

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


// Vect valstack;

/*Value** valstack;
map<char*,Value**> globs;
map<int,func> funmap;

int stacksize;
int stackalloc;
int globalloc;

stack<jmp_buf*> except_stack;
stack<int> stack_stack; // Stack state when an exception happens.
*/

//VMState* vm;

VMState* initstack()
{
    return new VMState();
/*    stacksize=0;
    stackalloc=100;
    globalloc=100;
    valstack = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*stackalloc);*/
}

void finish(VMState* vm)
{
    vm->finish();
/*    if (stacksize!=0) {
      cerr << "Warning: Stack size is non-zero (" << stacksize << ")" << endl;
      }*/
}

// Value* doPop()
// {
//     --stacksize;
//     Value* tmp=valstack[stacksize];
//     valstack[stacksize]=NULL;
//     return tmp;
// }

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

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

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

// void push(Value* val)
// {
//     // FIXME: Grow stack if necessary? Might be quite an overhead... maybe 
//     // make it an option.
//     valstack[stacksize] = val;
//     ++stacksize;
// }

// int tag()
// {
// //    cout << "Tag is " << valstack[stacksize-1]->getTag() << endl;
//     return valstack[stacksize-1]->getTag();
// }

// // Value* doPop()
// // {
// //     Value* tmp = valstack.back();
// //     valstack.pop_back();
// //     return tmp;
// // }

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

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

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

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

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

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

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

// void 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 projarg(int i, int t)
// {
//     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 goToIndex()
// {
//     --stacksize;
//     int idx = valstack[stacksize]->getInt();
//     valstack[stacksize-1] = valstack[stacksize-1]->lookup(idx);
// }

// /// Replace the top stack item with the contents of the second stack item.
// void setTop()
// {
//     valstack[stacksize-1]->setPtr(valstack[stacksize-2]);
//     valstack[stacksize-2]=valstack[stacksize-1];
//     stacksize-=2;
// }

// void pushglobal(char* modid, int i)
// {
//     Value** mglobs;
//     if (globs.find(modid)==globs.end()) {
//    mglobs = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*globalloc);
//    for(int i=0;i<globalloc;i++) { //TMP HACK
//        mglobs[i]=new Value(0,NULL);
//    }
//    globs[modid]=mglobs;

// // cout << modid << "," << mglobs << endl;
//     }
//     else {
//    mglobs = globs[modid];
// // cout << modid << "," << mglobs << endl;
//     }
//     push(mglobs[i]);
// //    cout << i << " ," << mglobs[i] << endl;
// }

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

// void newjmp_buf()
// {
//     jmp_buf* b = new jmp_buf[1];
//     except_stack.push(b);
// //    stackdata *s = new stackdata();
// //    s->data = valstack;
// //    s->size = stacksize;
//     stack_stack.push(stacksize);

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

//id kaya_throw(char* msg,int code)
//
//  vm->kaya_throw(msg,code);
//
//     PUSH(MKSTR(msg));
//     PUSH(MKINT(code));
//     MKEXCEPT;
//     THROW;
// }

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

Value* mkstr(wchar_t* str)
{
    return new Value((void*)(new String(str)),KVT_STRING);
}
// shouldn't be needed
Value* mkstr(char* str)
{
  return mkstr(strtowc(str));
}

Value* mkint(void* i)
{
    return new Value(i,KVT_INT);
}

Value* mkarrayval(void* i)
{
    return new Value(i,KVT_ARRAY);
}

/// Maths operators

int intpower(int x, int y)
{
    return (int)pow((double)x,(double)y);
}

double realpower(double x, double y)
{
    return pow(x,y);
}

/// String conversions

wchar_t* strtowc(const char* str) {
  return mkUCS(str);
}

wchar_t chrtowc(const char chr) {
  return *mkUCS(&chr);
}

char* wctostr(const wchar_t* wc) {
  unsigned int len = wcslen(wc)+1;
  char* dest = (char*)GC_MALLOC_ATOMIC(sizeof(char)*(len)*4);  
  mkUTF8(wc,dest,len);
  return dest;
}

// note that even one wchar_t may be bigger than a char...
char wctochr(const wchar_t c) {
  // result is therefore undefined if wchar_t represents something outside 0-127
  return *wctostr(&c);
}

/* These implementations may come in useful later for overloading to do transcoding between single-byte encodings and the UCS wchar_t - CIM
wchar_t* strtowc(const char* str) {
    int sz = strlen(str)*sizeof(wchar_t);
    wchar_t* buf=(wchar_t*)GC_MALLOC(sz);
    mbstate_t *ps = {0};
    mbsrtowcs(buf,&str,strlen(str),ps);
    return buf;
}

wchar_t chrtowc(const char chr) {
  const char* str = &chr;
    int sz = sizeof(wchar_t);
    wchar_t* buf=(wchar_t*)GC_MALLOC(sz);
    mbstate_t *ps = {0};
    mbrtowc(buf,str,strlen(str),ps);
    return *buf;
}

char* wctostr(const wchar_t* wc) {
    int sz = wcslen(wc)*sizeof(char)*MB_CUR_MAX;
    char* buf=(char*)GC_MALLOC(sz);
    mbstate_t *ps = {0};
    wcsrtombs(buf,&wc,wcslen(wc)*MB_CUR_MAX,ps);
    return buf;
}

char wctochr(const wchar_t c)
{
    int sz = sizeof(char)*MB_CUR_MAX;
    char buf[sz];
    mbstate_t *ps = {0};
    wcrtomb(buf,c,ps);
    return buf[0];
}
*/

/* UTF8 mbc constructor based on Jeff Bezanson's public domain code */
void mkUTF8(const wchar_t* raw, char* dest, unsigned int len) {
  //  char* dest = (char*)GC_MALLOC_ATOMIC(sizeof(char)*(1+wcslen(raw))*4);  
  unsigned int dpos = 0;
  for (unsigned int i=0;i<len;) {
    unsigned int ch = (unsigned int)raw[i++];
    if (ch < 0x80) {
      dest[dpos++] = (char)ch;
    } else if (ch < 0x800) {
      dest[dpos++] = (ch>>6) | 0xC0;
      dest[dpos++] = (ch & 0x3F) | 0x80;
    } else if (ch < 0x10000) {
      dest[dpos++] = (ch>>12) | 0xE0;
      dest[dpos++] = ((ch>>6) & 0x3F) | 0x80;
      dest[dpos++] = (ch & 0x3F) | 0x80;
    } else if (ch < 0x200000) {
      dest[dpos++] = (ch>>18) | 0xF0;
      dest[dpos++] = ((ch>>12) & 0x3F) | 0x80;
      dest[dpos++] = ((ch>>6) & 0x3F) | 0x80;
      dest[dpos++] = (ch & 0x3F) | 0x80;
    }
  }
  dest[dpos] = '\0';
}

/* UTF8 mbc unconstructor loosely based on Jeff Bezanson's public domain code */
wchar_t* mkUCS(const char* utf8) {
  int inlen = 0;
  if (utf8 == NULL) {
    inlen = 0;
  } else {
    inlen = strlen(utf8);
  }
  int cpos = 0;
  int dpos = 0;
  // assume it's all single-byte for memory allocation. It usually will be.
  wchar_t* dest = (wchar_t*)GC_MALLOC_ATOMIC(sizeof(wchar_t)*(inlen+1));  
  while (cpos < inlen) {
    int first = (int)utf8[cpos];
    if (first < 128) {
      // single byte character
      dest[dpos++] = (wchar_t)first;
      cpos++;
    } else if (first < 192) {
      // bad continuation character, skip it.
      cpos++;
    } else if (first < 224 && cpos+1 < inlen) {
      // two-byte character
      dest[dpos++] = (wchar_t)((((int)utf8[cpos] & 31) << 6) + (utf8[cpos+1] & 63));
      cpos+=2;
    } else if (first < 240 && cpos+2 < inlen) {
      // three-byte character
      dest[dpos++] = (wchar_t)((((int)utf8[cpos] & 15) << 12) + ((utf8[cpos+1] & 63) << 6) + (utf8[cpos+2] & 63));
      cpos+=3;
    } else if (first < 248 && cpos+3 < inlen) {
      // four-byte character
      dest[dpos++] = (wchar_t)((((int)utf8[cpos] & 7) << 18) + ((utf8[cpos+1] & 63) << 12) + ((utf8[cpos+2] & 63) << 6) + (utf8[cpos+3] & 63));
      cpos+=3;
    } else {
      // start of illegal 5+-byte character? skip it
      cpos++;
    }
  }
  dest[dpos++] = '\0';
  return dest;
}

Generated by  Doxygen 1.6.0   Back to index