RPA Toolkit
add RJS function calls.
authorMartin Stoilov <martin@rpasearch.com>
Thu, 5 May 2011 06:19:32 +0000 (23:19 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Thu, 5 May 2011 06:19:32 +0000 (23:19 -0700)
rjs/ecma262.rpa
rjs/rjscompiler.c
rjs/rjscompiler.h
rjs/rjsuids.h
rpa2/rpavm.c
rvm/rvmcpu.c

index 0ead0e9..0bbbe82 100644 (file)
 #!emit FunctionDeclaration
 #!emit FunctionParameter
 #!emit FormalParameterList
-
+#!emit Argument
+#!emit Arguments
+#!emit FunctionCall
+#!emit FunctionCallName
 
 #!uid Program                                          UID_PROGRAM                                             1
 #!uid PostfixExpressionValOp           UID_POSTFIXEXPRESSIONVALOP                      2
 #!uid FunctionDeclaration                      UID_FUNCTIONDECLARATION                         28
 #!uid FunctionParameter                                UID_FUNCTIONPARAMETER                           29
 #!uid FormalParameterList                      UID_FORMALPARAMETERLIST                         30
-
+#!uid CallExpression                           UID_CALLEXPRESSION                                      31
+#!uid FunctionCall                                     UID_FUNCTIONCALL                                        32
+#!uid Argument                                         UID_ARGUMENT                                            33
+#!uid Arguments                                                UID_ARGUMENTS                                           34
 
 # 6 Source Text
 SourceCharacter                        ::= .
@@ -232,16 +238,18 @@ NewExpression                                     ::= <NewArrayExpression> |
                                                                        <NewKeyword> <S>? <NewExpression> |
                                                                        <MemberExpression>
 
-
-CallExpression                                 ::= <CallExpression> <Arguments> |
-                                                                       <CallExpression> <S>? '[' <S>? Expression <S>? ']' |
+FunctionCallName                               ::= <CallExpression> | <MemberExpression>
+FunctionCall                                   ::= <FunctionCallName> <S>? <Arguments>
+                                                                       
+CallExpression                                 ::= <CallExpression> <S>? '[' <S>? Expression <S>? ']' |
                                                                        <CallExpression> '.' <IdentifierName> |
-                                                                       <MemberExpression> <S>? <Arguments>
+                                                                       <FunctionCall>
 
 Arguments                                              ::= '(' <S>? ')' |
                                                                '(' <S>? <ArgumentList> <S>? ')'
-ArgumentList                                   ::= <ArgumentList> <S>? ',' <S>? <AssignmentExpression> |
-                                                                       <AssignmentExpression>
+Argument                                               ::= <AssignmentExpression>
+ArgumentList                                   ::= <ArgumentList> <S>? ',' <S>? <Argument> |
+                                                                       <Argument>
 LeftHandSideExpression                 ::= <CallExpression> | <NewExpression>
 LeftHandSideExpressionAddr             ::= <CallExpression> | <NewExpression>
 
index 0c4430b..61848be 100644 (file)
@@ -42,7 +42,6 @@ static const rchar *rjs_compiler_record2str(rjs_compiler_t *co, rarray_t *record
 
 static rlong rjs_compiler_record2identifer(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
-       rlong i;
        rvm_varmap_t *v = NULL;
        rjs_coctx_t *ctx = NULL;
        rparecord_t *prec = (rparecord_t *)r_array_slot(records, rec);
@@ -51,11 +50,7 @@ static rlong rjs_compiler_record2identifer(rjs_compiler_t *co, rarray_t *records
         * First lets find out if we are within a function definition or
         * this is a global variable.
         */
-       for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
-               ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
-               if (ctx->type == RJS_COCTX_FUNCTION || ctx->type == RJS_COCTX_GLOBAL)
-                       break;
-       }
+       ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION | RJS_COCTX_GLOBAL);
        R_ASSERT(ctx);
 
        v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
@@ -89,6 +84,20 @@ static rlong rjs_compiler_record2identifer(rjs_compiler_t *co, rarray_t *records
 }
 
 
+rjs_coctx_t *rjs_compiler_getctx(rjs_compiler_t *co, rulong type)
+{
+       rlong i;
+       rjs_coctx_t *ctx;
+
+       for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
+               ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
+               if (ctx->type & type)
+                       return ctx;
+       }
+       return NULL;
+}
+
+
 rlong rjs_compiler_record2opcode(rparecord_t *prec)
 {
        const rchar *input = prec->input;
@@ -208,131 +217,41 @@ error:
 rint rjs_compiler_rh_varalloc(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
        rparecord_t *prec;
-       rjs_coctx_t *ctx = NULL;
-       rvm_varmap_t *v = NULL;
-       rlong i;
-
-       R_ASSERT(r_array_length(co->coctx));
-
-       /*
-        * First lets find out if we are within a function definition or
-        * this is a global variable.
-        */
-       for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
-               ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
-               if (ctx->type == RJS_COCTX_FUNCTION || ctx->type == RJS_COCTX_GLOBAL)
-                       break;
-       }
-       R_ASSERT(ctx);
-
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        rjs_compiler_debugtail(co, records, rec);
 
        if (rjs_compiler_playchildrecords(co, records, rec) < 0)
-               goto error;
+               return -1;
 
        rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
-       v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
-
-       /*
-        * TBD: Temporary here
-        */
-       if (v) {
-               r_printf("ERROR: variable already defined: %s\n", rjs_compiler_record2str(co, records, rec));
-               goto error;
-       }
-
-       if (ctx->type == RJS_COCTX_FUNCTION) {
-               rjs_coctx_function_t *functx = (rjs_coctx_function_t *)ctx;
-               functx->allocs += 1;
-               rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->allocs);
-       } else {
-               rjs_coctx_global_t *functx = (rjs_coctx_global_t *)ctx;
-               functx->allocs += 1;
-               r_carray_setlength(co->cpu->data, functx->allocs + 1);
-               rvm_scope_addpointer(co->scope, prec->input, prec->inputsiz, r_carray_slot(co->cpu->data, functx->allocs));
-       }
-       v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
-       if (v->datatype == VARMAP_DATATYPE_OFFSET) {
-               rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R1, FP, DA, v->data.offset));
-       } else {
-               rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R1, DA, XX, v->data.ptr));
-       }
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_CLRR, R1, XX, XX, 0));
-
+       if (rjs_compiler_record2identifer(co, records, rec) < 0)
+               return -1;
        rjs_compiler_debugtail(co, records, rec);
        return 0;
