mirror of
https://github.com/ccxvii/mujs.git
synced 2026-09-23 16:53:35 +08:00
Add constant folding.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+4
-4
@@ -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, " ");
|
||||
|
||||
Reference in New Issue
Block a user