RPA Toolkit
Added if statement compilation to RJS.
authorMartin Stoilov <martin@rpasearch.com>
Fri, 6 May 2011 06:09:14 +0000 (23:09 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Fri, 6 May 2011 06:09:14 +0000 (23:09 -0700)
rjs/ecma262.rpa
rjs/rjscompiler.c
rjs/rjscompiler.h
rjs/rjsuids.h
rvm/rvmcodegen.c
rvm/rvmcodegen.h
rvm/rvmcodemap.c
rvm/rvmcodemap.h

index 0bbbe82..6989a45 100644 (file)
@@ -37,8 +37,7 @@
 
 #!emit DecimalIntegerLiteral
 #!emit DecimalNonIntegerLiteral
-#!emit BlockBegin
-#!emit BlockEnd
+#!emit Block
 
 #!emit DoKeyword
 #!emit IterationDo
 #!emit Arguments
 #!emit FunctionCall
 #!emit FunctionCallName
+#!emit ReturnStatement
+#!emit IfStatement
+#!emit IfConditionOp
+#!emit IfTrueStatement
+#!emit IfFalseStatement
+
 
 #!uid Program                                          UID_PROGRAM                                             1
 #!uid PostfixExpressionValOp           UID_POSTFIXEXPRESSIONVALOP                      2
 #!uid FunctionCall                                     UID_FUNCTIONCALL                                        32
 #!uid Argument                                         UID_ARGUMENT                                            33
 #!uid Arguments                                                UID_ARGUMENTS                                           34
+#!uid ReturnStatement                          UID_RETURNSTATEMENT                                     35
+#!uid DoubleStringCharacters           UID_STRINGCHARACTERS                            36
+#!uid SingleStringCharacters           UID_STRINGCHARACTERS                            36
+#!uid IfStatement                                      UID_IFSTATEMENT                                         37
+#!uid IfConditionOp                                    UID_IFCONDITIONOP                                       38
+#!uid IfTrueStatement                          UID_IFTRUESTATEMENT                                     39
+#!uid IfFalseStatement                         UID_IFFALSESTATEMENT                            40
+#!uid Block                                                    UID_BLOCK                                                       41
 
 # 6 Source Text
 SourceCharacter                        ::= .
@@ -358,9 +371,7 @@ Statement                                           ::= <FunctionDeclarationStatement> |
                                                                <SwitchStatementOp>
 
 # 12.1 Block
-BlockBegin                                                     ::= <S>? '{' <S>?
-BlockEnd                                                       ::= <S>? '}' <S>?
-Block                                                          ::= <BlockBegin> <StatementList>? <BlockEnd>
+Block                                                          ::= <S>? '{' <S>? <StatementList>? <S>? '}' <S>?
 StatementList                                          ::= (<S>? <Statement>)+
 
 # 12.2 Variable Statement
@@ -380,14 +391,11 @@ ExpressionStatement                               ::= (<Expression> - ('function' | '{')) <SC>
 
 
 # 12.5 The if Statement
-
-ElseOp                                                         ::= 'else'
 IfConditionOp                                          ::= 'if' <S>? '(' <S>? <Expression> <S>? ')'
-IfOp                                                           ::= <IfConditionOp> <S>? <Statement>
-IfElseOp                                                       ::= <IfConditionOp> <S>? <Statement> <S>? <ElseOp> <S>? <Statement>
-
-IfStatement                                                    ::= <IfElseOp> |
-                                                                               <IfOp>
+IfTrueStatement                                                ::= <Statement>
+IfFalseStatement                                       ::= <Statement>
+IfStatement                                                    ::= <IfConditionOp> <S>? <IfTrueStatement> <S>? 'else' <S>? <IfFalseStatement> |
+                                                                       <IfConditionOp> <S>? <IfTrueStatement> 
 
 # 12.6 Iteration Statements
 # 12.6a Iteration do ... while() 
@@ -420,7 +428,7 @@ IterationStatement                                  ::= <IterationWhileOp> |
 
 # 12.9 The return Statement
 ReturnOp                                                       ::= ('return' - 'return' <IdentifierPart>) <WhiteSpace>* <AssignmentExpression>? (<S>? ';')
-ReturnStatement                                                ::= <ReturnOp>
+ReturnStatement                                                ::= ('return' - 'return' <IdentifierPart>) <WhiteSpace>* <AssignmentExpression>? (<S>? ';')
 
 # The Break Statement
 BreakOp                                                                ::= 'break' - 'break' <IdentifierPart>
index 61848be..1ca552e 100644 (file)
@@ -186,6 +186,8 @@ rint rjs_compiler_rh_program(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
        rjs_coctx_global_t ctx;
        rparecord_t *prec;
+       rlong mainidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__main", 0);
+       rlong start;
 
        r_memset(&ctx, 0, sizeof(ctx));
        ctx.base.type = RJS_COCTX_GLOBAL;
@@ -193,7 +195,8 @@ rint rjs_compiler_rh_program(rjs_compiler_t *co, rarray_t *records, rlong rec)
 
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, mainidx, rvm_asm(RVM_B, DA, XX, XX, 0));
+       start = rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
        rjs_compiler_debugtail(co, records, rec);
 
        if (rjs_compiler_playchildrecords(co, records, rec) < 0)
@@ -202,6 +205,9 @@ rint rjs_compiler_rh_program(rjs_compiler_t *co, rarray_t *records, rlong rec)
        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, mainidx);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_BL, DA, XX, XX, start - rvm_codegen_getcodesize(co->cg)));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_PRN, R0, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
        rjs_compiler_debugtail(co, records, rec);
