diff --git a/jsload.c b/jsload.c index 6988459..4e25c9d 100644 --- a/jsload.c +++ b/jsload.c @@ -5,6 +5,7 @@ static int jsP_loadstring(js_State *J, const char *filename, const char *source) { js_Ast *prog = jsP_parse(J, filename, source); if (prog) { + jsP_foldconstants(J, prog); jsP_pretty(J, prog); jsP_freeparse(J); return 0; diff --git a/jsoptim.c b/jsoptim.c new file mode 100644 index 0000000..f2edd93 --- /dev/null +++ b/jsoptim.c @@ -0,0 +1,86 @@ +#include "js.h" +#include "jsparse.h" + +static inline int i32(double d) +{ + double two32 = 4294967296.0; + double two31 = 2147483648.0; + + if (!isfinite(d) || d == 0) + return 0; + + d = fmod(d, two32); + d = d >= 0 ? floor(d) : ceil(d) + two32; + if (d >= two31) + return d - two32; + else + return d; +} + +static inline unsigned int u32(double d) +{ + return i32(d); +} + +static int N(js_Ast *node, double *r, double x) +{ + node->type = AST_NUMBER; + node->number = x; + node->a = node->b = node->c = node->d = NULL; + *r = x; + return 1; +} + +static int foldnumber(js_Ast *node, double *r) +{ + double x, y, z, w; + int a, b; + + a = node->a ? foldnumber(node->a, &x) : 0; + b = node->b ? foldnumber(node->b, &y) : 0; + if (node->c) foldnumber(node->c, &z); + if (node->d) foldnumber(node->d, &w); + + if (node->type == AST_NUMBER) { + *r = node->number; + return 1; + } + + /* not an expression */ + if (node->c || node->d) + return 0; + + /* binary */ + if (a && b) { + switch (node->type) { + case EXP_MUL: return N(node, r, x * y); + case EXP_DIV: return N(node, r, x / y); + case EXP_MOD: return N(node, r, fmod(x, y)); + case EXP_ADD: return N(node, r, x + y); + case EXP_SUB: return N(node, r, x - y); + case EXP_SHL: return N(node, r, i32(x) << (u32(y) & 0x1F)); + case EXP_SHR: return N(node, r, i32(x) >> (u32(y) & 0x1F)); + case EXP_USHR: return N(node, r, u32(x) >> (u32(y) & 0x1F)); + case EXP_BITAND: return N(node, r, i32(x) & i32(y)); + case EXP_BITXOR: return N(node, r, i32(x) ^ i32(y)); + case EXP_BITOR: return N(node, r, i32(x) | i32(y)); + } + } + + /* unary */ + else if (a) { + switch (node->type) { + case EXP_NEG: return N(node, r, -x); + case EXP_POS: return N(node, r, x); + case EXP_BITNOT: return N(node, r, ~i32(x)); + } + } + + return 0; +} + +void jsP_foldconstants(js_State *J, js_Ast *prog) +{ + double x; + foldnumber(prog, &x); +} diff --git a/jsparse.c b/jsparse.c index e28dc41..4125326 100644 --- a/jsparse.c +++ b/jsparse.c @@ -34,8 +34,8 @@ js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *c, js_A node->b = b; node->c = c; node->d = d; - node->n = 0; - node->s = NULL; + node->number = 0; + node->string = NULL; node->next = J->ast; J->ast = node; @@ -46,14 +46,14 @@ js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *c, js_A js_Ast *jsP_newstrnode(js_State *J, int type, const char *s) { js_Ast *node = jsP_newnode(J, type, 0, 0, 0, 0); - node->s = s; + node->string = s; return node; } js_Ast *jsP_newnumnode(js_State *J, int type, double n) { js_Ast *node = jsP_newnode(J, type, 0, 0, 0, 0); - node->n = n; + node->number = n; return node; } diff --git a/jsparse.h b/jsparse.h index 9e6efbe..07fd9ed 100644 --- a/jsparse.h +++ b/jsparse.h @@ -8,8 +8,8 @@ struct js_Ast int type; int line; js_Ast *a, *b, *c, *d; - double n; - const char *s; + double number; + const char *string; js_Ast *next; /* next in alloc list */ }; @@ -124,6 +124,7 @@ enum js_Ast *jsP_parse(js_State *J, const char *filename, const char *source); void jsP_freeparse(js_State *J); +void jsP_foldconstants(js_State *J, js_Ast *prog); void jsP_pretty(js_State *J, js_Ast *prog); #endif diff --git a/jspretty.c b/jspretty.c index 3475891..75eb461 100644 --- a/jspretty.c +++ b/jspretty.c @@ -165,10 +165,10 @@ static void printbinary(int level, js_Ast *a, js_Ast *b, const char *op) static void printast(js_Ast *n, int level) { switch (n->type) { - case AST_IDENTIFIER: printf("%s", n->s); return; - case AST_NUMBER: printf("%g", n->n); return; - case AST_STRING: printf("'%s'", n->s); return; - case AST_REGEXP: printf("/%s/", n->s); return; + case AST_IDENTIFIER: printf("%s", n->string); return; + case AST_NUMBER: printf("%g", n->number); return; + case AST_STRING: printf("'%s'", n->string); return; + case AST_REGEXP: printf("/%s/", n->string); return; case AST_LIST: putchar('['); printlist(n, level, " ");