-
-error:
-       return -1;
 }
 
 
 rint rjs_compiler_rh_varallocinit(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
        rparecord_t *prec;
-       rjs_coctx_t *ctx = NULL;
-       rvm_varmap_t *v = NULL;
-       rlong i;
-
-       R_ASSERT(r_array_length(co->coctx));
-
-       /*
-        * First lets find out if we are within a function definition or
-        * this is a global variable.
-        */
-       for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
-               ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
-               if (ctx->type == RJS_COCTX_FUNCTION || ctx->type == RJS_COCTX_GLOBAL)
-                       break;
-       }
-       R_ASSERT(ctx);
-
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        rjs_compiler_debugtail(co, records, rec);
 
        if (rjs_compiler_playchildrecords(co, records, rec) < 0)
-               goto error;
+               return -1;
 
        rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
-       v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
-
-       /*
-        * TBD: Temporary here
-        */
-       if (v) {
-               r_printf("ERROR: variable already defined: %s\n", rjs_compiler_record2str(co, records, rec));
-               goto error;
-       }
-
-       if (ctx->type == RJS_COCTX_FUNCTION) {
-               rjs_coctx_function_t *functx = (rjs_coctx_function_t *)ctx;
-               functx->allocs += 1;
-               rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->allocs);
-       } else {
-               rjs_coctx_global_t *functx = (rjs_coctx_global_t *)ctx;
-               functx->allocs += 1;
-               r_carray_setlength(co->cpu->data, functx->allocs + 1);
-               rvm_scope_addpointer(co->scope, prec->input, prec->inputsiz, r_carray_slot(co->cpu->data, functx->allocs));
-       }
-       v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
-       if (v->datatype == VARMAP_DATATYPE_OFFSET) {
-               rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
-       } else {
-               rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
-       }
+       if (rjs_compiler_record2identifer(co, records, rec) < 0)
+               return -1;
        rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
        rjs_compiler_debugtail(co, records, rec);
        return 0;
