RPA Toolkit
implemented break and continue, also added string concatination
authorMartin Stoilov <martin@rpasearch.com>
Wed, 19 Jan 2011 06:43:28 +0000 (22:43 -0800)
committerMartin Stoilov <martin@rpasearch.com>
Wed, 19 Jan 2011 06:43:28 +0000 (22:43 -0800)
rlib/rstring.c
rvm/rvmoperatoradd.c
rvm/rvmoperatoradd.h
rvm/rvmoperatorbin.c
tests/ecma262.rpa
tests/rpagen-test.c

index 68deb16..8be7999 100644 (file)
@@ -192,7 +192,7 @@ void r_string_assign(rstring_t *string, const rstr_t *str)
                string->s.str = (rchar*)r_malloc(str->size + 1);
                if (!string->s.str)
                        return;
-               r_memset(string->s.str, 0, str->size);
+               r_memset(string->s.str, 0, str->size + 1);
                r_memcpy(string->s.str, str->str, str->size);
                string->s.size = str->size;
        }
index f469395..2a36234 100644 (file)
@@ -34,3 +34,27 @@ void rvm_op_add_double(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rdouble op1,
        RVM_STATUS_UPDATE(cpu, RVM_STATUS_Z, !r);
        RVM_STATUS_UPDATE(cpu, RVM_STATUS_N, r < 0.0);
 }
+
+
+void rvm_op_concat_string_string(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+       rstring_t *s1 = (rstring_t *)RVM_REG_GETP(arg1);
+       rstring_t *s2 = (rstring_t *)RVM_REG_GETP(arg2);
+       rstring_t *d = r_string_create_from_rstr(&s1->s);
+       r_string_cat(d, &s2->s);
+
+       rvm_gc_add(cpu->gc, (robject_t*)d);
+       rvm_reg_setstring(res, d);
+}
+
+
+void rvm_op_concat_long_string(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+
+}
+
+
+void rvm_op_concat_string_long(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2)
+{
+
+}
index 96f05a9..4ee3f57 100644 (file)
@@ -11,6 +11,10 @@ extern "C" {
 void rvm_op_add_unsigned(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rword op1, rword op2);
 void rvm_op_add_long(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rlong op1, rlong op2);
 void rvm_op_add_double(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, rdouble op1, rdouble op2);
+void rvm_op_concat_string_string(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2);
+void rvm_op_concat_long_string(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2);
+void rvm_op_concat_string_long(rvmcpu_t *cpu, rushort opid, rvmreg_t *res, const rvmreg_t *arg1, const rvmreg_t *arg2);
+
 
 #ifdef __cplusplus
 }
index f198758..805c303 100644 (file)
@@ -189,6 +189,12 @@ void rvm_op_binary_init(rvm_opmap_t *opmap)
        }
 
        rvm_op_binary_insert(opmap, RVM_OPID_ADD, rvm_op_add_unsigned, rvm_op_add_long, rvm_op_add_double);
+       /*
+        * Overwrite RVM_OPID_ADD for string concatenation
+        */
+       rvm_opmap_set_binary_handler(opmap, RVM_OPID_ADD, rvm_op_concat_string_string, RVM_DTYPE_STRING, RVM_DTYPE_STRING);
+
+
        rvm_op_binary_insert(opmap, RVM_OPID_SUB, rvm_op_sub_unsigned, rvm_op_sub_long, rvm_op_sub_double);
        rvm_op_binary_insert(opmap, RVM_OPID_MUL, rvm_op_mul_unsigned, rvm_op_mul_long, rvm_op_mul_double);
        rvm_op_binary_insert(opmap, RVM_OPID_DIV, rvm_op_div_unsigned, rvm_op_div_long, rvm_op_div_double);
@@ -209,5 +215,4 @@ void rvm_op_binary_init(rvm_opmap_t *opmap)
        rvm_op_binary_insert(opmap, RVM_OPID_LESSEQ, rvm_op_lesseq_unsigned, rvm_op_lesseq_long, rvm_op_lesseq_double);
        rvm_op_binary_insert(opmap, RVM_OPID_GREATER, rvm_op_greater_unsigned, rvm_op_greater_long, rvm_op_greater_double);
        rvm_op_binary_insert(opmap, RVM_OPID_GREATEREQ, rvm_op_greatereq_unsigned, rvm_op_greatereq_long, rvm_op_greatereq_double);
-
 }
index 84e5f17..617c5a5 100644 (file)
@@ -306,14 +306,10 @@ AssignmentOperator                                ::= '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>='
 Expression             ::= <:AssignmentExpression:> ( <S>? ',' <S>? <:AssignmentExpression:> )*
 ExpressionNoIn         ::= <:AssignmentExpressionNoIn:> ( <S>? ',' <S>? <:AssignmentExpressionNoIn:> )*
 
-#Print statement;
-PrintOp                                                        ::= '%'print'%'
-
-BreakOp                                                        ::= 'break'
-BreakStatement                                 ::= <S>? <:BreakOp:> <:SC:>
 
 # 12 Statements
 Statement                                              ::= <:BreakStatement:> |
+                                                                       <:ContinueStatement:> |
                                                                        <:Block:> |
                                                                <:Comment:> |
                                                                <:VariableStatement:> |
