RPA Toolkit
work on RJS compile time errors
authorMartin Stoilov <martin@rpasearch.com>
Thu, 12 May 2011 05:18:47 +0000 (22:18 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Thu, 12 May 2011 05:18:47 +0000 (22:18 -0700)
rjs/ecma262.rpa
rjs/rjs.c
rjs/rjscompiler.c
rjs/rjscompiler.h
rjs/rjsexec.c
rjs/rjsuids.h
rlib/rjsobject.h

index 258c7d7..7de5eae 100644 (file)
@@ -11,7 +11,7 @@
 #!emit dqstring
 #!emit sqstring
 
-#!emitid UnaryOperator                                 UID_UNARYOPERATOR                                       1
+#!emitid SyntaxError                                   UID_SYNTAXERROR                                         1
 #!emitid AdditiveOperator                              UID_BINARYOPERATOR                                      2
 #!emitid AdditiveOperator                              UID_ADDITIVEOPERATOR                            2
 #!emitid MultiplicativeOperator                        UID_MULTIPLICATIVEOPERATOR                      2
@@ -29,7 +29,7 @@
 #!emitid PrefixOperator                                        UID_PREFIXOPERATOR                                      2
 #!emitid ShiftOperator                                 UID_SHIFTOPERATOR                                       2
 #!emitid EqualityOperator                              UID_EQUALITYOPERATOR                            2
-#!emitid Program                                               UID_PROGRAM                                             3
+#!emitid UnaryOperator                                 UID_UNARYOPERATOR                                       3
 #!emitid This                                                  UID_THIS                                                        4
 #!emitid Expression                                            UID_EXPRESSION                                          5
 #!emitid LeftHandSideExpression                        UID_LEFTHANDSIDEEXPRESSION                      6
 #!emitid DecimalNonIntegerLiteral              UID_DECIMALNONINTEGERLITERAL            53
 #!emitid BreakStatement                                        UID_BREAKSTATEMENT                                      54
 #!emitid ContinueStatement                             UID_CONTINUESTATEMENT                           55
+#!emitid IterationWhile                                        UID_ITERATIONWHILE                                      56
+#!emitid IterationDo                                   UID_ITERATIONDO                                         57
+#!emitid WhileExpressionCompare                        UID_WHILEEXPRESSIONCOMPARE                      58
+#!emitid DoWhileExpressionCompare              UID_DOWHILEEXPRESSIONCOMPARE            59
+#!emitid Program                                               UID_PROGRAM                                             60
 
 
 # 6 Source Text
@@ -366,14 +371,12 @@ IfStatement                                                       ::= <IfConditionOp> <S>? <IfTrueStatement> <S>? 'else' <S>? <I
 
 # 12.6 Iteration Statements
 # 12.6a Iteration do ... while() 
-WhileKeyword                                           ::= 'while'
-WhileExpression                                                ::= <WhileKeyword> <S>? '(' <S>? <Expression> <S>? ')'
-DoKeyword                                                      ::= 'do'
-IterationDo                                                    ::= <DoKeyword> <S>? <Statement> <S>? <WhileExpression> (<S>? ';')
+DoWhileExpressionCompare                       ::= <Expression>
+IterationDo                                                    ::= 'do' <S>? <Statement> <S>? 'while' <S>? '(' <S>? <DoWhileExpressionCompare> <S>? ')' (<S>? ';')
 
 # 12.6b Iteration while()
-WhileConditionOp                                       ::= 'while' <S>? '(' <S>? <Expression> <S>? ')'
-IterationWhileOp                                       ::= <WhileConditionOp> <S>? <Statement>
+WhileExpressionCompare                         ::= <Expression>
+IterationWhile                                         ::= 'while' <S>? '(' <S>? <WhileExpressionCompare> <S>? ')' <S>? <Statement>
 
 # 12.6c Iteration for ( ; ; )
 ExpressionNoIn                                         ::= <Expression>
@@ -384,7 +387,7 @@ ForIterationStatement                               ::= <Statement>
 IterationFor                                           ::= 'for' <S>? '(' <S>? <ForExpressionInit>? <S>? ';' <S>? <ForExpressionCompare>? <S>? ';' <S>? <ForExpressionIncrement>? <S>? ')' <S>? <ForIterationStatement>
 
 
-IterationStatement                                     ::= <IterationWhileOp> |
+IterationStatement                                     ::= <IterationWhile> |
                                                                                <IterationFor> |
                                                                        <IterationDo>
 
@@ -443,9 +446,11 @@ FunctionDeclarationStatement               ::= ('function' - 'function' <IdentifierPart>)<S>?
 
 
 # 14 Program
+SyntaxError                                            ::= (. - <SC>)+ <SC>?
 SourceElements                                         ::= (<S>? <SourceElement>)+
-SourceElement                                          ::= <FunctionDeclaration> |
-                                                                       <Statement>
+SourceElement                                  ::= <FunctionDeclaration> |
+                                                               <Statement> |
+                                                               <SyntaxError>
 Program                                                        ::= <SourceElements>
 # The root rule, it is anonymous
 <Program>
index 0889d72..1d5383e 100644 (file)
--- a/rjs/rjs.c
+++ b/rjs/rjs.c
@@ -1,4 +1,5 @@
 #include "rmem.h"
+#include "rjsobject.h"
 #include "rjs.h"
 
 
@@ -22,11 +23,17 @@ const rchar *rjs_version()
 
 rjs_engine_t *rjs_engine_create()
 {
+       rvmreg_t *tp;
        rjs_engine_t *jse = (rjs_engine_t *) r_zmalloc(sizeof(*jse));
 
        jse->pa = rjs_parser_create();
        jse->cpu = rvm_cpu_create_default();
        rvm_cpu_addswitable(jse->cpu, "rjsswitable", rjsswitable);
+
+       tp = rvm_cpu_alloc_global(jse->cpu);
+       rvm_reg_setjsobject(tp, (robject_t *)rjs_object_create(sizeof(rvmreg_t)));
+       rvm_cpu_setreg(jse->cpu, TP, tp);
+
        return jse;
 }
 
index c08f5e4..efe7c7c 100644 (file)
@@ -256,7 +256,6 @@ rint rjs_compiler_rh_program(rjs_compiler_t *co, rarray_t *records, rlong 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_ALLOCOBJ, TP, DA, XX, 0));
        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_EXT, XX, XX, XX, 0));
        rjs_compiler_debugtail(co, records, rec);