@@ -417,6 +423,27 @@ rint rjs_compiler_rh_decimalnonintegerliteral(rjs_compiler_t *co, rarray_t *reco
 }
 
 
+rint rjs_compiler_rh_stringcharacters(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R1, DA, XX, (void*)prec->input));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R2, DA, XX, prec->inputsiz));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCSTR, R0, R1, R2, 0));
+       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_expressionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
        rparecord_t *prec;
@@ -739,6 +766,126 @@ rint rjs_compiler_rh_arguments(rjs_compiler_t *co, rarray_t *records, rlong rec)
 }
 
 
+rint rjs_compiler_rh_returnstatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       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_BX, LR, XX, XX, 0));
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
+rint rjs_compiler_rh_ifstatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_ifstatement_t ctx;
+
+       r_memset(&ctx, 0, sizeof(ctx));
+       ctx.base.type = RJS_COCTX_IFSTATEMENT;
+       ctx.start = rvm_codegen_getcodesize(co->cg);
+       ctx.trueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iftrue", ctx.start);
+       ctx.falseidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iffalse", ctx.start);
+       ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__ifend", ctx.start);
+
+       r_array_push(co->coctx, &ctx, rjs_coctx_t*);
+
+       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;
+
+       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_redefinelabel(co->cg, ctx.endidx);
+       if (!rvm_codegen_validlabel(co->cg, ctx.falseidx))
+               rvm_codegen_redefinelabel(co->cg, ctx.falseidx);
+       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_ifconditionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
+
+       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_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->falseidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
+rint rjs_compiler_rh_iftruestatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
+
+       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_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
+rint rjs_compiler_rh_iffalsestatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
+
+       R_ASSERT(ctx);
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rvm_codegen_redefinelabel(co->cg, ctx->falseidx);
+       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;
@@ -773,6 +920,7 @@ rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
        co->handlers[UID_LEFTHANDSIDEEXPRESSIONADDR] = rjs_compiler_rh_lefthandsideexpressionaddr;
        co->handlers[UID_DECIMALINTEGERLITERAL] = rjs_compiler_rh_decimalintegerliteral;
        co->handlers[UID_DECIMALNONINTEGERLITERAL] = rjs_compiler_rh_decimalnonintegerliteral;
+       co->handlers[UID_STRINGCHARACTERS] = rjs_compiler_rh_stringcharacters;
        co->handlers[UID_ADDITIVEEXPRESSIONOP] = rjs_compiler_rh_expressionop;
        co->handlers[UID_MULTIPLICATIVEEXPRESSIONOP] = rjs_compiler_rh_expressionop;
        co->handlers[UID_BITWISEANDOP] = rjs_compiler_rh_expressionop;
@@ -796,6 +944,12 @@ rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
        co->handlers[UID_FUNCTIONCALL] = rjs_compiler_rh_functioncall;
        co->handlers[UID_ARGUMENT] = rjs_compiler_rh_argument;
        co->handlers[UID_ARGUMENTS] = rjs_compiler_rh_arguments;
+       co->handlers[UID_RETURNSTATEMENT] = rjs_compiler_rh_returnstatement;
+       co->handlers[UID_STRINGCHARACTERS] = rjs_compiler_rh_stringcharacters;
+       co->handlers[UID_IFSTATEMENT] = rjs_compiler_rh_ifstatement;
+       co->handlers[UID_IFCONDITIONOP] = rjs_compiler_rh_ifconditionop;
+       co->handlers[UID_IFTRUESTATEMENT] = rjs_compiler_rh_iftruestatement;
+       co->handlers[UID_IFFALSESTATEMENT] = rjs_compiler_rh_iffalsestatement;
 
        return co;
 }
