RPA Toolkit
work on the RJS function definitions.
authorMartin Stoilov <martin@rpasearch.com>
Thu, 5 May 2011 04:11:45 +0000 (21:11 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Thu, 5 May 2011 04:11:45 +0000 (21:11 -0700)
rjs/ecma262.rpa
rjs/rjscompiler.c
rjs/rjsuids.h
rvm/rvmcodegen.c
rvm/rvmcodegen.h

index 5efecea..0ead0e9 100644 (file)
 #!emit VariableAllocate
 #!emit VariableAllocateAndInit
 #!emit NewArrayExpression
+#!emit FunctionName
+#!emit FunctionDeclaration
+#!emit FunctionParameter
+#!emit FormalParameterList
 
 
 #!uid Program                                          UID_PROGRAM                                             1
 #!uid NewArrayExpression                       UID_NEWARRAYEXPRESSION                          24
 #!uid MemberExpressionDotOp                    UID_MEMBEREXPRESSIONDOTOP                       25
 #!uid MemberExpressionIndexOp          UID_MEMBEREXPRESSIONINDEXOP                     26
+#!uid FunctionName                                     UID_FUNCTIONNAME                                        27
+#!uid FunctionDeclaration                      UID_FUNCTIONDECLARATION                         28
+#!uid FunctionParameter                                UID_FUNCTIONPARAMETER                           29
+#!uid FormalParameterList                      UID_FORMALPARAMETERLIST                         30
 
 
 # 6 Source Text
@@ -326,7 +334,7 @@ Expression                                          ::= <AssignmentExpression> ( <S>? ',' <S>? <AssignmentExpress
 
 
 # 12 Statements
-Statement                                              ::= <FunctionDefinitionStatement> |
+Statement                                              ::= <FunctionDeclarationStatement> |
                                                                <ExpressionStatement> |
                                                                        <ContinueStatement> |
                                                                        <Block> |
@@ -437,15 +445,23 @@ DefaultClauseOp                                           ::= <DefaultKeywordOp> <S>? ':' <S>? <StatementList>?
 
 
 # 13 Function Definition
-FunctionName                                           ::= <Identifier>
-FunctionNameLookupAlloc                                ::= <Identifier>
-FunctionDefinition                                     ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionName><S>?'('<S>?<FormalParameterList>?<S>?')'
-FunctionDeclaration                                    ::= <FunctionDefinition><S>?'{'<S>?<FunctionBody>?<S>?'}'
-FunctionExpression                                     ::= ('function' - 'function'<IdentifierPart>)<S>?<FunctionName>?<S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>?'}'
-FunctionParameter                                      ::= <Identifier>
+FunctionName                                           ::= <IdentifierNoEmit>
+FunctionDeclaration                                    ::= ('function'-'function'<IdentifierPart>)<S>?<FunctionName><S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>?'}'
+FunctionExpression                                     ::= ('function'-'function'<IdentifierPart>)<S>?<FunctionName>?<S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>?'}'
 FormalParameterList                            ::= <FunctionParameter> ( <S>? ',' <S>? <FunctionParameter> )*
-FunctionDefinitionStatement                    ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionNameLookupAlloc><S>?'('<S>?<FormalParameterList>?<S>?')' <SC>
+FunctionParameter                                      ::= <IdentifierNoEmit>
 FunctionBody                                           ::= <SourceElements>
+FunctionDeclarationStatement           ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionName><S>?'('<S>?<FormalParameterList>?<S>?')' <SC>
+
+# FunctionName                                         ::= <IdentifierNoEmit>
+# FunctionNameLookupAlloc                      ::= <IdentifierNoEmit>
+# FunctionDefinition                           ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionName><S>?'('<S>?<FormalParameterList>?<S>?')'
+# FunctionDeclaration                          ::= <FunctionDefinition><S>?'{'<S>?<FunctionBody>?<S>?'}'
+# FunctionExpression                           ::= ('function' - 'function'<IdentifierPart>)<S>?<FunctionName>?<S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>?'}'
+# FunctionParameter                            ::= <Identifier>
+# FormalParameterList                          ::= <FunctionParameter> ( <S>? ',' <S>? <FunctionParameter> )*
+# FunctionDefinitionStatement          ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionNameLookupAlloc><S>?'('<S>?<FormalParameterList>?<S>?')' <SC>
+# FunctionBody                                         ::= <SourceElements>
 
 
 # 14 Program
index 327f12d..0c4430b 100644 (file)
@@ -40,6 +40,55 @@ 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);
+
+       /*
+        * 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);
+
+       v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
+
+       /*
+        * TBD: Temporary here
+        */
+       if (v) {
+               r_printf("ERROR: Identifier already defined: %s\n", rjs_compiler_record2str(co, records, rec));
+               return -1;
+       }
+
+       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));
+       }
+
+       return 0;
+}
+
+
 rlong rjs_compiler_record2opcode(rparecord_t *prec)
 {
        const rchar *input = prec->input;
@@ -542,14 +591,14 @@ rint rjs_compiler_rh_memberexpressiondotop(rjs_compiler_t *co, rarray_t *records
        rjs_compiler_debughead(co, records, rec);
        if (rpa_record_getruleuid(records, rpa_recordtree_parent(records, rec, RPA_RECORD_START)) == UID_LEFTHANDSIDEEXPRESSIONADDR &&
                rpa_recordtree_next(records, rec, RPA_RECORD_START) == -1) {
-               rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));    // Supposedly Array Address
+               rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));    // Supposedly an Array
                rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, prec->inputsiz));
                rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R2, DA, XX, (void*)prec->input));
                rvm_codegen_addins(co->cg, rvm_asm(RVM_OBJLKUPADD, R0, R1, R2, 0));     // Get the offset of the element at offset R0
                rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDROBJH, R0, R1, R0, 0));       // Get the address of the element at offset R0
 
        } else {
-               rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));    // Supposedly Array Address
+               rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));    // Supposedly an Array
                rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, prec->inputsiz));
                rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R2, DA, XX, (void*)prec->input));
                rvm_codegen_addins(co->cg, rvm_asm(RVM_OBJLKUP, R0, R1, R2, 0));        // Get the offset of the element at offset R0
