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

ValueFuns.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 "Heap.h"
#include "ValueFuns.h"
#include "stdfuns.h"
#include "Closure.h"

FunTable* inttable = new IntTable();
FunTable* stringtable = new StringTable();
FunTable* fntable = new FnTable();
FunTable* arraytable = new ArrayTable();
FunTable* uniontable = new UnionTable();
FunTable* exceptiontable = new ExceptionTable();
FunTable* realtable = new RealTable();

/// Functions on int

Value* IntTable::eq(Value* x, Value* y)
{
    return new Value((void*)(x->getInt()==y->getInt()),inttable);
}

Value* IntTable::cmp(Value* x, Value* y)
{
    return new Value((void*)(x->getInt()-y->getInt()),inttable);
}

Value* IntTable::copy(Value* x)
{
    return new Value((void*)(x->getInt()),inttable);
}

Value* IntTable::marshal(VMState* vm,vector<Value*>& done,Value* x, int id)
{
    Value* v = new Value(NULL,stringtable);
    char buf[50];
    sprintf(buf,"[%d]I[%d]",id,x->getInt());
    v->setString(new String(buf));
    return v;
}

Value* IntTable::hash(Value* x)
{
    return new Value((void*)(x->getInt()),inttable);
}

/// Functions on String

Value* StringTable::eq(Value* x, Value* y)
{
    return new Value((void*)(x->getString()->eq(y->getString())),inttable);
}

Value* StringTable::cmp(Value* x, Value* y)
{
    return new Value((void*)(x->getString()->cmp(y->getString())),inttable);
}

Value* StringTable::copy(Value* x)
{
    return MKSTR(x->getString()->getVal());
}

Value* StringTable::marshal(VMState* vm,vector<Value*>& done,Value* x, int id)
{
    Value* v = new Value(NULL,stringtable);
    String* s = x->getString();
    char *buf = (char*)(GC_MALLOC(sizeof(char)*(s->length()+16)));
    sprintf(buf,"[%d]S[[%d]%s]",id,s->length(),s->getVal());
    v->setString(new String(buf));
    return v;
}

Value* StringTable::hash(Value* x)
{
    return new Value((void*)x->getString()->hash(),inttable);
}

/// Functions on closures

Value* FnTable::eq(Value* x, Value* y)
{
    return new Value((void*)(x->getFunc()->eq(y->getFunc())),inttable);
}

/// This is probably quite meaningless
Value* FnTable::cmp(Value* x, Value* y)
{
    return new Value((void*)((int)(x->getRaw())-(int)(y->getRaw())),inttable);
//    kaya_throw("Can't compare closures sensibly",1);
//    return new Value(0,inttable);
}

Value* FnTable::copy(Value* x)
{
    return new Value((void*)(x->getFunc()->copy()),fntable);
}

Value* FnTable::marshal(VMState* vm,vector<Value*>& done,Value* x, int id)
{
    // Check for circles.
    int idx;
    vector<Value*>::iterator it = done.begin();
    for(idx=0;it!=done.end();++it,++idx) {
      if ((*it)==x) {
          // Already done it, just spit out a reference to it.
          char buf[20];
          sprintf(buf,"[%d]C[%d]",id,idx);
          return new Value(new String(buf),stringtable);
      }
    }
    idx = done.size();
    done.push_back(x);

    Closure *c = x->getFunc();
    char buf[20];
    sprintf(buf,"[%d]F[[%d]",id,idx);
    String* mclos = new String(buf);
    char cfnid[50];
    sprintf(cfnid,"[%d][%d]",c->getFnID(),c->getNumArgs());
    mclos->append(new String(cfnid));
    Value** cargs = c->getArgs();

    for(int i=0;i<c->getNumArgs();i++) {
      char* el = funtable_marshal_aux(vm,done,cargs[i],id);
      mclos->append(new String(el));
    }
    mclos->append(new String("]"));
    return new Value(mclos,stringtable);
//    vm->kaya_throw("Can't marshal closures sensibly",1);
//    return new Value(new String("<<closure>>"),stringtable);
}

Value* FnTable::hash(Value* x)
{
    // FIXME: Do this. Not sure functions will hash sensibly.
    return 0;
}

/// Functions on Reals

Value* RealTable::eq(Value* x, Value* y)
{
    return new Value((void*)(x->getRaw()==y->getRaw()),inttable);
}

Value* RealTable::cmp(Value* x, Value* y)
{
    double xv = x->getReal();
    double yv = y->getReal();
    int r;   
    if (yv>xv) r=-1;
    else if (yv==xv) r=0;
    else r=1;
    return new Value((void*)r,inttable);
}