@@ -332,6 +331,7 @@ rint rjs_compiler_rh_initializer(rjs_compiler_t *co, rarray_t *records, rlong re
 
 rint rjs_compiler_rh_identifier(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
+       rjs_coerror_t error;
        rvm_varmap_t *v;
        rparecord_t *prec;
        rlong swiid = -1;
@@ -356,8 +356,11 @@ rint rjs_compiler_rh_identifier(rjs_compiler_t *co, rarray_t *records, rlong rec
                        goto end;
                }
 
-               r_printf("ERROR: Undefined identifier: %s\n", rjs_compiler_record2str(co, records, rec));
-               return -1;
+               error.code = RJS_ERROR_UNDEFINED;
+               error.script = prec->input;
+               error.scriptsize = prec->inputsiz;
+               r_array_add(co->errors, &error);
+               return 0;
        }
 
        if (rjs_compiler_record_parentuid(co, records, rec) == UID_LEFTHANDSIDEEXPRESSIONADDR && rpa_recordtree_next(records, rec, RPA_RECORD_START) == -1) {
@@ -1034,6 +1037,114 @@ error:
 }
 
 
+rint rjs_compiler_rh_iterationwhile(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_iteration_t ctx;
+
+       r_memset(&ctx, 0, sizeof(ctx));
+       ctx.base.type = RJS_COCTX_ITERATION;
+       ctx.start = rvm_codegen_getcodesize(co->cg);
+       ctx.iterationidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iteration", ctx.start);
+       ctx.continueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__continue", ctx.start);
+       ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__end", ctx.start);
+       r_array_push(co->coctx, &ctx, rjs_coctx_t*);
+       rvm_scope_push(co->scope);
+
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rjs_compiler_debugtail(co, records, rec);
+
+
+       rvm_codegen_redefinelabel(co->cg, ctx.iterationidx);
+       rvm_codegen_redefinelabel(co->cg, ctx.continueidx);
+
+       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_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
+       rvm_codegen_redefinelabel(co->cg, ctx.endidx);
+       rjs_compiler_debugtail(co, records, rec);
+
+       rvm_scope_pop(co->scope);
+       r_array_removelast(co->coctx);
+       return 0;
+
+error:
+       rvm_scope_pop(co->scope);
+       r_array_removelast(co->coctx);
+       return -1;
+}
+
+
+rint rjs_compiler_rh_iterationdo(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_iteration_t ctx;
+
+       r_memset(&ctx, 0, sizeof(ctx));
+       ctx.base.type = RJS_COCTX_ITERATION;
+       ctx.start = rvm_codegen_getcodesize(co->cg);
+       ctx.iterationidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iteration", ctx.start);
+       ctx.continueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__continue", ctx.start);
+       ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__end", ctx.start);
+       r_array_push(co->coctx, &ctx, rjs_coctx_t*);
+       rvm_scope_push(co->scope);
+
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rjs_compiler_debugtail(co, records, rec);
+
+
+       rvm_codegen_redefinelabel(co->cg, ctx.iterationidx);
+
+       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_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
+       rvm_codegen_redefinelabel(co->cg, ctx.endidx);
+       rjs_compiler_debugtail(co, records, rec);
+
+       rvm_scope_pop(co->scope);
+       r_array_removelast(co->coctx);
+       return 0;
+
+error:
+       rvm_scope_pop(co->scope);
+       r_array_removelast(co->coctx);
+       return -1;
+}
+
+
+rint rjs_compiler_rh_dowhileexpressioncompare(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rparecord_t *prec;
+       rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
+
+       R_ASSERT(ctx);
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       rvm_codegen_redefinelabel(co->cg, ctx->continueidx);
+       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_BEQ, DA, XX, XX, 0));
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
 rint rjs_compiler_rh_forexpressioncompare(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
        rparecord_t *prec;
@@ -1316,6 +1427,31 @@ rint rjs_compiler_rh_break(rjs_compiler_t *co, rarray_t *records, rlong rec)
 }
 
 
