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

Heap.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 <gc/new_gc_alloc.h>

#include <iostream>
#include "Heap.h"
#include <stdio.h>
#include <assert.h>
#include "ValueFuns.h"
#include "stdfuns.h"
#include "Array.h"
#include "VMState.h"
#include "Closure.h"

//extern int stacksize;
//extern int stackalloc;


Value::Value(void* ptr, FunTable* ft):m_val(ptr),m_funtable(ft)
{
//    cout << "Created a value " << this << endl;
}

String* Value::getString()
{
    /// TODO - throw if it's not a string..
    if (m_val!=NULL)
      return (String*)m_val;
    else
      return new String("");
}

Exception* Value::getExcept()
{
    /// TODO - throw if it's not an exception.
    if (m_val!=NULL)
      return (Exception*)m_val;
    else {
      assert(false);
      return NULL;
    }
}

void Value::runClosure(VMState* vm)
{
//    cout << m_val << endl;
    ((Closure*)m_val)->run(vm);
//    ((func)m_val)(vm);
}

Array* Value::getArray()
{
    /// TODO - throw if it's not an array.
    if (m_val!=NULL)
      return (Array*)m_val;
    else
      return new Array();
}

Union* Value::getUnion()
{
    /// TODO - throw if it's not a union.
    if (m_val!=NULL)
      return (Union*)m_val;
    assert(false);
    return NULL; // Can't happen.
}

void Value::int2str()
{
    int v=getInt();
    char buf[50]; // *Ick*
    sprintf(buf,"%d",v);
    setString(new String(buf));
}

void Value::real2str()
{
    double v=getReal();
    char buf[100]; // *Ick*
    sprintf(buf,"%g",v);
    setString(new String(buf));
    m_funtable = stringtable;
}

void Value::str2int()
{
    String* s=getString();
    int val=(int)(strtol(s->getVal(),NULL,10));
    setInt(val);
    m_funtable = inttable;
}

void Value::str2real()
{
    String* s=getString();
    double val=strtod(s->getVal(),NULL);
    setReal(val);
    m_funtable = realtable;
}

void Value::chr2str()
{
    char v=(char)getInt();
    setString(new String(v));
    m_funtable = stringtable;
}

void Value::bool2str()
{
    int v=getInt();
    if (v==1) { setString(new String("true")); }
    else { setString(new String("false")); }
}

void Value::str2chr()
{
    assert(false); // Makes no sense!
}

void Value::int2real()
{
    int v=getInt();
    setReal((double)v);
    m_funtable = realtable;
}

void Value::real2int()
{
    double v=getReal();
    setInt((int)v);
    m_funtable = inttable;
}

void Value::setInt(int i)
{
    m_val=(void*)i;
    m_funtable = inttable;
}

void Value::setReal(double v)
{
    m_val=(void*)(new Real(v));
    m_funtable = realtable;
}

void Value::setFunc(Closure* f)
{
    m_val=(void*)f;
    m_funtable = fntable;
}

void Value::setString(String* str)
{
    m_val=(void*)str;
    m_funtable = stringtable;
}

void Value::setArray(Array* a)
{
    m_val=(void*)a;
    m_funtable = arraytable;
}

void Value::readString()
{
    char buf[255];
    fgets(buf,255,stdin);
    char *loc = strchr(buf,'\n');
    *loc = '\0';
    setString(new String(buf));
}

void Value::readInt()
{
    int v;
    scanf("%d",&v);
    setInt(v);
}

/*
void Value::setIdxPtr(Value* p,unsigned i)
{
//    cout << "Setting " << this << " to " << p->m_val << endl;
    Value* current=this;
    for(unsigned x=0;x<i;x++)
    {
      --stacksize;
      int idx = valstack[stacksize]->getInt();
//    int idx = stack.back()->getInt();
//    cout << idx << ",";
//    stack.pop_back();
      valstack[stacksize]=0;
      Value* next = current->lookup(idx);
      current = next;
    }
//    cout << endl;
    current->m_val=p->m_val;
    current->m_funtable=p->m_funtable;
}
*/

void Value::project(VMState* vm, int i)
{
    if (vm->topItem()->getType()!=UNION) {
      vm->kaya_throw("Attempt to project from non-Union",1);
    }

    Union* top=(Union*)(vm->topItem()->m_val);
    Value* arg=top->args[i];
    m_val=arg->m_val;
    m_funtable = arg->m_funtable;
}

/*
void Value::makeArray(int i,vector<Value*>& stack)
{
    int size=1;
    for(int x=0;x<i;x++)
    {
      int idx = stack.back()->getInt();
      stack.pop_back();
      size=size*idx;
    }
    m_val=(void*)(new Value*[size]);
    for(int j=0;j<size;j++) {
      ((Value**)m_val)[j] = new Value();
    }
}
*/