index c60dbf6..6d228a5 100644 (file)
@@ -20,6 +20,7 @@ extern "C" {
 #define RJS_COCTX_GLOBAL (1 << 1)
 #define RJS_COCTX_FUNCTION (1 << 2)
 #define RJS_COCTX_FUNCTIONCALL (1 << 3)
+#define RJS_COCTX_IFSTATEMENT (1 << 4)
 
 typedef struct rjs_coctx_s {
        rulong type;
@@ -44,6 +45,15 @@ typedef struct rjs_coctx_functioncall_s {
 } rjs_coctx_functioncall_t;
 
 
+typedef struct rjs_coctx_ifstatement_s {
+       rjs_coctx_t base;
+       rlong start;
+       rlong trueidx;
+       rlong falseidx;
+       rlong endidx;
+} rjs_coctx_ifstatement_t;
+
+
 typedef struct rjs_compiler_s rjs_compiler_t;
 typedef rint (*RJS_COMPILER_RH)(rjs_compiler_t *co, rarray_t *records, rlong rec);
 
index d96e848..dd6c87b 100644 (file)
 #define UID_FUNCTIONCALL 32
 #define UID_ARGUMENT 33
 #define UID_ARGUMENTS 34
+#define UID_RETURNSTATEMENT 35
+#define UID_STRINGCHARACTERS 36
+#define UID_STRINGCHARACTERS 36
+#define UID_IFSTATEMENT 37
+#define UID_IFCONDITIONOP 38
+#define UID_IFTRUESTATEMENT 39
+#define UID_IFFALSESTATEMENT 40
index c8f868d..eb85e23 100644 (file)
@@ -71,6 +71,12 @@ rlong rvm_codegen_redefinelabel(rvm_codegen_t *cg, rlong index)
 }
 
 
+rlong rvm_codegen_validlabel(rvm_codegen_t *cg, rlong index)
+{
+       return rvm_codemap_validindex(cg->codemap, index);
+}
+
+
 rlong rvm_codegen_redefinepointer(rvm_codegen_t *cg, rlong index, rpointer data)
 {
        rvm_codelabel_t *label = rvm_codemap_label(cg->codemap, index);
index 0024ece..a1184ba 100644 (file)
@@ -45,6 +45,7 @@ rulong rvm_codegen_getcodesize(rvm_codegen_t *cg);
 void rvm_codegen_setcodesize(rvm_codegen_t *cg, ruint size);
 void rvm_codegen_clear(rvm_codegen_t *cg);
 rint rvm_codegen_relocate(rvm_codegen_t *cg, rvm_codelabel_t **err);
+rlong rvm_codegen_validlabel(rvm_codegen_t *cg, rlong index);
 rlong rvm_codegen_redefinelabel(rvm_codegen_t *cg, rlong index);
 rlong rvm_codegen_redefinepointer(rvm_codegen_t *cg, rlong index, rpointer data);
 rlong rvm_codegen_addlabel(rvm_codegen_t *cg, const rchar* name, ruint namesize);
index ee7cc3b..03dd17d 100644 (file)
@@ -42,7 +42,7 @@ void rvm_codemap_clear(rvm_codemap_t *codemap)
 
 rvm_codelabel_t *rvm_codemap_label(rvm_codemap_t *codemap, rlong index)
 {
-       if (index < 0)
+       if (index < 0 || index >= r_array_length(codemap->labels))
                return NULL;
        return (rvm_codelabel_t*)r_array_slot(codemap->labels, index);
 }
@@ -126,6 +126,16 @@ rlong rvm_codemap_invalid_add(rvm_codemap_t *codemap, const rchar *name, ruint n
 }
 
 
+rlong rvm_codemap_validindex(rvm_codemap_t *codemap, rlong labelidx)
+{
+       rvm_codelabel_t *label = rvm_codemap_label(codemap, labelidx);
+
+       if (label && label->type != RVM_CODELABEL_INVALID)
+               return 1;
+       return 0;
+}
+
+
 rlong rvm_codemap_invalid_add_s(rvm_codemap_t *codemap, const rchar *name)
 {
        return rvm_codemap_invalid_add(codemap, name, r_strlen(name));
index 1b1871d..37aa7a6 100644 (file)
@@ -44,6 +44,7 @@ rlong rvm_codemap_lookup(rvm_codemap_t *codemap, const rchar *name, ruint namesi
 rlong rvm_codemap_lookup_s(rvm_codemap_t *codemap, const rchar *name);
 rlong rvm_codemap_lastlabel(rvm_codemap_t *codemap);
 rvm_codelabel_t *rvm_codemap_label(rvm_codemap_t *codemap, rlong index);
+rlong rvm_codemap_validindex(rvm_codemap_t *codemap, rlong labelidx);
 rword rvm_codemap_resolve(rvm_codemap_t *codemap, rlong index, rvm_codelabel_t **err);
 void rvm_codemap_dump(rvm_codemap_t *codemap);