@@ -560,6 +609,138 @@ rint rjs_compiler_rh_memberexpressiondotop(rjs_compiler_t *co, rarray_t *records
 }
 
 
+rint rjs_compiler_rh_memberexpressionindexop(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_asm(RVM_PUSH, R0, XX, XX, 0));   // Supposedly an Array
+       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);
+       if (rpa_record_getruleuid(records, rpa_recordtree_parent(records, rec, RPA_RECORD_START)) == UID_LEFTHANDSIDEEXPRESSIONADDR &&
+               rpa_recordtree_next(records, rec, RPA_RECORD_START) == -1) {
+               rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly an Array
+               rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDROBJN, R0, R1, R0, 0));       // Get the address of the element at offset R0
+
+       } else {
+               rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly an Array
+               rvm_codegen_addins(co->cg, rvm_asm(RVM_LDOBJN, R0, R1, R0, 0)); // Get the value of the element at offset R0
+       }
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
+rint rjs_compiler_rh_functiondeclaration(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       rjs_coctx_function_t ctx;
+       rparecord_t *prec;
+       rlong start, execidx, endidx, allocsidx;
+
+       r_memset(&ctx, 0, sizeof(ctx));
+       ctx.base.type = RJS_COCTX_FUNCTION;
+
+       prec = (rparecord_t *)r_array_slot(records, rec);
+       rjs_compiler_debughead(co, records, rec);
+       start = rvm_codegen_getcodesize(co->cg);
+       endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__funend", start);
+       execidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__funexec", start);
+       allocsidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__allocs", start);
+
+       if (rpa_record_getruleuid(records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_START)) != UID_FUNCTIONNAME)
+               goto error;
+       if (rjs_compiler_record2identifer(co, records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_START)) < 0)
+               goto error;
+
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_JUMP, execidx, rvm_asm(RVM_MOV, R0, DA, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_SETTYPE, R0, DA, XX, RVM_DTYPE_FUNCTION));
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
+       rvm_codegen_redefinelabel(co->cg, execidx);
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_DEFAULT, allocsidx, rvm_asm(RVM_ADD, SP, FP, DA, 0));
+
+       rjs_compiler_debugtail(co, records, rec);
+
+       r_array_push(co->coctx, &ctx, rjs_coctx_t*);
+       rvm_scope_push(co->scope);
+       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, endidx);
+       rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
+       rvm_codegen_redefinepointer(co->cg, allocsidx, (rpointer)ctx.allocs);
+       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_functionparameter(rjs_compiler_t *co, rarray_t *records, rlong rec)
+{
+       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;
+       }
+       R_ASSERT(ctx);
+       functx = (rjs_coctx_function_t *)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);
+       v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
+
+       /*
+        * TBD: Temporary here
+        */
+       if (v) {
+               r_printf("ERROR: Identifier already defined: %s\n", rjs_compiler_record2str(co, records, rec));
+               return -1;
+       }
+
+       functx->allocs += 1;
+       rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->allocs);
+
+       rjs_compiler_debugtail(co, records, rec);
+       return 0;
+}
+
+
 rint rjs_compiler_rh_(rjs_compiler_t *co, rarray_t *records, rlong rec)
 {
        rparecord_t *prec;
@@ -611,6 +792,9 @@ rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
        co->handlers[UID_ASSIGNMENTEXPRESSIONOP] = rjs_compiler_rh_assignmentexpressionop;
        co->handlers[UID_NEWARRAYEXPRESSION] = rjs_compiler_rh_newarrayexpression;
        co->handlers[UID_MEMBEREXPRESSIONDOTOP] = rjs_compiler_rh_memberexpressiondotop;
+       co->handlers[UID_MEMBEREXPRESSIONINDEXOP] = rjs_compiler_rh_memberexpressionindexop;
+       co->handlers[UID_FUNCTIONDECLARATION] = rjs_compiler_rh_functiondeclaration;
+       co->handlers[UID_FUNCTIONPARAMETER] = rjs_compiler_rh_functionparameter;
 
        return co;
 }
