static naRef f_setsize(naContext c, naRef me, int argc, naRef* args)
{
if(argc < 2 || !naIsVector(args[0])) ARGERR();
- naVec_setsize(args[0], (int)naNumValue(args[1]).num);
+ naVec_setsize(c, args[0], (int)naNumValue(args[1]).num);
return args[0];
}
if(naIsNil(nlen) || len > naVec_size(v) - start)
len = naVec_size(v) - start;
result = naNewVector(c);
- naVec_setsize(result, len);
+ naVec_setsize(c, result, len);
for(i=0; i<len; i++)
naVec_set(result, i, naVec_get(v, start + i));
return result;
return naStr_substr(naNewString(c), src, start, len);
}
+static naRef f_left(naContext c, naRef me, int argc, naRef* args)
+{
+ int len;
+ naRef src = argc > 0 ? args[0] : naNil();
+ naRef lenr = argc > 1 ? naNumValue(args[1]) : naNil();
+ if(!naIsString(src)) ARGERR();
+ if(!naIsNum(lenr)) ARGERR();
+ len = (int)lenr.num;
+ if(len < 0) len = 0;
+ return naStr_substr(naNewString(c), src, 0, len);
+}
+
+static naRef f_right(naContext c, naRef me, int argc, naRef* args)
+{
+ int len, srclen;
+ naRef src = argc > 0 ? args[0] : naNil();
+ naRef lenr = argc > 1 ? naNumValue(args[1]) : naNil();
+ if(!naIsString(src)) ARGERR();
+ if(!naIsNum(lenr)) ARGERR();
+ srclen = naStr_len(src);
+ len = (int)lenr.num;
+ if (len > srclen) len = srclen;
+ if(len < 0) len = 0;
+ return naStr_substr(naNewString(c), src, srclen - len, len);
+}
+
static naRef f_chr(naContext c, naRef me, int argc, naRef* args)
{
char chr[1];
// that it can be reset if we get a die()/naRethrowError() situation
// later. Right now, the IP on the stack trace is the line of the
// die() call, when it should be this one...
+//
+// FIXME: don't use naCall at all here, we don't need it. Fix up the
+// context stack to tail call the function directly. There's no need
+// for f_call() to live on the C stack at all.
static naRef f_call(naContext c, naRef me, int argc, naRef* args)
{
naContext subc;
callargs = argc > 1 ? args[1] : naNil();
callme = argc > 2 ? args[2] : naNil(); // Might be nil, that's OK
callns = argc > 3 ? args[3] : naNil(); // ditto
- if(!IS_HASH(callme)) callme = naNil();
+ if(!IS_HASH(callme) && !IS_GHOST(callme)) callme = naNil();
if(!IS_HASH(callns)) callns = naNil();
if(argc==0 || !IS_FUNC(args[0]) || (!IS_NIL(callargs) && !IS_VEC(callargs)))
ARGERR();
int start = 0;
if(argc < 2 || !IS_STR(args[0]) || !IS_STR(args[1])) ARGERR();
if(argc > 2) start = (int)(naNumValue(args[2]).num);
- return naNum(find(PTR(args[0]).str->data, PTR(args[0]).str->len,
- PTR(args[1]).str->data, PTR(args[1]).str->len,
+ return naNum(find((void*)naStr_data(args[0]), naStr_len(args[0]),
+ (void*)naStr_data(args[1]), naStr_len(args[1]),
start));
}
qsort(sd.recs, sd.n, sizeof(sd.recs[0]),
(int(*)(const void*,const void*))sortcmp);
out = naNewVector(c);
- naVec_setsize(out, sd.n);
+ naVec_setsize(c, out, sd.n);
for(i=0; i<sd.n; i++)
PTR(out).vec->rec->array[i] = sd.elems[sd.recs[i].i];
naFree(sd.recs);
return out;
}
+static naRef f_id(naContext c, naRef me, int argc, naRef* args)
+{
+ char *t = "unk", buf[64];
+ if(argc != 1 || !IS_REF(args[0]))
+ naRuntimeError(c, "bad/missing argument to id()");
+ if (IS_STR(args[0])) t = "str";
+ else if(IS_VEC(args[0])) t = "vec";
+ else if(IS_HASH(args[0])) t = "hash";
+ else if(IS_CODE(args[0])) t = "code";
+ else if(IS_FUNC(args[0])) t = "func";
+ else if(IS_CCODE(args[0])) t = "ccode";
+ else if(IS_GHOST(args[0])) {
+ naGhostType *gt = PTR(args[0]).ghost->gtype;
+ t = gt->name ? (char*)gt->name : "ghost";
+ }
+ sprintf(buf, "%s:%p", (char*)t, (void*)PTR(args[0]).obj);
+ return NEWCSTR(c, buf);
+}
+
static naCFuncItem funcs[] = {
{ "size", f_size },
{ "keys", f_keys },
{ "streq", f_streq },
{ "cmp", f_cmp },
{ "substr", f_substr },
+ { "left", f_left },
+ { "right", f_right },
{ "chr", f_chr },
{ "contains", f_contains },
{ "typeof", f_typeof },
{ "rand", f_rand },
{ "bind", f_bind },
{ "sort", f_sort },
+ { "id", f_id },
{ 0 }
};