00001 #include <string.h>
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004
00005 #include "nasal.h"
00006 #include "code.h"
00007
00008 void naFree(void* m) { free(m); }
00009 void* naAlloc(int n) { return malloc(n); }
00010 void* naRealloc(void* b, int n) { return realloc(b, n); }
00011 void naBZero(void* m, int n) { memset(m, 0, n); }
00012
00013 void naTempSave(naContext c, naRef r)
00014 {
00015 int i;
00016 if(!IS_OBJ(r)) return;
00017 if(c->ntemps >= c->tempsz) {
00018 struct naObj** newtemps;
00019 c->tempsz *= 2;
00020 newtemps = naAlloc(c->tempsz * sizeof(struct naObj*));
00021 for(i=0; i<c->ntemps; i++)
00022 newtemps[i] = c->temps[i];
00023 naFree(c->temps);
00024 c->temps = newtemps;
00025 }
00026 c->temps[c->ntemps++] = PTR(r).obj;
00027 }
00028
00029 naRef naObj(int type, struct naObj* o)
00030 {
00031 naRef r;
00032 SETPTR(r, o);
00033 o->type = type;
00034 return r;
00035 }
00036
00037 int naTrue(naRef r)
00038 {
00039 if(IS_NIL(r)) return 0;
00040 if(IS_NUM(r)) return r.num != 0;
00041 if(IS_STR(r)) return 1;
00042 return 0;
00043 }
00044
00045 naRef naNumValue(naRef n)
00046 {
00047 double d;
00048 if(IS_NUM(n)) return n;
00049 if(IS_NIL(n)) return naNil();
00050 if(IS_STR(n) && naStr_tonum(n, &d))
00051 return naNum(d);
00052 return naNil();
00053 }
00054
00055 naRef naStringValue(naContext c, naRef r)
00056 {
00057 if(IS_NIL(r) || IS_STR(r)) return r;
00058 if(IS_NUM(r)) {
00059 naRef s = naNewString(c);
00060 naStr_fromnum(s, r.num);
00061 return s;
00062 }
00063 return naNil();
00064 }
00065
00066 naRef naNew(struct Context* c, int type)
00067 {
00068 naRef result;
00069 if(c->nfree[type] == 0)
00070 c->free[type] = naGC_get(&globals->pools[type],
00071 OBJ_CACHE_SZ, &c->nfree[type]);
00072 result = naObj(type, c->free[type][--c->nfree[type]]);
00073 naTempSave(c, result);
00074 return result;
00075 }
00076
00077 naRef naNewString(struct Context* c)
00078 {
00079 naRef s = naNew(c, T_STR);
00080 PTR(s).str->emblen = 0;
00081 PTR(s).str->data.ref.len = 0;
00082 PTR(s).str->data.ref.ptr = 0;
00083 PTR(s).str->hashcode = 0;
00084 return s;
00085 }
00086
00087 naRef naNewVector(struct Context* c)
00088 {
00089 naRef r = naNew(c, T_VEC);
00090 PTR(r).vec->rec = 0;
00091 return r;
00092 }
00093
00094 naRef naNewHash(struct Context* c)
00095 {
00096 naRef r = naNew(c, T_HASH);
00097 PTR(r).hash->rec = 0;
00098 return r;
00099 }
00100
00101 naRef naNewCode(struct Context* c)
00102 {
00103 return naNew(c, T_CODE);
00104 }
00105
00106 naRef naNewCCode(struct Context* c, naCFunction fptr)
00107 {
00108 naRef r = naNew(c, T_CCODE);
00109 PTR(r).ccode->fptr = fptr;
00110 return r;
00111 }
00112
00113 naRef naNewFunc(struct Context* c, naRef code)
00114 {
00115 naRef func = naNew(c, T_FUNC);
00116 PTR(func).func->code = code;
00117 PTR(func).func->namespace = naNil();
00118 PTR(func).func->next = naNil();
00119 return func;
00120 }
00121
00122 naRef naNewGhost(naContext c, naGhostType* type, void* ptr)
00123 {
00124 naRef ghost = naNew(c, T_GHOST);
00125 PTR(ghost).ghost->gtype = type;
00126 PTR(ghost).ghost->ptr = ptr;
00127 return ghost;
00128 }
00129
00130 naGhostType* naGhost_type(naRef ghost)
00131 {
00132 if(!IS_GHOST(ghost)) return 0;
00133 return PTR(ghost).ghost->gtype;
00134 }
00135
00136 void* naGhost_ptr(naRef ghost)
00137 {
00138 if(!IS_GHOST(ghost)) return 0;
00139 return PTR(ghost).ghost->ptr;
00140 }
00141
00142 naRef naNil()
00143 {
00144 naRef r;
00145 SETPTR(r, 0);
00146 return r;
00147 }
00148
00149 naRef naNum(double num)
00150 {
00151 naRef r;
00152 SETNUM(r, num);
00153 return r;
00154 }
00155
00156 int naEqual(naRef a, naRef b)
00157 {
00158 double na=0, nb=0;
00159 if(IS_REF(a) && IS_REF(b) && PTR(a).obj == PTR(b).obj)
00160 return 1;
00161 if(IS_NIL(a) || IS_NIL(b))
00162 return 0;
00163 if(IS_NUM(a) && IS_NUM(b) && a.num == b.num)
00164 return 1;
00165 if(IS_STR(a) && IS_STR(b) && naStr_equal(a, b))
00166 return 1;
00167
00168
00169 if(IS_NUM(a)) { na = a.num; }
00170 else if(!(IS_STR(a) && naStr_tonum(a, &na))) { return 0; }
00171
00172 if(IS_NUM(b)) { nb = b.num; }
00173 else if(!(IS_STR(b) && naStr_tonum(b, &nb))) { return 0; }
00174
00175 return na == nb ? 1 : 0;
00176 }
00177
00178 int naStrEqual(naRef a, naRef b)
00179 {
00180 int i;
00181 char *ap, *bp;
00182 if(!IS_STR(a) || !IS_STR(b) || naStr_len(a) != naStr_len(b))
00183 return 0;
00184 ap = naStr_data(a);
00185 bp = naStr_data(b);
00186 for(i=0; i<naStr_len(a); i++)
00187 if(ap[i] != bp[i])
00188 return 0;
00189 return 1;
00190 }
00191
00192 int naTypeSize(int type)
00193 {
00194 switch(type) {
00195 case T_STR: return sizeof(struct naStr);
00196 case T_VEC: return sizeof(struct naVec);
00197 case T_HASH: return sizeof(struct naHash);
00198 case T_CODE: return sizeof(struct naCode);
00199 case T_FUNC: return sizeof(struct naFunc);
00200 case T_CCODE: return sizeof(struct naCCode);
00201 case T_GHOST: return sizeof(struct naGhost);
00202 };
00203 return 0x7fffffff;
00204 }
00205
00206 int naIsNil(naRef r) { return IS_NIL(r); }
00207 int naIsNum(naRef r) { return IS_NUM(r); }
00208 int naIsString(naRef r) { return IS_STR(r); }
00209 int naIsScalar(naRef r) { return IS_SCALAR(r); }
00210 int naIsVector(naRef r) { return IS_VEC(r); }
00211 int naIsHash(naRef r) { return IS_HASH(r); }
00212 int naIsFunc(naRef r) { return IS_FUNC(r); }
00213 int naIsCode(naRef r) { return IS_CODE(r); }
00214 int naIsCCode(naRef r) { return IS_CCODE(r); }
00215 int naIsGhost(naRef r) { return IS_GHOST(r); }
00216
00217 void naSetUserData(naContext c, void* p) { c->userData = p; }
00218 void* naGetUserData(naContext c)
00219 {
00220 if(c->userData) return c->userData;
00221 return c->callParent ? naGetUserData(c->callParent) : 0;
00222 }
00223
00224 void naAddSym(naContext c, naRef ns, char *sym, naRef val)
00225 {
00226 naRef name = naStr_fromdata(naNewString(c), sym, strlen(sym));
00227 naHash_set(ns, naInternSymbol(name), val);
00228 }
00229
00230 naRef naGenLib(naContext c, naCFuncItem *fns)
00231 {
00232 naRef ns = naNewHash(c);
00233 for(; fns->name; fns++)
00234 naAddSym(c, ns, fns->name, naNewFunc(c, naNewCCode(c, fns->func)));
00235 return ns;
00236 }