Value* Value::lookup(VMState* vm, int i)
{
    if (m_val && getType()!=ARRAY) {
//    cout << m_val << "," << getType() << endl;
      vm->kaya_throw("Attempt to lookup in non-Array",1);
    }
    if (i<0) {
      vm->kaya_throw("Attempt to lookup negative array index",1);
    }

    Array* v = (Array*)m_val;
    if (v==NULL)
    {
      v = new Array();
      m_val=v;
      m_funtable = arraytable;
    }

    if (v->size()<=i) {
      v->expectedSize(i);
      do {
          Value* n = new Value(NULL, inttable);
          v->push_back(n);
      }
      while(v->size()<=i);
    }

    return v->lookup(i);
}

int Value::length()
{
    Array* v = (Array*)m_val;
    if (v==NULL)
    {
      v = new Array();
      m_val=v;
    }
    return v->size();
}

String::String(char* val)
{
    if (val!=NULL) {
      m_alloc = (strlen(val)+10)*2;
      m_str=(char*)GC_MALLOC_ATOMIC(m_alloc*sizeof(char));
      strcpy(m_str,val);
    }
    else {
      m_alloc = 20;
      m_str=(char*)GC_MALLOC_ATOMIC(m_alloc*sizeof(char));
//    strcpy(m_str,"(none)"); // Debugging purposes
      strcpy(m_str,"");
    }
}

String::String(char val)
{
    m_alloc = 10;
    m_str=(char*)GC_MALLOC_ATOMIC(m_alloc*sizeof(char));
    m_str[0]=val;
    m_str[1]='\0';
}

char* String::getVal()
{
    return m_str;
}

int String::length()
{
    return strlen(m_str);
}

char String::getIndex(int i)
{
    return m_str[i];
}

void String::setIndex(int i, char c)
{
    m_str[i]=c;
}

void String::append(String* s)
{
    // reallocation is safe with strings, because there will be no
    // references into the middle.
    if (length()+s->length()>=m_alloc) {
      m_alloc = (length()+s->length()+10)*2;
      char* newstr = (char*)GC_MALLOC_ATOMIC(sizeof(char)*m_alloc);
      strcpy(newstr,m_str);
      m_str=newstr;
    }
    strcat(m_str,s->getVal());
}

bool String::eq(String* s)
{
//    cout << "Comparing " << s->getVal() << " and " << m_str << "." << endl;
    return (strcmp(m_str,s->getVal())==0);
}

int String::cmp(String* s)
{
//    cout << "Comparing " << s->getVal() << " and " << m_str << "." << endl;
    return (strcmp(m_str,s->getVal()));
}

int String::hash()
{
    int hash = 0;
    for(unsigned i=0;i<strlen(m_str);i++) {
      hash = 131*hash+m_str[i];
    }
    return hash;
}

Union::Union(VMState* vm, int t,int ar, bool getargs)
{
    // Make space for the data, then take <arity> items off the stack and
    // put them into the structure.
//    cout << "Making union with tag " << t << " and arity " << ar << endl;

    args = (Value**)GC_MALLOC_UNCOLLECTABLE(sizeof(Value*)*ar);
    if (getargs) {
      for(int i=0;i<ar;i++) {
//        --stacksize;
/// Create a *new* reference, or things break in confusing ways.
          Value* top = vm->topItem();
          args[i]=new Value(top->getRaw(),
                        top->getFunTable());
          vm->doPop();
      }
    }
    tag=t;
    arity=ar;
}

bool Union::eq(Union* x)
{
    if (tag!=x->tag) return false;
    for(int i=0;i<arity;i++)
    {
      if (!funtable_eq(args[i],x->args[i])) { return false; }
    }
    return true;
}

int Union::cmp(Union* x)
{
    if (tag<x->tag) return -1;
    if (tag>x->tag) return 1;

    for(int i=0;i<arity;i++)
    {
      int cmp = funtable_compare(args[i],x->args[i]);
      if (cmp!=0) return cmp;
    }
    return 0;
}

Union* Union::copy()
{
    Union* u = new Union(NULL,tag,arity,false);
    for(int i=0;i<arity;i++) {
      Value* ai = funtable_copy(args[i]);
      u->args[i]=ai;
    }
    return u;
}

Exception::Exception(VMState* vm)
{
    Value* codeval = vm->doPop();
    Value* errval = vm->doPop();
    code = codeval->getInt();
    err = errval->getString();
}

void Exception::show()
{
    cout << err->getVal() << " (error code " << code << ")" << endl;
}

bool Exception::eq(Exception* x)
{
    /*   cout << "Comparing..." << endl;
    show();
    x->show();

    cout << ((err->eq(x->err)) && (code==x->code)) << endl;*/
    return (err->eq(x->err)) && (code==x->code);
}

int Exception::cmp(Exception* x)
{
    return (code-x->code);
}

Generated by  Doxygen 1.6.0   Back to index