From cbdebfda70f002b30cedb4c981102c266b028c81 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Sat, 25 Jan 2014 22:57:01 +0100 Subject: [PATCH] Implement some Array functions. --- js.h | 1 + jsarray.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++- jsrun.c | 6 ++ 3 files changed, 195 insertions(+), 3 deletions(-) diff --git a/js.h b/js.h index d78a795..014c669 100644 --- a/js.h +++ b/js.h @@ -121,6 +121,7 @@ int js_isnumber(js_State *J, int idx); int js_isstring(js_State *J, int idx); int js_isprimitive(js_State *J, int idx); int js_isobject(js_State *J, int idx); +int js_isarray(js_State *J, int idx); int js_iscallable(js_State *J, int idx); int js_isuserdata(js_State *J, const char *tag, int idx); diff --git a/jsarray.c b/jsarray.c index 77a8bc9..a8460b9 100644 --- a/jsarray.c +++ b/jsarray.c @@ -2,8 +2,186 @@ #include "jsvalue.h" #include "jsbuiltin.h" -static int jsB_Array(js_State *J, int argc) { return 0; } -static int jsB_new_Array(js_State *J, int argc) { return 0; } +static int jsB_new_Array(js_State *J, int argc) +{ + int i; + + js_newarray(J); + + if (argc == 1) { + if (js_isnumber(J, 1)) { + js_copy(J, 1); + js_setproperty(J, -2, "length"); + } else { + js_copy(J, 1); + js_setproperty(J, -2, "0"); + } + } else { + char buf[32]; + for (i = 1; i <= argc; ++i) { + sprintf(buf, "%u", i - 1); + js_copy(J, i); + js_setproperty(J, -2, buf); + } + } + return 1; +} + +static int Ap_concat(js_State *J, int argc) +{ + unsigned int n, len, i; + char buf[32]; + + js_newarray(J); + n = 0; + + for (i = 0; i <= argc; i++) { + js_copy(J, i); + if (js_isarray(J, -1)) { + unsigned int k = 0; + + js_getproperty(J, -1, "length"); + len = js_touint32(J, -1); + js_pop(J, 1); + + while (k < len) { + sprintf(buf, "%u", k); + if (js_hasproperty(J, -1, buf)) { + js_getproperty(J, -1, buf); + sprintf(buf, "%u", n); + js_setproperty(J, -3, buf); + } + ++k; + ++n; + } + js_pop(J, 1); + } else { + sprintf(buf, "%u", n); + js_setproperty(J, -2, buf); + ++n; + } + } + + return 1; +} + +static int Ap_join(js_State *J, int argc) +{ + char * volatile out = NULL; + char buf[32]; + const char *r, *sep = ","; + unsigned int seplen, n; + unsigned int k, len; + + js_getproperty(J, 0, "length"); + len = js_touint32(J, -1); + js_pop(J, 1); + + if (argc == 1 && !js_isundefined(J, 1)) { + sep = js_tostring(J, 1); + seplen = strlen(sep); + } + + if (len == 0) { + js_pushliteral(J, ""); + return 1; + } + + if (js_try(J)) { + free(out); + js_throw(J); + } + + n = 1; + for (k = 0; k < len; ++k) { + sprintf(buf, "%u", k); + js_getproperty(J, 0, buf); + if (js_isundefined(J, -1) || js_isnull(J, -1)) + r = ""; + else + r = js_tostring(J, -1); + n += strlen(r); + + if (k == 0) { + out = malloc(n); + strcpy(out, r); + } else { + n += seplen; + out = realloc(out, n); + strcat(out, sep); + strcat(out, r); + } + + js_pop(J, 1); + } + + js_pushstring(J, out); + + js_endtry(J); + free(out); + return 1; +} + + +static int Ap_pop(js_State *J, int argc) +{ + unsigned int n; + char buf[32]; + + js_getproperty(J, 0, "length"); + n = js_touint32(J, -1); + js_pop(J, 1); + + if (n > 0) { + sprintf(buf, "%u", n - 1); + js_getproperty(J, 0, buf); + js_delproperty(J, 0, buf); + js_pushnumber(J, n - 1); + js_setproperty(J, 0, "length"); + } else { + js_pushnumber(J, 0); + js_setproperty(J, 0, "length"); + js_pushundefined(J); + } + return 1; +} + +static int Ap_push(js_State *J, int argc) +{ + unsigned int n; + int i; + char buf[32]; + + js_getproperty(J, 0, "length"); + n = js_touint32(J, -1); + js_pop(J, 1); + + for (i = 1; i <= argc; ++i) { + sprintf(buf, "%u", n); + js_copy(J, i); + js_setproperty(J, 0, buf); + ++n; + } + + js_pushnumber(J, n); + js_setproperty(J, 0, "length"); + + js_pushnumber(J, n); + return 1; +} + +// reverse +// shift +// slice +// sort +// splice +// unshift + +static int Ap_toString(js_State *J, int argc) +{ + js_pop(J, argc); + return Ap_join(J, 0); +} static int A_isArray(js_State *J, int argc) { @@ -19,7 +197,14 @@ static int A_isArray(js_State *J, int argc) void jsB_initarray(js_State *J) { js_pushobject(J, J->Array_prototype); - js_newcconstructor(J, jsB_Array, jsB_new_Array, 1); + { + jsB_propf(J, "toString", Ap_toString, 0); + jsB_propf(J, "concat", Ap_concat, 1); + jsB_propf(J, "join", Ap_join, 1); + jsB_propf(J, "pop", Ap_pop, 0); + jsB_propf(J, "push", Ap_push, 1); + } + js_newcconstructor(J, jsB_new_Array, jsB_new_Array, 1); { /* ECMA-262-5 */ jsB_propf(J, "isArray", A_isArray, 1); diff --git a/jsrun.c b/jsrun.c index ce45232..312285f 100644 --- a/jsrun.c +++ b/jsrun.c @@ -98,6 +98,12 @@ int js_iscallable(js_State *J, int idx) return 0; } +int js_isarray(js_State *J, int idx) +{ + const js_Value *v = stackidx(J, idx); + return v->type == JS_TOBJECT && v->u.object->type == JS_CARRAY; +} + int js_isiterator(js_State *J, int idx) { const js_Value *v = stackidx(J, idx);