-/* ast.c
+/* expr.c
Extension module for the rfxswf library.
Part of the swftools package.
code_t*c=0;\
classinfo_t*t=0;
+#define EVAL_HEADER_LEFTRIGHT \
+ constant_t left = n->child[0]->type->eval(n->child[0]);\
+ constant_t right = n->child[1]->type->eval(n->child[1]);\
+ constant_t r; \
+ if(left.type==CONSTANT_UNKNOWN || right.type==CONSTANT_UNKNOWN) {\
+ r.type = CONSTANT_UNKNOWN;return r; \
+ }
+
+
#define RET \
typedcode_t r; \
r.c = c; \
static classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, nodetype_t*t)
{
- if(!type1 || !type2)
- return registry_getanytype();
- if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2))
- return registry_getanytype();
+ if(t == &node_plus) {
+ if((TYPE_IS_XMLLIST(type1) || TYPE_IS_XML(type1)) &&
+ (TYPE_IS_XMLLIST(type2) || TYPE_IS_XML(type2)))
+ return TYPE_OBJECT;
+ if(BOTH_INT(type1, type2))
+ return TYPE_INT;
+ if(IS_NUMBER_OR_INT(type1) && IS_NUMBER_OR_INT(type2))
+ return TYPE_NUMBER;
+ if(TYPE_IS_DATE(type1) || TYPE_IS_DATE(type2))
+ return TYPE_OBJECT;
+ if(TYPE_IS_STRING(type1) || TYPE_IS_STRING(type2)) {
+ /* depending on where the strings come from, the result type
+ of an "add" might be an object or a string, depending on the
+ verifier's mood. So basically we just don't know the type. */
+ return TYPE_VOID;
+ }
+ if(TYPE_IS_ANY(type1) || TYPE_IS_ANY(type2))
+ return TYPE_ANY;
+ return TYPE_OBJECT; // e.g. array+array = object
+ }
+
if(type1 == type2)
return type1;
- return registry_getanytype();
-}
-static char is_getlocal(code_t*c)
-{
- if(!c || c->prev || c->next)
- return 0;
- return(c->opcode == OPCODE_GETLOCAL
- || c->opcode == OPCODE_GETLOCAL_0
- || c->opcode == OPCODE_GETLOCAL_1
- || c->opcode == OPCODE_GETLOCAL_2
- || c->opcode == OPCODE_GETLOCAL_3);
+ return TYPE_ANY;
}
static int getlocalnr(code_t*c)
{
write->opcode = OPCODE_SETPROPERTY;
multiname_t*m = (multiname_t*)r->data[0];
write->data[0] = multiname_clone(m);
- if(m->type == QNAME || m->type == MULTINAME) {
+ if(m->type == QNAME || m->type == MULTINAME ||
+ m->type == QNAMEA || m->type == MULTINAMEA) {
if(!justassign) {
prefix = abc_dup(prefix); // we need the object, too
}
use_temp_var = 1;
- } else if(m->type == MULTINAMEL) {
+ } else if(m->type == MULTINAMEL || m->type == MULTINAMELA ||
+ m->type == RTQNAME || m->type == RTQNAMEA) {
if(!justassign) {
/* dupping two values on the stack requires 5 operations and one register-
couldn't adobe just have given us a dup2? */
return c;
}
+typedcode_t push_constant(constant_t*v)
+{
+ typedcode_t t;
+ switch(v->type) {
+ case CONSTANT_INT: t.c = abc_pushint(0, v->i);t.t = TYPE_INT;break;
+ case CONSTANT_UINT: t.c = abc_pushuint(0, v->u);t.t = TYPE_UINT;break;
+ case CONSTANT_FLOAT: t.c = abc_pushdouble(0, v->f);t.t = TYPE_FLOAT;break;
+ case CONSTANT_TRUE: t.c = abc_pushtrue(0);t.t = TYPE_BOOLEAN;break;
+ case CONSTANT_FALSE: t.c = abc_pushfalse(0);t.t = TYPE_BOOLEAN;break;
+ case CONSTANT_STRING: t.c = abc_pushstring2(0, v->s);t.t = TYPE_STRING;break;
+ case CONSTANT_NULL: t.c = abc_pushnull(0);t.t = TYPE_NULL;break;
+ case CONSTANT_UNDEFINED: t.c = abc_pushundefined(0);t.t = TYPE_ANY;break;
+ case CONSTANT_NAMESPACE:
+ case CONSTANT_NAMESPACE_PACKAGE:
+ case CONSTANT_NAMESPACE_PACKAGEINTERNAL:
+ case CONSTANT_NAMESPACE_PROTECTED:
+ case CONSTANT_NAMESPACE_EXPLICIT:
+ case CONSTANT_NAMESPACE_STATICPROTECTED:
+ case CONSTANT_NAMESPACE_PRIVATE:
+ t.c = abc_pushnamespace(0, v->ns);t.t = TYPE_NAMESPACE;break;
+ default:
+ syntaxerror("internal error: bad constant");
+ }
+ return t;
+}
+
code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to);
+int constant_to_int(constant_t*c)
+{
+ switch(c->type) {
+ case CONSTANT_INT: return c->i;
+ case CONSTANT_UINT: return (int)c->u;
+ case CONSTANT_FLOAT: return c->f;
+ case CONSTANT_TRUE: return 1;
+ case CONSTANT_FALSE: return 0;
+ case CONSTANT_STRING: return atoi(c->s->str);
+ default: syntaxerror("can't convert this constant to an integer");
+ }
+}
+
+double constant_to_float(constant_t*c)
+{
+ switch(c->type) {
+ case CONSTANT_INT: return (double)c->i;
+ case CONSTANT_UINT: return (double)c->u;
+ case CONSTANT_FLOAT: return c->f;
+ case CONSTANT_TRUE: return (double)1;
+ case CONSTANT_FALSE: return (double)0;
+ case CONSTANT_STRING: return atof(c->s->str);
+ default: syntaxerror("can't convert this constant to a float");
+ }
+}
+
// -------------------------- x + y -----------------------------------
typedcode_t node_plus_write(node_t*n)
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_plus_eval(node_t*n)
+{
+ EVAL_HEADER_LEFTRIGHT;
+ char left_int = left.type == CONSTANT_INT || left.type == CONSTANT_UINT;
+ if(left_int && (right.type == CONSTANT_INT || right.type == CONSTANT_UINT)) {
+ int i = constant_to_int(&left) + constant_to_int(&right);
+ r.type = CONSTANT_INT;
+ r.i = i;
+ } else if(left_int && right.type == CONSTANT_FLOAT) {
+ double f = constant_to_int(&left) + constant_to_float(&right);
+ r.type = CONSTANT_FLOAT;
+ r.f = f;
+ } else if(left.type == CONSTANT_STRING) {
+ char*add = constant_tostring(&right);
+ int l1 = left.s->len;
+ int l2 = strlen(add);
+ char*s = malloc(l1+l2+1);
+ memcpy(s, left.s->str, l1);
+ memcpy(s+l1, add, l2);
+ s[l1+l2]=0;
+ r.type = CONSTANT_STRING;
+ r.s = malloc(sizeof(string_t));
+ r.s->str = s;
+ r.s->len = l1+l2;
+ free(add);
+ } else {
+ r.type = CONSTANT_UNKNOWN;
+ }
+ return r;
+}
nodetype_t node_plus =
{
name:"plus",
flags:NODE_HAS_CHILDREN,
+eval:node_plus_eval,
write:node_plus_write,
read:node_plus_read,
exec:node_plus_exec,
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_minus_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_minus =
{
name:"minus",
flags:NODE_HAS_CHILDREN,
+eval: node_minus_eval,
write: node_minus_write,
read: node_minus_read,
exec: node_minus_exec
}
return c;
}
+constant_t node_lplusplus_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_lplusplus =
{
name: "lplusplus",
flags:NODE_HAS_CHILDREN,
+eval: node_lplusplus_eval,
write: node_lplusplus_write,
read: node_lplusplus_read,
exec: node_lplusplus_exec
}
return c;
}
+constant_t node_lminusminus_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_lminusminus =
{
name: "lminusminus",
flags:NODE_HAS_CHILDREN,
+eval: node_lminusminus_eval,
write: node_lminusminus_write,
read: node_lminusminus_read,
exec: node_lminusminus_exec
}
return c;
}
+constant_t node_rplusplus_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_rplusplus =
{
name: "rplusplus",
flags:NODE_HAS_CHILDREN,
+eval: node_rplusplus_eval,
write: node_rplusplus_write,
read: node_rplusplus_read,
exec: node_rplusplus_exec
}
return c;
}
+constant_t node_rminusminus_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_rminusminus =
{
name: "rminusminus",
flags:NODE_HAS_CHILDREN,
+eval: node_rminusminus_eval,
write: node_rminusminus_write,
read: node_rminusminus_read,
exec: node_rminusminus_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_multiply_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_multiply =
{
name: "multiply",
flags:NODE_HAS_CHILDREN,
+eval: node_multiply_eval,
write: node_multiply_write,
read: node_multiply_read,
exec: node_multiply_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_div_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_div =
{
name: "div",
flags:NODE_HAS_CHILDREN,
+eval: node_div_eval,
write: node_div_write,
read: node_div_read,
exec: node_div_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_mod_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_mod =
{
name: "mod",
flags:NODE_HAS_CHILDREN,
+eval: node_mod_eval,
write: node_mod_write,
read: node_mod_read,
exec: node_mod_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_lt_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_lt =
{
name: "lt",
flags:NODE_HAS_CHILDREN,
+eval: node_lt_eval,
write: node_lt_write,
read: node_lt_read,
exec: node_lt_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_gt_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_gt =
{
name: "gt",
flags:NODE_HAS_CHILDREN,
+eval: node_gt_eval,
write: node_gt_write,
read: node_gt_read,
exec: node_gt_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_le_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_le = //<=
{
name: "le",
flags:NODE_HAS_CHILDREN,
+eval: node_le_eval,
write: node_le_write,
read: node_le_read,
exec: node_le_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_ge_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_ge = //>=
{
name: "ge",
flags:NODE_HAS_CHILDREN,
+eval: node_ge_eval,
write: node_ge_write,
read: node_ge_read,
exec: node_ge_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_eqeq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_eqeq = //==
{
name: "eqeq",
flags:NODE_HAS_CHILDREN,
+eval: node_eqeq_eval,
write: node_eqeq_write,
read: node_eqeq_read,
exec: node_eqeq_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_eqeqeq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_eqeqeq = //===
{
name: "eqeqeq",
flags:NODE_HAS_CHILDREN,
+eval: node_eqeqeq_eval,
write: node_eqeqeq_write,
read: node_eqeqeq_read,
exec: node_eqeqeq_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_noteqeq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_noteqeq = //!==
{
name: "noteqeq",
flags:NODE_HAS_CHILDREN,
+eval: node_noteqeq_eval,
write: node_noteqeq_write,
read: node_noteqeq_read,
exec: node_noteqeq_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_noteq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_noteq = //!=
{
name: "noteq",
flags:NODE_HAS_CHILDREN,
+eval: node_noteq_eval,
write: node_noteq_write,
read: node_noteq_read,
exec: node_noteq_exec
jmp->branch = label;
return c;
}
+constant_t node_oror_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_oror = //||
{
name: "oror",
flags:NODE_HAS_CHILDREN,
+eval: node_oror_eval,
write: node_oror_write,
read: node_oror_read,
exec: node_oror_exec
jmp->branch = label;
return c;
}
+constant_t node_andand_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_andand = //&&
{
name: "andand",
flags:NODE_HAS_CHILDREN,
+eval: node_andand_eval,
write: node_andand_write,
read: node_andand_read,
exec: node_andand_exec
EXEC_HEADER_ONE;
return x;
}
+constant_t node_not_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_not =
{
name: "not",
flags:NODE_HAS_CHILDREN,
+eval: node_not_eval,
write: node_not_write,
read: node_not_read,
exec: node_not_exec
EXEC_HEADER_ONE;
return x;
}
+constant_t node_bitnot_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_bitnot =
{
name: "bitnot",
flags:NODE_HAS_CHILDREN,
+eval: node_bitnot_eval,
write: node_bitnot_write,
read: node_bitnot_read,
exec: node_bitnot_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_bitand_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_bitand =
{
name: "bitand",
flags:NODE_HAS_CHILDREN,
+eval: node_bitand_eval,
write: node_bitand_write,
read: node_bitand_read,
exec: node_bitand_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_bitxor_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_bitxor =
{
name: "bitxor",
flags:NODE_HAS_CHILDREN,
+eval: node_bitxor_eval,
write: node_bitxor_write,
read: node_bitxor_read,
exec: node_bitxor_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_bitor_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_bitor =
{
name: "bitor",
flags:NODE_HAS_CHILDREN,
+eval: node_bitor_eval,
write: node_bitor_write,
read: node_bitor_read,
exec: node_bitor_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_shr_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_shr = //>>
{
name: "shr",
flags:NODE_HAS_CHILDREN,
+eval: node_shr_eval,
write: node_shr_write,
read: node_shr_read,
exec: node_shr_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_shl_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_shl = //<<
{
name: "shl",
flags:NODE_HAS_CHILDREN,
+eval: node_shl_eval,
write: node_shl_write,
read: node_shl_read,
exec: node_shl_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_ushr_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_ushr = //>>>
{
name: "ushr",
flags:NODE_HAS_CHILDREN,
+eval: node_ushr_eval,
write: node_ushr_write,
read: node_ushr_read,
exec: node_ushr_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_in_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_in = //in
{
name: "in",
flags:NODE_HAS_CHILDREN,
+eval: node_in_eval,
write: node_in_write,
read: node_in_read,
exec: node_in_exec
READ_HEADER_LEFTRIGHT;
c = code_append(left.c, right.c);
c = abc_astypelate(c);
- t = TYPE_ANY;
+ if(TYPE_IS_CLASS(right.t) && right.t->data) {
+ t = (classinfo_t*)right.t->data;
+ } else {
+ t = TYPE_ANY;
+ }
RET;
}
code_t* node_as_exec(node_t*n)
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_as_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_as = //as
{
name: "as",
flags:NODE_HAS_CHILDREN,
+eval: node_as_eval,
write: node_as_write,
read: node_as_read,
exec: node_as_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_instanceof_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_instanceof = //instanceof
{
name: "instanceof",
flags:NODE_HAS_CHILDREN,
+eval: node_instanceof_eval,
write: node_instanceof_write,
read: node_instanceof_read,
exec: node_instanceof_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_is_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_is = //is
{
name: "is",
flags:NODE_HAS_CHILDREN,
+eval: node_is_eval,
write: node_is_write,
read: node_is_read,
exec: node_is_exec
EXEC_HEADER_LEFTRIGHT;
return code_append(left, right);
}
+constant_t node_arraylookup_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_arraylookup =
{
name: "arraylookup",
flags:NODE_HAS_CHILDREN,
+eval: node_arraylookup_eval,
write: node_arraylookup_write,
read: node_arraylookup_read,
exec: node_arraylookup_exec
EXEC_HEADER_ONE;
return x;
}
+constant_t node_typeof_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_typeof = //typeof
{
name: "typeof",
flags:NODE_HAS_CHILDREN,
+eval: node_typeof_eval,
write: node_typeof_write,
read: node_typeof_read,
exec: node_typeof_exec
EXEC_HEADER_ONE;
return x;
}
+constant_t node_void_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_void = //void
{
name: "void",
flags:NODE_HAS_CHILDREN,
+eval: node_void_eval,
write: node_void_write,
read: node_void_read,
exec: node_void_exec
EXEC_HEADER_ONE;
return x;
}
+constant_t node_neg_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_neg = //-
{
name: "neg",
flags:NODE_HAS_CHILDREN,
+eval: node_neg_eval,
write: node_neg_write,
read: node_neg_read,
exec: node_neg_exec
c = converttype(c, f, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_muleq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_muleq =
{
name: "muleq",
flags:NODE_HAS_CHILDREN,
+eval: node_muleq_eval,
write: node_muleq_write,
read: node_muleq_read,
exec: node_muleq_exec
c = converttype(c, TYPE_NUMBER, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_modeq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_modeq = //%=
{
name: "modeq",
flags:NODE_HAS_CHILDREN,
+eval: node_modeq_eval,
write: node_modeq_write,
read: node_modeq_read,
exec: node_modeq_exec
c = converttype(c, TYPE_INT, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_shleq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_shleq = //<<=
{
name: "shleq",
flags:NODE_HAS_CHILDREN,
+eval: node_shleq_eval,
write: node_shleq_write,
read: node_shleq_read,
exec: node_shleq_exec
c = converttype(c, TYPE_INT, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_shreq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_shreq = //>>=
{
name: "shreq",
flags:NODE_HAS_CHILDREN,
+eval: node_shreq_eval,
write: node_shreq_write,
read: node_shreq_read,
exec: node_shreq_exec
c = converttype(c, TYPE_UINT, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_ushreq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_ushreq = //>>>=
{
name: "ushreq",
flags:NODE_HAS_CHILDREN,
+eval: node_ushreq_eval,
write: node_ushreq_write,
read: node_ushreq_read,
exec: node_ushreq_exec
c = converttype(c, TYPE_NUMBER, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_diveq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_diveq =
{
name: "diveq",
flags:NODE_HAS_CHILDREN,
+eval: node_diveq_eval,
write: node_diveq_write,
read: node_diveq_read,
exec: node_diveq_exec
c = converttype(c, TYPE_INT, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_bitoreq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_bitoreq = //|=
{
name: "bitoreq",
flags:NODE_HAS_CHILDREN,
+eval: node_bitoreq_eval,
write: node_bitoreq_write,
read: node_bitoreq_read,
exec: node_bitoreq_exec
c = converttype(c, TYPE_INT, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_bitxoreq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_bitxoreq = //^=
{
name: "bitxoreq",
flags:NODE_HAS_CHILDREN,
+eval: node_bitxoreq_eval,
write: node_bitxoreq_write,
read: node_bitxoreq_read,
exec: node_bitxoreq_exec
c = converttype(c, TYPE_INT, left.t);
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_bitandeq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_bitandeq = //^=
{
name: "bitandeq",
flags:NODE_HAS_CHILDREN,
+eval: node_bitandeq_eval,
write: node_bitandeq_write,
read: node_bitandeq_read,
exec: node_bitandeq_exec
c = abc_add_i(c);
} else {
c = abc_add(c);
- c = converttype(c, TYPE_NUMBER, left.t);
+ c = converttype(c, join_types(left.t,right.t,&node_plus), left.t);
}
c = toreadwrite(left.c, c, 0, 0, 1);
t = left.t;
c = abc_add_i(c);
} else {
c = abc_add(c);
- c = converttype(c, TYPE_NUMBER, left.t);
+ c = converttype(c, join_types(left.t,right.t,&node_plus), left.t);
}
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_pluseq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_pluseq = //+=
{
name: "pluseq",
flags:NODE_HAS_CHILDREN,
+eval: node_pluseq_eval,
write: node_pluseq_write,
read: node_pluseq_read,
exec: node_pluseq_exec
}
return toreadwrite(left.c, c, 0, 0, 0);
}
+constant_t node_minuseq_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_minuseq = //-=
{
name: "minuseq",
flags:NODE_HAS_CHILDREN,
+eval: node_minuseq_eval,
write: node_minuseq_write,
read: node_minuseq_read,
exec: node_minuseq_exec
c = converttype(c, right.t, left.t);
return toreadwrite(left.c, c, 1, 0, 0);
}
+constant_t node_assign_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_assign =
{
name: "assign",
flags:NODE_HAS_CHILDREN,
+eval: node_assign_eval,
write: node_assign_write,
read: node_assign_read,
exec: node_assign_exec
c = j2->branch = abc_label(c);
return c;
}
+constant_t node_tenary_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_tenary =
{
name: "tenary",
flags:NODE_HAS_CHILDREN,
+eval: node_tenary_eval,
write: node_tenary_write,
read: node_tenary_read,
exec: node_tenary_exec
}
return c;
}
+constant_t node_comma_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_comma =
{
name: "expr",
flags: NODE_HAS_CHILDREN,
+eval: node_comma_eval,
write: node_comma_write,
read: node_comma_read,
exec: node_comma_exec
code_t* node_new_exec(node_t*n)
{
}
+constant_t node_new_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_new = //new
{
write: node_new_write,
read: node_new_read,
+eval: node_new_eval,
exec: node_new_exec
};
code_t* node_delete_exec(node_t*n)
{
}
+constant_t node_delete_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_delete = //delete
{
write: node_delete_write,
read: node_delete_read,
+eval: node_delete_eval,
exec: node_delete_exec
};
code_t* node_dot_exec(node_t*n)
{
}
+constant_t node_dot_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_dot =
{
write: node_dot_write,
read: node_dot_read,
+eval: node_dot_eval,
exec: node_dot_exec
};
{
}
+constant_t node_dotdot_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_dotdot = //..
{
write: node_dotdot_write,
read: node_dotdot_read,
+eval: node_dotdot_eval,
exec: node_dotdot_exec
};
code_t* node_dotat_exec(node_t*n)
{
}
+constant_t node_dotat_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_dotat = //.@
{
write: node_dotat_write,
read: node_dotat_read,
+eval: node_dotat_eval,
exec: node_dotat_exec
};
code_t* node_dotstar_exec(node_t*n)
{
}
+constant_t node_dotstar_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_dotstar = //.*
{
write: node_dotstar_write,
read: node_dotstar_read,
+eval: node_dotstar_eval,
exec: node_dotstar_exec
};
code_t* node_filter_exec(node_t*n)
{
}
+constant_t node_filter_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_filter = //.(
{
write: node_filter_write,
read: node_filter_read,
+eval: node_filter_eval,
exec: node_filter_exec
};
code_t* node_call_exec(node_t*n)
{
}
+constant_t node_call_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_call = //functioncall
{
write: node_call_write,
read: node_call_read,
+eval: node_call_eval,
exec: node_call_exec
};
code_t* node_at_exec(node_t*n)
{
}
+constant_t node_at_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_at = //@
{
write: node_at_write,
read: node_at_read,
+eval: node_at_eval,
exec: node_at_exec
};
code_t* node_dotns_exec(node_t*n)
{
}
+constant_t node_dotns_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_dotns = //.::
{
write: node_dotns_write,
read: node_dotns_read,
+eval: node_dotns_eval,
exec: node_dotns_exec
};
#endif
case CONSTANT_NAMESPACE_PRIVATE:
c = abc_pushnamespace(0, v->ns);
break;
- default: syntaxerror("invalid constant");
+ case CONSTANT_UNKNOWN:
+ syntaxerror("internal error: invalid constant");
+ default:
+ *(int*)0=0;
+ syntaxerror("invalid constant (%d)", v->type);
+
}
RET;
}
{
return 0;
}
+constant_t node_const_eval(node_t*n)
+{
+ constant_t*c = constant_clone(n->value);
+ constant_t r = *c;
+ free(c); //shallow free
+ return r;
+}
nodetype_t node_const =
{
name: "const",
flags:0,
+eval: node_const_eval,
write: node_const_write,
read: node_const_read,
exec: node_const_exec
typedcode_t node_code_write(node_t*n)
{
- syntaxerror("not implemented yet");
+ typedcode_t t;
+ t.c = 0;
+ int tmp = gettempvar();
+ t.c = abc_setlocal(t.c, tmp);
+ code_t*w = toreadwrite(n->code.c, abc_getlocal(0,tmp), 1, 0, 0);
+ t.c = code_append(t.c, w);
+ t.c = abc_kill(t.c, tmp);
+ n->code.c=0;
+ t.t = n->code.t;
+ return t;
}
typedcode_t node_code_read(node_t*n)
{
- /* TODO: this dup might be unnecessary- n->code.c is only read out once */
typedcode_t t;
- t.c = code_dup(n->code.c);
+ t.c = n->code.c;
+ n->code.c=0;
t.t = n->code.t;
return t;
}
c = cut_last_push(c);
return c;
}
+constant_t node_code_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_code =
{
name: "code",
flags:0,
+eval: node_code_eval,
write: node_code_write,
read: node_code_read,
exec: node_code_exec
};
-// ------------------------ code node ------------------------------
+// ------------------------ dummy node ------------------------------
typedcode_t node_dummy_write(node_t*n)
{
{
typedcode_t t;
t.c = abc_pushundefined(0);
- t.t = 0;
+ t.t = TYPE_ANY;
return t;
}
code_t* node_dummy_exec(node_t*n)
{
return 0;
}
+constant_t node_dummy_eval(node_t*n)
+{
+ constant_t r;r.type=CONSTANT_UNKNOWN;return r;
+}
nodetype_t node_dummy =
{
name: "dummy",
flags:0,
+eval: node_dummy_eval,
write: node_dummy_write,
read: node_dummy_read,
exec: node_dummy_exec
return n;
}
+node_t* mkstringnode(const char*s)
+{
+ return mkconstnode(constant_new_string(s));
+}
+
+node_t* mkaddnode(node_t*n1, node_t*n2)
+{
+ return mknode2(&node_plus, n1, n2);
+}
+
node_t* multinode_extend(node_t*n, node_t*add)
{
n->child = realloc(n->child, (n->num_children+1)*sizeof(node_t*));
void node_free(node_t*n)
{
int t;
- if(n->type == &node_const) {
- constant_free(n->value);n->value = 0;
- }
- else if(n->type == &node_code) {
- code_free(n->code.c);n->code.c = 0;
- }
- else for(t=0;t<n->num_children;t++) {
+ if(n->type == &node_code) {
+ if(n->code.c) {
+ code_free(n->code.c);n->code.c = 0;
+ }
+ } else if(n->type == &node_const) {
+ /* keep, this is not our reference */
+ } else for(t=0;t<n->num_children;t++) {
node_free(n->child[t]);n->child[t] = 0;
}
free(n);
typedcode_t node_read(node_t*n)
{
- typedcode_t t = n->type->read(n);
+ constant_t c = n->type->eval(n);
+ if(c.type == CONSTANT_UNKNOWN) {
+ typedcode_t t = n->type->read(n);
+ node_free(n);
+ return t;
+ } else {
+ typedcode_t t = push_constant(&c);
+ node_free(n);
+ return t;
+ }
+}
+typedcode_t node_write(node_t*n)
+{
+ typedcode_t t = n->type->write(n);
node_free(n);
return t;
}
node_free(n);
return c;
}
+constant_t node_eval(node_t*n)
+{
+ constant_t c = n->type->eval(n);
+ node_free(n);
+ return c;
+}
/*
|
fprintf(fi, "%s%s (%s)\n", p1, n->type->name, s);
free(s);
} else if(n->type == &node_code) {
- fprintf(fi, "%s%s\n", p1, n->type->name);
+ fprintf(fi, "%s%s (%s)\n", p1, n->type->name, n->code.t?n->code.t->name:"*");
code_dump2(n->code.c, 0, 0, (char*)p2, fi);
} else {
fprintf(fi, "%s%s\n", p1, n->type->name);
void node_dump(node_t*n)
{
- printf("---------------------------VVVV\n");
+ printf("------------VVVV---------------\n");
node_dump2(n,"","",stdout);
- printf("---------------------------^^^^\n");
+ printf("-------------------------------\n");
}