+rint rjs_compiler_rh_syntaxerror(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rjs_coerror_t error;
+
+       r_memset(&error, 0, sizeof(error));
+       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);
+       error.code = RJS_ERROR_SYNTAX;
+       error.script = prec->input;
+       error.scriptsize = prec->inputsiz;
+       r_array_add(co->errors, &error);
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
 rint rjs_compiler_rh_(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
        rparecord_t *prec;
@@ -1341,6 +1477,7 @@ rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
        co->cg = rvm_codegen_create();
        co->scope = rvm_scope_create();
        co->coctx = r_array_create(sizeof(rjs_coctx_t *));
+       co->errors = r_array_create(sizeof(rjs_coerror_t));
        co->cpu = cpu;
        r_memset(co->handlers, 0, sizeof(co->handlers));
 
@@ -1382,7 +1519,11 @@ rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
        co->handlers[UID_IFCONDITIONOP] = rjs_compiler_rh_ifconditionop;
        co->handlers[UID_IFTRUESTATEMENT] = rjs_compiler_rh_iftruestatement;
        co->handlers[UID_IFFALSESTATEMENT] = rjs_compiler_rh_iffalsestatement;
+       co->handlers[UID_ITERATIONDO] = rjs_compiler_rh_iterationdo;
+       co->handlers[UID_ITERATIONWHILE] = rjs_compiler_rh_iterationwhile;
        co->handlers[UID_ITERATIONFOR] = rjs_compiler_rh_iterationfor;
+       co->handlers[UID_DOWHILEEXPRESSIONCOMPARE] = rjs_compiler_rh_dowhileexpressioncompare;
+       co->handlers[UID_WHILEEXPRESSIONCOMPARE] = rjs_compiler_rh_forexpressioncompare;
        co->handlers[UID_FOREXPRESSIONCOMPARE] = rjs_compiler_rh_forexpressioncompare;
        co->handlers[UID_FOREXPRESSIONINCREMENT] = rjs_compiler_rh_forexpressionincrement;
        co->handlers[UID_POSTFIXEXPRESSIONOP] = rjs_compiler_rh_postfixexpressionop;
@@ -1394,6 +1535,7 @@ rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
        co->handlers[UID_UNARYOPERATOR] = rjs_compiler_rh_unaryoperator;
        co->handlers[UID_BREAKSTATEMENT] = rjs_compiler_rh_break;
        co->handlers[UID_CONTINUESTATEMENT] = rjs_compiler_rh_continue;
+       co->handlers[UID_SYNTAXERROR] = rjs_compiler_rh_syntaxerror;
 
        return co;
 }