@@ -398,6 +394,14 @@ IterationStatement                                         ::= <:IterationWhileOp:> |
 ReturnOp                                               ::= ('return' - 'return' <:IdentifierPart:>) <WhiteSpace>* <:AssignmentExpression:>? (<S>? ';')
 ReturnStatement                                        ::= <:ReturnOp:>
 
+# The Break Statement
+BreakOp                                                        ::= 'break' - 'break' <:IdentifierPart:>
+BreakStatement                                 ::= <S>? <:BreakOp:> <:SC:>
+
+# The Continue Statement
+ContinueOp                                             ::= 'continue' - 'continue' <:IdentifierPart:>
+ContinueStatement                              ::= <S>? <:ContinueOp:> <:SC:>
+
 
 # 13 Function Definition
 FunctionName                                           ::= <:Identifier:>
index 73643c6..3b86d74 100644 (file)
@@ -80,6 +80,7 @@ typedef struct rvm_compiler_s {
        rarray_t *fundecl;
        rarray_t *opcodes;
        rarray_t *codespan;
+       rarray_t *loops;
        rarray_t *varmap;
        rarray_t *stat;
        rvmcpu_t *cpu;
@@ -190,6 +191,7 @@ rvm_compiler_t *rvm_compiler_create(rpa_dbex_handle dbex)
        co->stat = r_array_create(sizeof(rvm_costat_t));
        co->fundecl = r_array_create(sizeof(rvm_fundecl_t));
        co->codespan = r_array_create(sizeof(rvm_codespan_t));
+       co->loops = r_array_create(sizeof(rvm_codespan_t*));
        co->varmap = r_array_create(sizeof(rvm_varmap_t*));
        r_array_push(co->fp, 0, rword);
        co->dbex = dbex;
@@ -209,6 +211,7 @@ void rvm_compiler_destroy(rvm_compiler_t *co)
                r_object_destroy((robject_t*) co->fundecl);
                r_object_destroy((robject_t*) co->codespan);
                r_object_destroy((robject_t*) co->varmap);
+               r_object_destroy((robject_t*) co->loops);
                r_free(co);
        }
 }
@@ -1410,7 +1413,7 @@ int codegen_breakkeyword_callback(const char *name, void *userdata, const char *
 {
        rvm_compiler_t *co = (rvm_compiler_t *)userdata;
        rulong off = rvm_codegen_getcodesize(co->cg);
-       rvm_codespan_t *cs = (rvm_codespan_t *)r_array_lastslot(co->codespan);
+       rvm_codespan_t *cs = (rvm_codespan_t *)r_array_last(co->loops, rvm_codespan_t*);
 
        if (cs->type != RVM_CODESPAN_LOOP) {
                return 0;
@@ -1425,6 +1428,25 @@ int codegen_breakkeyword_callback(const char *name, void *userdata, const char *
 }
 
 
+int codegen_continuekeyword_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
+{
+       rvm_compiler_t *co = (rvm_compiler_t *)userdata;
+       rulong off = rvm_codegen_getcodesize(co->cg);
+       rvm_codespan_t *cs = (rvm_codespan_t *)r_array_last(co->loops, rvm_codespan_t*);
+
+       if (cs->type != RVM_CODESPAN_LOOP) {
+               return 0;
+       }
+
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(rvm_codegen_getcodesize(co->cg) - cs->l3)));
+
+
+       codegen_print_callback(name, userdata, input, size, reason, start, end);
+       codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
+       return size;
+}
+
+
 int codegen_forkeyword_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
 {
        rvm_compiler_t *co = (rvm_compiler_t *)userdata;
@@ -1434,6 +1456,7 @@ int codegen_forkeyword_callback(const char *name, void *userdata, const char *in
        cs.codestart = rvm_codegen_getcodesize(co->cg);
        r_array_add(co->codespan, &cs);
        rvm_scope_push(co->scope);
+       r_array_push(co->loops, r_array_lastslot(co->codespan), rvm_codespan_t*);
 
        codegen_print_callback(name, userdata, input, size, reason, start, end);
        codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
@@ -1511,6 +1534,7 @@ int codegen_iterationforop_callback(const char *name, void *userdata, const char
        rvm_codegen_replaceins(co->cg, cs.l2, rvm_asm(RVM_B, DA, XX, XX, cs.codesize - (cs.l2 - cs.codestart)));        // Re-writing the instruction
 
        rvm_scope_pop(co->scope);
+       r_array_removelast(co->loops);
 
        codegen_print_callback(name, userdata, input, size, reason, start, end);
        codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
@@ -1795,6 +1819,7 @@ void rpagen_load_rules(rpa_dbex_handle dbex, rvm_compiler_t *co)
        rpa_dbex_add_callback_exact(dbex, "ForExpressionIncrementOp", RPA_REASON_END, codegen_forincrementop_callback, co);
        rpa_dbex_add_callback_exact(dbex, "IterationForOp", RPA_REASON_MATCHED, codegen_iterationforop_callback, co);
        rpa_dbex_add_callback_exact(dbex, "BreakOp", RPA_REASON_MATCHED, codegen_breakkeyword_callback, co);
+       rpa_dbex_add_callback_exact(dbex, "ContinueOp", RPA_REASON_MATCHED, codegen_continuekeyword_callback, co);
 
 
        if (verboseinfo)