@@ -689,15 +873,29 @@ static rint rjs_compiler_playrecord(rjs_compiler_t *co, rarray_t *records, rlong
 rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records)
 {
        rlong i;
+       rvm_codelabel_t *labelerr;
 
        if (!co || !records || r_array_empty(records)) {
-
+               /*
+                * TBD
+                */
                return -1;
        }
 
        for (i = 0; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
                if (rjs_compiler_playrecord(co, records, i) < 0)
+                       /*
+                        * TBD
+                        */
                        return -1;
        }
+
+       if (rvm_codegen_relocate(co->cg, &labelerr) < 0) {
+               /*
+                * TBD
+                */
+               return -1;
+       }
+
        return 0;
 }
index a185ea8..1b86d11 100644 (file)
@@ -24,3 +24,7 @@
 #define UID_NEWARRAYEXPRESSION 24
 #define UID_MEMBEREXPRESSIONDOTOP 25
 #define UID_MEMBEREXPRESSIONINDEXOP 26
+#define UID_FUNCTIONNAME 27
+#define UID_FUNCTIONDECLARATION 28
+#define UID_FUNCTIONPARAMETER 29
+#define UID_FORMALPARAMETERLIST 30
index b0dcb1f..c8f868d 100644 (file)
@@ -71,6 +71,16 @@ rlong rvm_codegen_redefinelabel(rvm_codegen_t *cg, rlong index)
 }
 
 
+rlong rvm_codegen_redefinepointer(rvm_codegen_t *cg, rlong index, rpointer data)
+{
+       rvm_codelabel_t *label = rvm_codemap_label(cg->codemap, index);
+
+       if (!label)
+               return -1;
+       return rvm_codemap_addpointer(cg->codemap, label->name->str, label->name->size, data);
+}
+
+
 rlong rvm_codegen_addlabel(rvm_codegen_t *cg, const rchar* name, ruint namesize)
 {
        return rvm_codemap_addoffset(cg->codemap, name, namesize, rvm_codemap_lookup_s(cg->codemap, ".code"), RVM_CODE2BYTE_OFFSET(rvm_codegen_getcodesize(cg)));
@@ -220,3 +230,24 @@ rlong rvm_codegen_addstring_s(rvm_codegen_t *cg, const rchar *name, const rchar*
 {
        return rvm_codegen_addstring(cg, name, r_strlen(name), data);
 }
+
+
+rlong rvm_codegen_add_numlabel_s(rvm_codegen_t *cg, const rchar *alphaname, rlong numname)
+{
+       rchar label[128];
+
+       r_memset(label, 0, sizeof(label));
+       r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
+       return rvm_codegen_addlabel_s(cg, label);
+}
+
+
+rlong rvm_codegen_invalid_add_numlabel_s(rvm_codegen_t *cg, const rchar *alphaname, rlong numname)
+{
+       rchar label[128];
+
+       r_memset(label, 0, sizeof(label));
+       r_snprintf(label, sizeof(label) - 1, "L%07ld__%s:", numname, alphaname);
+       return rvm_codegen_invalid_addlabel_s(cg, label);
+}
+
index 8ec32bd..0024ece 100644 (file)
@@ -46,6 +46,7 @@ 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_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);
 rlong rvm_codegen_addlabel_s(rvm_codegen_t *cg, const rchar* name);
 rlong rvm_codegen_invalid_addlabel(rvm_codegen_t *cg, const rchar* name, ruint namesize);
@@ -54,6 +55,8 @@ rlong rvm_codegen_adddata(rvm_codegen_t *cg, const rchar *name, ruint namesize,
 rlong rvm_codegen_adddata_s(rvm_codegen_t *cg, const rchar *name, rconstpointer data, rsize_t size);
 rlong rvm_codegen_addstring(rvm_codegen_t *cg, const rchar *name, ruint namesize, const rchar* data);
 rlong rvm_codegen_addstring_s(rvm_codegen_t *cg, const rchar *name, const rchar* data);
+rlong rvm_codegen_add_numlabel_s(rvm_codegen_t *cg, const rchar *alphaname, rlong numname);
+rlong rvm_codegen_invalid_add_numlabel_s(rvm_codegen_t *cg, const rchar *alphaname, rlong numname);
 
 #ifdef __cplusplus
 }