-
-error:
-       return -1;
 }
 
 
@@ -676,7 +595,7 @@ rint rjs_compiler_rh_functiondeclaration(rjs_compiler_t *co, rarray_t *records,
        rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
-
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_redefinelabel(co->cg, endidx);
        rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
        rvm_codegen_redefinepointer(co->cg, allocsidx, (rpointer)ctx.allocs);
@@ -698,18 +617,13 @@ rint rjs_compiler_rh_functionparameter(rjs_compiler_t *co, rarray_t *records, rl
        rjs_coctx_t *ctx = NULL;
        rjs_coctx_function_t *functx = NULL;
        rparecord_t *prec;
-       rlong i;
        rvm_varmap_t *v;
 
        /*
         * First lets find out if we are within a function definition or
         * this is a global variable.
         */
-       for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
-               ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
-               if (ctx->type == RJS_COCTX_FUNCTION)
-                       break;
-       }
+       ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION);
        R_ASSERT(ctx);
        functx = (rjs_coctx_function_t *)ctx;
 
@@ -741,6 +655,90 @@ rint rjs_compiler_rh_functionparameter(rjs_compiler_t *co, rarray_t *records, rl
 }
 
 
+rint rjs_compiler_rh_functioncall(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_functioncall_t ctx;
+
+       r_memset(&ctx, 0, sizeof(ctx));
+       ctx.base.type = RJS_COCTX_FUNCTIONCALL;
+       r_array_push(co->coctx, &ctx, rjs_coctx_t*);
+
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
+       rjs_compiler_debugtail(co, records, rec);
+
+       /*
+        * Important: Function call has two children FunctionCallName, Arguments
+        * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
+        * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
+        * result of the FunctionCallName will be in R0.
+        */
+       if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
+               goto error;
+
+       rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BXL, R0, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
+       rjs_compiler_debugtail(co, records, rec);
+       r_array_removelast(co->coctx);
+       return 0;
+
+error:
+       r_array_removelast(co->coctx);
+       return -1;
+}
+
+
+rint rjs_compiler_rh_argument(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
+
+       R_ASSERT(ctx);
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rjs_compiler_debugtail(co, records, rec);
+
+       if (rjs_compiler_playchildrecords(co, records, rec) < 0)
+               return -1;
+
+       rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
+       ctx->arguments += 1;
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
+rint rjs_compiler_rh_arguments(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
+
+       R_ASSERT(ctx);
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rjs_compiler_debugtail(co, records, rec);
+
+       if (rjs_compiler_playchildrecords(co, records, rec) < 0)
+               return -1;
+
+       rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
 rint rjs_compiler_rh_(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
        rparecord_t *prec;
@@ -795,6 +793,9 @@ rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
        co->handlers[UID_MEMBEREXPRESSIONINDEXOP] = rjs_compiler_rh_memberexpressionindexop;
        co->handlers[UID_FUNCTIONDECLARATION] = rjs_compiler_rh_functiondeclaration;
        co->handlers[UID_FUNCTIONPARAMETER] = rjs_compiler_rh_functionparameter;
+       co->handlers[UID_FUNCTIONCALL] = rjs_compiler_rh_functioncall;
+       co->handlers[UID_ARGUMENT] = rjs_compiler_rh_argument;
+       co->handlers[UID_ARGUMENTS] = rjs_compiler_rh_arguments;
 
        return co;
 }
index b7ee56d..c60dbf6 100644 (file)
@@ -17,9 +17,9 @@ extern "C" {
 #define RJS_COMPILER_NHANDLERS 128
 
 #define RJS_COCTX_NONE 0
-#define RJS_COCTX_GLOBAL 1
-#define RJS_COCTX_FUNCTION 2
-
+#define RJS_COCTX_GLOBAL (1 << 1)
+#define RJS_COCTX_FUNCTION (1 << 2)
+#define RJS_COCTX_FUNCTIONCALL (1 << 3)
 
 typedef struct rjs_coctx_s {
        rulong type;
@@ -38,6 +38,12 @@ typedef struct rjs_coctx_function_s {
 } rjs_coctx_function_t;
 
 
+typedef struct rjs_coctx_functioncall_s {
+       rjs_coctx_t base;
+       rsize_t arguments;
+} rjs_coctx_functioncall_t;
+
+
 typedef struct rjs_compiler_s rjs_compiler_t;
 typedef rint (*RJS_COMPILER_RH)(rjs_compiler_t *co, rarray_t *records, rlong rec);
 
@@ -57,7 +63,7 @@ struct rjs_compiler_s {
 rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu);
 void rjs_compiler_destroy(rjs_compiler_t *co);
 rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records);
-
+rjs_coctx_t *rjs_compiler_getctx(rjs_compiler_t *co, rulong type);
 
 #ifdef __cplusplus
 }
index 1b86d11..d96e848 100644 (file)
@@ -28,3 +28,7 @@
 #define UID_FUNCTIONDECLARATION 28
 #define UID_FUNCTIONPARAMETER 29
 #define UID_FORMALPARAMETERLIST 30
+#define UID_CALLEXPRESSION 31
+#define UID_FUNCTIONCALL 32
+#define UID_ARGUMENT 33
+#define UID_ARGUMENTS 34
index 47ca3e3..ab67d65 100644 (file)
@@ -259,7 +259,8 @@ static void rpavm_swi_emitend(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
        rpa_ruledata_t *ruledata = RVM_CPUREG_GETP(cpu, ins->op1);
        rpastat_t *stat = (rpastat_t *)cpu->userdata1;
-       rparecord_t *rec;
+       rparecord_t *rec, *startrec;
+       rlong startindex = RVM_CPUREG_GETL(cpu, R1) + 1;
        rlong index = RVM_CPUREG_GETL(cpu, R_REC);
        rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
        rword tplen = RVM_CPUREG_GETU(cpu, ins->op3);
@@ -273,6 +274,7 @@ static void rpavm_swi_emitend(rvmcpu_t *cpu, rvm_asmins_t *ins)
        index = r_array_replace(stat->records, index + 1, NULL);
        RVM_CPUREG_SETL(cpu, R_REC, index);
        rec = (rparecord_t *)r_array_slot(stat->records, index);
+       startrec = (rparecord_t *)r_array_slot(stat->records, startindex);
        rec->rule = name.str;
        rec->top = tp;
        rec->size = tplen;
@@ -281,6 +283,8 @@ static void rpavm_swi_emitend(rvmcpu_t *cpu, rvm_asmins_t *ins)
        rec->input = stat->instack[tp].input;
        rec->inputsiz = stat->instack[tp + tplen].input - stat->instack[tp].input;
        rec->next = 0;
+       startrec->size = tplen;
+       startrec->inputsiz = rec->inputsiz;
 
        if (tplen) {
                rec->type |= RPA_RECORD_MATCH;
index 6bbfaba..e728e98 100644 (file)
@@ -1130,6 +1130,8 @@ static void rvm_op_prn(rvmcpu_t *cpu, rvm_asmins_t *ins)
                rvm_printf("(Object) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
        else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
                rvm_printf("(SWI) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
+       else if (rvm_reg_gettype(r) == RVM_DTYPE_FUNCTION)
+               rvm_printf("(FUNCTION) R%d = %p\n", ins->op1, RVM_REG_GETP(r));
        else
                rvm_printf("(UNKNOWN) R%d = ?\n", ins->op1);
 }