@@ -1405,6 +1547,7 @@ void rjs_compiler_destroy(rjs_compiler_t *co)
                rvm_codegen_destroy(co->cg);
                rvm_scope_destroy(co->scope);
                r_array_destroy(co->coctx);
+               r_array_destroy(co->errors);
                r_free(co->temp);
                co->cpu = NULL;
                r_free(co);
@@ -1481,6 +1624,7 @@ rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records)
                return -1;
        }
 
+       r_array_setlength(co->errors, 0);
        for (i = 0; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
                if (rjs_compiler_playrecord(co, records, i) < 0)
                        /*
@@ -1489,6 +1633,13 @@ rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records)
                        return -1;
        }
 
+       if (r_array_length(co->errors)) {
+               /*
+                * TBD
+                */
+               return -1;
+       }
+
        if (rvm_codegen_relocate(co->cg, &labelerr) < 0) {
                /*
                 * TBD
index 727e91d..11ed985 100644 (file)
@@ -24,6 +24,11 @@ extern "C" {
 #define RJS_COCTX_ITERATION (1 << 5)
 #define RJS_COCTX_OPERATION (1 << 5)
 
+#define RJS_ERROR_NONE 0
+#define RJS_ERROR_UNDEFINED 1
+#define RJS_ERROR_SYNTAX 2
+
+
 typedef struct rjs_coctx_s {
        rulong type;
 } rjs_coctx_t;
@@ -72,6 +77,13 @@ typedef struct rjs_coctx_iteration_s {
 } rjs_coctx_iteration_t;
 
 
+typedef struct rjs_coerror_s {
+       rlong code;
+       const rchar *script;
+       rlong scriptsize;
+} rjs_coerror_t;
+
+
 typedef struct rjs_compiler_s rjs_compiler_t;
 typedef rint (*RJS_COMPILER_RH)(rjs_compiler_t *co, rarray_t *records, rlong rec);
 
@@ -80,6 +92,7 @@ struct rjs_compiler_s {
        rvm_codegen_t *cg;
        rvm_scope_t *scope;
        rarray_t *coctx;
+       rarray_t *errors;
        rchar *temp;
        rlong headoff;
        rlong opcode;
index 9912130..ffdecf0 100644 (file)
@@ -64,6 +64,55 @@ error:
 }
 
 
+int rjs_exec_script(rjs_engine_t *jse, rstr_t  *script)
+{
+       if (!script)
+               return -1;
+       if (parseinfo) {
+               rjs_engine_dumpast(jse, script->str, script->size);
+       } else if (debugcompileonly) {
+               int res = 0;
+               jse->debugcompile = 1;
+               res = rjs_engine_compile(jse, script->str, script->size);
+               jse->debugcompile = 0;
+               if (res < 0)
+                       return -1;
+       } else if (compileonly) {
+               rjs_engine_compile(jse, script->str, script->size);
+       } else {
+               if (rjs_engine_compile(jse, script->str, script->size) < 0)
+                       return -1;
+               if (rjs_engine_run(jse) < 0)
+                       return -1;
+       }
+
+       return 0;
+}
+
+
+void rjs_display_errors(rjs_engine_t *jse, rstr_t *script)
+{
+       rlong line = 0;
+       rlong i;
+       rjs_coerror_t *err;
+
+       for (i = 0; i < r_array_length(jse->co->errors); i++) {
+               err = (rjs_coerror_t *)r_array_slot(jse->co->errors, i);
+               fprintf(stdout, "Line: %ld ", (rlong)line);
+               if (err->code == RJS_ERROR_SYNTAX) {
+                       fprintf(stdout, "Sytax Error");
+               } else if (err->code == RJS_ERROR_UNDEFINED) {
+                       fprintf(stdout, "Undefined Identifier");
+               } else {
+                       fprintf(stdout, "Error");
+               }
+               fprintf(stdout, "(%ld, %ld): ", (rlong)(err->script - script->str), (rlong)err->scriptsize);
+               fwrite(err->script, sizeof(rchar), err->scriptsize, stdout);
+               fprintf(stdout, "\n");
+       }
+}
+
+
 int main(int argc, char *argv[])
 {
        rint i;
@@ -76,6 +125,7 @@ int main(int argc, char *argv[])
 
                } else if (r_strcmp(argv[i], "-d") == 0) {
                        debuginfo = 1;
+                       jse->debugexec = 1;
                } else if (r_strcmp(argv[i], "-p") == 0) {
                        parseinfo = 1;
                } else if (r_strcmp(argv[i], "-C") == 0) {
@@ -95,7 +145,8 @@ int main(int argc, char *argv[])
                                line.size = r_strlen(argv[i]);
                                script = &line;
                        }
-                       goto exec;
+                       if (rjs_exec_script(jse, script) < 0)
+                               goto end;
                }
        }
 
@@ -107,30 +158,14 @@ int main(int argc, char *argv[])
                                        unmapscript = script;
                                }
                        }
-                       goto exec;
+                       if (rjs_exec_script(jse, script) < 0)
+                               goto end;
                }
        }
 
-exec:
-       if (!script)
-               goto end;
-       if (parseinfo) {
-               rjs_engine_dumpast(jse, script->str, script->size);
-       } else if (debugcompileonly) {
-               jse->debugcompile = 1;
-               rjs_engine_compile(jse, script->str, script->size);
-               jse->debugcompile = 0;
-       } else if (compileonly) {
-               rjs_engine_compile(jse, script->str, script->size);
-       } else {
-               if (rjs_engine_compile(jse, script->str, script->size) < 0)
-                       goto end;
-               if (debuginfo)
-                       jse->debugexec = 1;
-               rjs_engine_run(jse);
-       }
-
 end:
+       if (jse->co && r_array_length(jse->co->errors))
+               rjs_display_errors(jse, script);
        rjs_engine_destroy(jse);
        if (unmapscript)
                rjs_unmap_file(unmapscript);
index a2e24f3..b4079a4 100644 (file)
@@ -1,4 +1,4 @@
-#define UID_UNARYOPERATOR 1
+#define UID_SYNTAXERROR 1
 #define UID_BINARYOPERATOR 2
 #define UID_ADDITIVEOPERATOR 2
 #define UID_MULTIPLICATIVEOPERATOR 2
@@ -16,7 +16,7 @@
 #define UID_PREFIXOPERATOR 2
 #define UID_SHIFTOPERATOR 2
 #define UID_EQUALITYOPERATOR 2
-#define UID_PROGRAM 3
+#define UID_UNARYOPERATOR 3
 #define UID_THIS 4
 #define UID_EXPRESSION 5
 #define UID_LEFTHANDSIDEEXPRESSION 6
@@ -70,3 +70,8 @@
 #define UID_DECIMALNONINTEGERLITERAL 53
 #define UID_BREAKSTATEMENT 54
 #define UID_CONTINUESTATEMENT 55
+#define UID_ITERATIONWHILE 56
+#define UID_ITERATIONDO 57
+#define UID_WHILEEXPRESSIONCOMPARE 58
+#define UID_DOWHILEEXPRESSIONCOMPARE 59
+#define UID_PROGRAM 60
index cad7087..af8f709 100644 (file)
@@ -6,6 +6,12 @@
 #include "rcarray.h"
 #include "rharray.h"
 
+/*
+ * This class targets the JavaScript Object implementation. Although I think it is pretty useful
+ * collection primitive that is worth staying in RLIB. In the future I might either rename it or
+ * move it to RJS.
+ */
+
 #ifdef __cplusplus
 extern "C" {
 #endif