<p>含有js的页面</p>
<script>
-function f()
+
+function P(x)
{
- document.write(arguments.length);
+ this.x = x;
}
-f("hello", "world");
+var a = create P(1);
+
+document.write(a.x);
</script>
#include"abc_html.h"
+static char* js_days[] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+static char* js_mons[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+int64_t abc_js_date()
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+}
+
+void abc_js_date_toString(char* s, int max, int64_t msec)
+{
+ struct tm tm;
+
+ msec /= 1000;
+
+ localtime_r(&msec, &tm);
+
+ int t0 = msec % (24 * 3600);
+ int t1 = tm.tm_hour * 3600 + tm.tm_min * 60 + tm.tm_sec;
+
+ snprintf(s, max, "%s, %s %02d %d %02d:%02d:%02d GMT+%02d00",
+ js_days[tm.tm_wday],
+ js_mons[tm.tm_mon],
+ tm.tm_mday,
+ tm.tm_year + 1900,
+ tm.tm_hour,
+ tm.tm_min,
+ tm.tm_sec,
+ (t1 - t0) / 3600);
+// strftime(s, max, "%A, %Y-%m-%d %T GMT%z", &tm);
+}
+
int abc_html_write(abc_html_t* html, const char* s)
{
abc_char_t* c;
uint32_t vargs_flag:1;
uint32_t void_flag :1;
uint32_t call_flag :1;
+ uint32_t init_flag :1;
uint32_t vla_flag :1;
uint32_t js_flag :1;
uint32_t this_done :1; // set when node is a function call() & its 'this' pointer is set
+ uint32_t js_flag :1; // set when for js obj type
uint32_t semi_flag :1; // set when followed by a ';'
};
if (!f->node.define_flag)
continue;
+ if (strcmp(f->node.w->text->data, "P"))
+ continue;
+
printf("\n");
scf_logi("------- %s() ------\n", f->node.w->text->data);
return 0;
}
-static int _optimize_js_array_bb(scf_ast_t* ast, scf_basic_block_t* bb, scf_list_t* bb_list_head)
+static int __js_ref_obj(scf_ast_t* ast, scf_3ac_code_t** pc, scf_node_t* obj)
+{
+ scf_3ac_code_t* c;
+ scf_variable_t* v;
+ scf_function_t* f = NULL;
+ scf_type_t* t = NULL;
+ scf_node_t* pf;
+
+ int ret = scf_ast_find_global_function(&f, ast, "scf__auto_ref");
+ if (ret < 0)
+ return ret;
+
+ ret = scf_ast_find_type_type(&t, ast, SCF_FUNCTION_PTR);
+ if (ret < 0)
+ return ret;
+
+ v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 1, 1, f);
+ if (!v)
+ return -ENOMEM;
+ v->const_literal_flag = 1;
+
+ pf = scf_node_alloc(NULL, v->type, v);
+ scf_variable_free(v);
+ v = NULL;
+ if (!pf)
+ return -ENOMEM;
+
+ scf_node_t* srcs[2] = {pf, obj};
+
+ c = scf_3ac_code_NN(SCF_OP_CALL, NULL, 0, srcs, 2);
+ if (!c) {
+ scf_node_free(pf);
+ return -ENOMEM;
+ }
+
+ *pc = c;
+ return 0;
+}
+
+static int _optimize_js_array_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t* bb, scf_list_t* bb_list_head)
{
scf_3ac_operand_t* base;
scf_3ac_operand_t* index;
scf_3ac_code_t* c2;
scf_variable_t* v;
scf_node_t* array;
+ scf_node_t* node;
scf_type_t* Object = NULL;
scf_list_t* l;
if (ret < 0)
return ret;
- c2->basic_block = c->basic_block;
+ c2->basic_block = c->basic_block;
+ c2->basic_block->call_flag = 1;
assert(scf_list_prev(&c->list) != scf_list_sentinel(&bb->code_list_head));
scf_list_add_tail(scf_list_prev(&c->list), &c2->list);
+
+ if (f->js_flag && scf_type_is_assign_array_index(c->op->type)) {
+ base = c->srcs->data[3];
+ node = base->node;
+
+ while (SCF_OP_EXPR == node->type)
+ node = node->nodes[0];
+
+ v = _scf_operand_get(node);
+
+ if (v->arg_flag) {
+ c2 = NULL;
+ ret = __js_ref_obj(ast, &c2, node);
+ if (ret < 0)
+ return ret;
+
+ c2->basic_block = c->basic_block;
+ c2->basic_block->call_flag = 1;
+
+ scf_list_add_tail(scf_list_prev(&c->list), &c2->list);
+ }
+ }
}
}
}
if (bb->jmp_flag || bb->end_flag || bb->cmp_flag)
continue;
- int ret = _optimize_js_array_bb(ast, bb, bb_list_head);
+ int ret = _optimize_js_array_bb(ast, f, bb, bb_list_head);
if (ret < 0)
return ret;
}
int abc_html_write_i(Object* html, int64_t i);
int abc_html_write_d(Object* html, double d);
+int64_t abc_js_date();
+void abc_js_date_toString(char* s, int max, int64_t msec);
+
enum {
JS_Undef,
JS_Number,
JS_String,
JS_Object,
+ JS_Date,
+ JS_Boolean,
};
struct Object
// p.x --> p.members[x]
char* str;
double d;
+ int64_t i64;
+
+ int __init(Object* this)
+ {
+ this->type = JS_Object;
+ return 0;
+ }
int __init(Object* this, double d)
{
return 0;
}
+ Object* Boolean(Object* this)
+ {
+ Object* res = create Object();
+ if (!res)
+ return NULL;
+
+ res->i64 = 0;
+ res->type = JS_Boolean;
+ return res;
+ }
+
+ Object* Boolean(Object* this, int64_t i)
+ {
+ Object* res = create Object();
+ if (!res)
+ return NULL;
+
+ res->i64 = i;
+ res->type = JS_Boolean;
+ return res;
+ }
+
+ Object* Boolean(Object* this, Object* that)
+ {
+ Object* res = create Object();
+ if (!res)
+ return NULL;
+
+ switch (that->type) {
+ case JS_Number:
+ if (0.0 == that->d)
+ res->i64 = 0;
+ else
+ res->i64 = 1;
+ break;
+
+ case JS_String:
+ if ('\0' == that->str[0])
+ res->i64 = 0;
+ else
+ res->i64 = 1;
+ break;
+
+ case JS_Boolean:
+ res->i64 = that->i64;
+ break;
+
+ case JS_Object:
+ if (that)
+ res->i64 = 0;
+ else
+ res->i64 = 1;
+ break;
+ default:
+ res->i64 = 0;
+ break;
+ };
+
+ res->type = JS_Boolean;
+ return res;
+ }
+
+ Object* Date(Object* this)
+ {
+ Object* res = create Object(0);
+ if (!res)
+ return NULL;
+
+ res->i64 = abc_js_date();
+ res->type = JS_Date;
+ return res;
+ }
+
const char* toString(Object* this)
{
char* p;
type = this->type;
switch (type) {
+ case JS_Boolean:
+ s = scf__auto_malloc(8);
+ if (!s)
+ return NULL;
+
+ if (this->i64)
+ sprintf(s, "true");
+ else
+ sprintf(s, "false");
+ break;
+
case JS_Number:
s = scf__auto_malloc(128);
if (!s)
memcpy(s, p, len + 1);
break;
+ case JS_Date:
+ s = scf__auto_malloc(128);
+ if (!s)
+ return NULL;
+
+ abc_js_date_toString(s, 127, this->i64);
+ break;
default:
p = "undefined";
len = strlen(p);
int printf(const char* fmt, ...);
int snprintf(char* buf, uintptr_t size, const char* fmt, ...);
+int sprintf (char* buf, const char* fmt, ...);
int rand();
void srand(uint32_t seed);
scf_variable_t* v = dn->var;
if (v && v->w)
- scf_logw("dn: %#lx, v_%d/%s/%#lx\n", 0xffff & (uintptr_t)dn, v->w->line, v->w->text->data, 0xffff & (uintptr_t)v);
+ scf_logd("dn: %#lx, v_%d/%s/%#lx\n", 0xffff & (uintptr_t)dn, v->w->line, v->w->text->data, 0xffff & (uintptr_t)v);
else
- scf_logw("dn: %#lx, v_%#lx\n", 0xffff & (uintptr_t)dn, 0xffff & (uintptr_t)v);
+ scf_logd("dn: %#lx, v_%#lx\n", 0xffff & (uintptr_t)dn, 0xffff & (uintptr_t)v);
break;
}
}
int i;
int j;
- scf_logi("bytes: %d\n", bytes);
+ scf_logd("bytes: %d\n", bytes);
assert(c->rcg);
if (scf_ast_find_type_type(&pt, ast, SCF_FUNCTION_PTR) < 0)
return SCF_DFA_ERROR;
+ int ret = scf_ast_find_type(&Object, ast, "Object");
+ if (ret < 0)
+ return SCF_DFA_ERROR;
+
assert(pt);
assert(op);
dfa_identity_t* id = scf_stack_top(d->current_identities);
if (id && id->identity) {
- scf_logi("ast->current_block: %p, js_type: %d\n", ast->current_block, ast->current_block->node.type);
- int ret = scf_ast_find_function(&f, ast, id->identity->text->data);
+ scf_logd("ast->current_block: %p, js_type: %d\n", ast->current_block, ast->current_block->node.type);
+ ret = scf_ast_find_function(&f, ast, id->identity->text->data);
if (ret < 0)
return SCF_DFA_ERROR;
+ if (!f)
+ f = scf_scope_find_function(Object->scope, id->identity->text->data);
+
if (f) {
scf_logd("f: %p, %s\n", f, f->node.w->text->data);
return SCF_DFA_ERROR;
}
} else {
- ret = scf_ast_find_type(&Object, ast, "Object");
- if (ret < 0)
- return SCF_DFA_ERROR;
-
if (Object->type != var_pf->type) {
scf_loge("invalid function ptr\n");
return SCF_DFA_ERROR;
return 0;
}
-static int _call_add_obj(scf_ast_t* ast, scf_lex_word_t* w, scf_node_t* call, scf_expr_t* e, scf_type_t* Object)
+int _call_add_obj(scf_ast_t* ast, scf_lex_word_t* w, scf_node_t* call, scf_expr_t* e, scf_type_t* Object)
{
scf_variable_t* v = NULL;
scf_expr_t* e2;
} create_module_data_t;
+int _call_add_obj(scf_ast_t* ast, scf_lex_word_t* w, scf_node_t* call, scf_expr_t* e, scf_type_t* Object);
+
static int _create_is_create(scf_dfa_t* dfa, void* word)
{
scf_lex_word_t* w = word;
return SCF_LEX_WORD_KEY_CREATE == w->type;
}
+static int __js_init_func(scf_ast_t* ast, scf_function_t* f)
+{
+ scf_variable_t* this = scf_scope_find_variable(f->scope, "this");
+ scf_variable_t* that = NULL;
+ scf_variable_t* pf = NULL;
+ scf_type_t* Object = NULL;
+ scf_type_t* pt = NULL;
+ scf_node_t* node;
+ scf_node_t* assign;
+ scf_node_t* create;
+ scf_node_t* _return;
+ scf_expr_t* e;
+ scf_block_t* b;
+
+ if (scf_ast_find_type_type(&pt, ast, SCF_FUNCTION_PTR) < 0)
+ return SCF_DFA_ERROR;
+
+ if (scf_ast_find_type(&Object, ast, "Object") < 0)
+ return SCF_DFA_ERROR;
+
+ that = SCF_VAR_ALLOC_BY_TYPE(this->w, Object, 1, 1, NULL);
+ if (!that)
+ return -ENOMEM;
+ that->member_flag = 1;
+ that->arg_flag = 1;
+ this->arg_flag = 0;
+
+ memcpy(that->w->text->data, "that", 4);
+ f->argv->data[0] = that;
+ scf_scope_push_var(f->scope, that);
+
+ // this = create Object()
+ // add 'this'
+ node = scf_node_alloc(NULL, this->type, this);
+ if (!node)
+ return -ENOMEM;
+
+ b = scf_block_alloc_cstr("multi_rets");
+ if (!b) {
+ scf_node_free(node);
+ return -ENOMEM;
+ }
+
+ int ret = scf_node_add_child((scf_node_t*)b, node);
+ if (ret < 0) {
+ scf_node_free(node);
+ scf_block_free(b);
+ return ret;
+ }
+
+ // add '='
+ assign = scf_node_alloc(this->w, SCF_OP_ASSIGN, NULL);
+ if (!assign) {
+ scf_block_free(b);
+ return -ENOMEM;
+ }
+
+ ret = scf_node_add_child(assign, (scf_node_t*)b);
+ if (ret < 0) {
+ scf_node_free(assign);
+ scf_block_free(b);
+ return ret;
+ }
+
+ // add 'create'
+ create = scf_node_alloc(this->w, SCF_OP_CREATE, NULL);
+ if (!create) {
+ scf_node_free(assign);
+ return -ENOMEM;
+ }
+
+ ret = scf_node_add_child(assign, create);
+ if (ret < 0) {
+ scf_node_free(create);
+ scf_node_free(assign);
+ return ret;
+ }
+
+ // add 'Object()'
+ pf = SCF_VAR_ALLOC_BY_TYPE(Object->w, pt, 1, 1, NULL);
+ if (!pf) {
+ scf_node_free(assign);
+ return -ENOMEM;
+ }
+ pf->const_literal_flag = 1;
+
+ node = scf_node_alloc(NULL, pf->type, pf);
+ scf_variable_free(pf);
+ pf = NULL;
+ if (!node) {
+ scf_node_free(assign);
+ return -ENOMEM;
+ }
+
+ ret = scf_node_add_child(create, node);
+ if (ret < 0) {
+ scf_node_free(node);
+ scf_node_free(assign);
+ return ret;
+ }
+
+ e = scf_expr_alloc();
+ if (!e)
+ return -ENOMEM;
+
+ ret = scf_node_add_child(e, assign);
+ if (ret < 0) {
+ scf_node_free(assign);
+ scf_expr_free(e);
+ return ret;
+ }
+
+ ret = scf_node_add_child((scf_node_t*)f, e);
+ if (ret < 0) {
+ scf_expr_free(e);
+ return ret;
+ }
+
+ int i;
+ for (i = f->node.nb_nodes - 2; i >= 0; i--)
+ f->node.nodes[i + 1] = f->node.nodes[i];
+ f->node.nodes[0] = e;
+ e = NULL;
+
+ // return this
+ e = scf_expr_alloc();
+ if (!e)
+ return -ENOMEM;
+
+ node = scf_node_alloc(NULL, this->type, this);
+ if (!node) {
+ scf_expr_free(e);
+ return -ENOMEM;
+ }
+
+ ret = scf_node_add_child(e, node);
+ if (ret < 0) {
+ scf_node_free(node);
+ scf_expr_free(e);
+ return ret;
+ }
+
+ _return = scf_node_alloc(this->w, SCF_OP_RETURN, NULL);
+ if (!_return) {
+ scf_expr_free(e);
+ return -ENOMEM;
+ }
+
+ ret = scf_node_add_child(_return, e);
+ if (ret < 0) {
+ scf_expr_free(e);
+ scf_node_free(_return);
+ return ret;
+ }
+
+ ret = scf_node_add_child((scf_node_t*)f, _return);
+ if (ret < 0) {
+ scf_node_free(_return);
+ return ret;
+ }
+
+ return 0;
+}
+
static int _create_action_lp_stat(scf_dfa_t* dfa, scf_vector_t* words, void* data)
{
dfa_data_t* d = data;
scf_parse_t* parse = dfa->priv;
dfa_data_t* d = data;
scf_lex_word_t* w = words->data[words->size - 1];
+ scf_function_t* f = NULL;
create_module_data_t* md = d->module_datas[dfa_module_create.index];
scf_type_t* t = NULL;
return SCF_DFA_ERROR;
}
+ if (d->current_var && strcmp(t->name->data, "Object")) {
+ d->current_var->js_type = t->type;
+ scf_logw("type '%s', t->type: %d, d->current_var: %s, type: %d, js_type: %d\n",
+ t->name->data, t->type, d->current_var->w->text->data, d->current_var->type, d->current_var->js_type);
+ }
+
if (scf_ast_find_type_type(&pt, parse->ast, SCF_FUNCTION_PTR) < 0)
return SCF_DFA_ERROR;
assert(pt);
SCF_CHECK_ERROR(!var, SCF_DFA_ERROR, "var '%s' alloc failed\n", w->text->data);
var->const_literal_flag = 1;
+ if (scf_ast_find_function(&f, parse->ast, w->text->data) < 0)
+ return SCF_DFA_ERROR;
+
+ if (f && f->js_flag) {
+ t->node.js_flag = 1;
+ md->create->js_flag = 1;
+
+ if (!f->init_flag) {
+ if (__js_init_func(parse->ast, f) < 0)
+ return SCF_DFA_ERROR;
+
+ f->init_flag = 1;
+ }
+
+ var->func_ptr = f;
+ }
+
scf_node_t* node = scf_node_alloc(NULL, var->type, var);
SCF_CHECK_ERROR(!node, SCF_DFA_ERROR, "node alloc failed\n");
static int _create_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
{
- scf_parse_t* parse = dfa->priv;
- dfa_data_t* d = data;
- scf_lex_word_t* w = words->data[words->size - 1];
- create_module_data_t* md = d->module_datas[dfa_module_create.index];
+ scf_parse_t* parse = dfa->priv;
+ dfa_data_t* d = data;
+ scf_lex_word_t* w = words->data[words->size - 1];
+ create_module_data_t* md = d->module_datas[dfa_module_create.index];
+ scf_type_t* Object = NULL;
md->nb_rps++;
assert(md->nb_rps == md->nb_lps);
if (d->expr) {
+ if (md->create->js_flag) {
+ int ret = scf_ast_find_type(&Object, parse->ast, "Object");
+ if (ret < 0)
+ return ret;
+
+ ret = _call_add_obj(parse->ast, w, md->create, d->expr, Object);
+ if (ret < 0)
+ return ret;
+ }
+
int ret = scf_node_add_child(md->create, d->expr);
d->expr = NULL;
SCF_CHECK_ERROR(ret < 0, SCF_DFA_ERROR, "node add child failed\n");
d->expr = md->parent_expr;
d->expr_local_flag--;
+ if (md->create->js_flag)
+ md->create->type = SCF_OP_CALL;
+
if (d->expr) {
int ret = scf_expr_add_node(d->expr, md->create);
SCF_CHECK_ERROR(ret < 0, SCF_DFA_ERROR, "expr add child failed\n");
static int _create_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* data)
{
- scf_parse_t* parse = dfa->priv;
- dfa_data_t* d = data;
- scf_lex_word_t* w = words->data[words->size - 1];
- create_module_data_t* md = d->module_datas[dfa_module_create.index];
+ scf_parse_t* parse = dfa->priv;
+ dfa_data_t* d = data;
+ scf_lex_word_t* w = words->data[words->size - 1];
+ create_module_data_t* md = d->module_datas[dfa_module_create.index];
+ scf_type_t* Object = NULL;
SCF_CHECK_ERROR(!d->expr, SCF_DFA_ERROR, "\n");
+ if (md->create->js_flag) {
+ int ret = scf_ast_find_type(&Object, parse->ast, "Object");
+ if (ret < 0)
+ return ret;
+
+ ret = _call_add_obj(parse->ast, w, md->create, d->expr, Object);
+ if (ret < 0)
+ return ret;
+ }
+
int ret = scf_node_add_child(md->create, d->expr);
d->expr = NULL;
SCF_CHECK_ERROR(ret < 0, SCF_DFA_ERROR, "node add child failed\n");
scf_type_t* t = NULL;
scf_type_t* t2 = NULL;
scf_function_t* f = NULL;
+ scf_block_t* b = NULL;
dfa_identity_t* id = scf_stack_pop(d->current_identities);
scf_lex_word_t* w;
if (scf_ast_find_type_type(&t, parse->ast, md->current_var->js_type) < 0)
return SCF_DFA_ERROR;
+ if (!strcmp(t->name->data, "Object")) {
+ if (strcmp(md->current_var->w->text->data, "this") || !d->current_function)
+ return SCF_DFA_ERROR;
+
+ f = d->current_function;
+
+ b = (scf_block_t*)f->node.parent;
+ assert(b->node.file_flag);
+
+ t = scf_type_alloc(f->node.w, f->node.w->text->data, SCF_STRUCT + parse->ast->nb_structs, 0);
+ if (!t) {
+ scf_loge("\n");
+ return SCF_DFA_ERROR;
+ }
+
+ t->scope = scf_scope_alloc(f->node.w, "class");
+
+ parse->ast->nb_structs++;
+ t->node.class_flag = 1;
+ scf_scope_push_type(b->scope, t);
+ scf_node_add_child((scf_node_t*)b, (scf_node_t*)t);
+
+ md->current_var->js_type = t->type;
+
+ scf_logi("md->current_var->js_type: %d, %s\n", t->type, t->name->data);
+ }
+
t2 = NULL;
if (scf_ast_find_type_type(&t2, parse->ast, SCF_VAR_VAR) < 0)
return SCF_DFA_ERROR;
dfa_identity_t* id = scf_stack_top(d->current_identities);
if (id && id->identity) {
-
- scf_variable_t* v = NULL;
- scf_function_t* f = NULL;
-
- if (scf_ast_find_variable(&v, parse->ast, id->identity->text->data) < 0)
- return SCF_DFA_ERROR;
-
- if (!v) {
- scf_logw("'%s' not var\n", id->identity->text->data);
-
- if (scf_ast_find_function(&f, parse->ast, id->identity->text->data) < 0)
- return SCF_DFA_ERROR;
-
- if (!f) {
- scf_logw("'%s' not function\n", id->identity->text->data);
- return SCF_DFA_NEXT_SYNTAX;
- }
- }
-
if (_expr_add_var(parse, d) < 0) {
scf_loge("expr add var error\n");
return SCF_DFA_ERROR;
for (i = parent->nb_nodes - 2; i >= 0; i--) {
ret = parent->nodes[i];
- if (ret->semi_flag)
+ if (ret->semi_flag || SCF_OP_EXPR != ret->type)
break;
if (b->node.nb_nodes >= nb_rets - 1)
scf_variable_t* v0 = _scf_operand_get(nodes[0]); \
scf_variable_t* v1 = _scf_operand_get(nodes[1]); \
\
- if (scf_variable_float(v0) || scf_variable_float(v1)) { \
+ } while (0)
+// if (scf_variable_float(v0) || scf_variable_float(v1)) { \
scf_loge("float type can't cmp equal\n"); \
return -EINVAL; \
} \
- } while (0)
CMPEQ_CHECK_FLOAT();
scf_variable_t* v = f->rets->data[0];
scf_type_t* t = NULL;
- scf_logi("v: %p, f->rets->size: %d\n", v, f->rets->size);
+ scf_logd("v: %p, f->rets->size: %d\n", v, f->rets->size);
ret = scf_ast_find_type_type(&t, parse->ast, v->type);
if (ret < 0)
}
assert(scf_list_empty(&h));
- scf_basic_block_print_list(&f->basic_block_list_head);
+// scf_basic_block_print_list(&f->basic_block_list_head);
}
int ret = scf_optimize(parse->ast, functions);