Value* RealTable::copy(Value* x)
{
    double xv = x->getReal();
    Value* v=new Value(NULL,realtable);
    v->setReal(xv);
    return v;
}

Value* RealTable::marshal(VMState* vm,vector<Value*>& done,Value* x, int id)
{
    Value* v = new Value(NULL,stringtable);
    char buf[255];
    sprintf(buf,"[%d]R[%e]",id,x->getReal());
    v->setString(new String(buf));
    return v;
}

Value* RealTable::hash(Value* x)
{
    vector<Value*> done;
    Value* s = marshal(NULL,done,x,0);
    return new Value((void*)s->getString()->hash(),inttable);
}

/// Functions on Arrays

Value* ArrayTable::eq(Value* x, Value* y)
{
    return new Value((void*)(x->getArray()->eq(y->getArray())),inttable);
}

Value* ArrayTable::cmp(Value* x, Value* y)
{
    return new Value((void*)(x->getArray()->cmp(y->getArray())),inttable);
}

Value* ArrayTable::copy(Value* x)
{
    return new Value(x->getArray()->copy(),arraytable);
}

Value* ArrayTable::marshal(VMState* vm,vector<Value*>& done,Value* x, int id)
{
    // Check for circles.
    int idx;
    vector<Value*>::iterator it = done.begin();
    for(idx=0;it!=done.end();++it,++idx) {
      if ((*it)==x) {
          // Already done it, just spit out a reference to it.
          char buf[20];
          sprintf(buf,"[%d]C[%d]",id,idx);
          return new Value(new String(buf),stringtable);
      }
    }
    idx = done.size();
    done.push_back(x);

    Array* v = x->getArray();
    char buf[20];
    sprintf(buf,"[%d]A[[%d]",id,idx);
    String* marray = new String(buf);
    for(int i=0;i<v->size();i++) {
      char* el = funtable_marshal_aux(vm,done,v->lookup(i),id);
      marray->append(new String(el));
    }
    marray->append(new String("]"));
    return new Value(marray,stringtable);
}

Value* ArrayTable::hash(Value* x)
{
    // FIXME: Do this.
    return 0;
}

/// Functions on Unions

Value* UnionTable::eq(Value* x, Value* y)
{
    return new Value((void*)(x->getUnion()->eq(y->getUnion())),inttable);
}

Value* UnionTable::cmp(Value* x, Value* y)
{
    return new Value((void*)(x->getUnion()->cmp(y->getUnion())),inttable);
}

Value* UnionTable::copy(Value* x)
{
    return new Value(x->getUnion()->copy(),uniontable);
}

Value* UnionTable::marshal(VMState* vm,vector<Value*>& done,Value* x, int id)
{
    // Check for circles.
    int idx;
    vector<Value*>::iterator it = done.begin();
    for(idx=0;it!=done.end();++it,++idx) {
      if ((*it)==x) {
          // Already done it, just spit out a reference to it.
          char buf[20];
          sprintf(buf,"[%d]C[%d]",id,idx);
          return new Value(new String(buf),stringtable);
      }
    }
    idx = done.size();
    done.push_back(x);

    Union *u = x->getUnion();
    char buf[20];
    sprintf(buf,"[%d]U[[%d]",id,idx);
    String* munion = new String(buf);
    char utag[50];
    sprintf(utag,"[%d][%d]",u->tag,u->arity);
    munion->append(new String(utag));

    for(int i=0;i<u->arity;i++) {
      char* el = funtable_marshal_aux(vm,done,u->args[i],id);
      munion->append(new String(el));
    }
    munion->append(new String("]"));
    return new Value(munion,stringtable);
}

Value* UnionTable::hash(Value* x)
{
    return 0;
}


/// Functions on Exceptions

Value* ExceptionTable::eq(Value* x, Value* y)
{
    return new Value((void*)(x->getExcept()->eq(y->getExcept())),inttable);
}

Value* ExceptionTable::cmp(Value* x, Value* y)
{
    return new Value((void*)(x->getExcept()->cmp(y->getExcept())),inttable);
}

Value* ExceptionTable::copy(Value* x)
{
    // No point since they're immutable
    return x;
}

Value* ExceptionTable::marshal(VMState* vm,vector<Value*>& done,Value* x, int id)
{
    vm->kaya_throw("Can't marshal exceptions sensibly",1);
    return new Value(new String("<<exception>>"),stringtable);
}

Value* ExceptionTable::hash(Value* x)
{
    return 0;
}


Generated by  Doxygen 1.6.0   Back to index