static int Compiler_compileSetSlotNode(Context* context, Node* node) { int obj = Compiler_compile(context, node->left); int val = Compiler_compile(context, node->right); int slot = Compiler_compile(context, node->data.node); Block_append(context->block, OP_SET, context->reg, obj, slot, val); return context->reg++; }
static int Compiler_compileUnOpNode(Context* context, Node* node) { int obj = Compiler_compile(context, node->right); int op = Compiler_compile(context, node->data.node); Block_append(context->block, OP_SEND, context->reg, obj, op, 0); return context->reg++; }
static int Compiler_compileSendNode(Context* context, Node* node) { int obj = Compiler_compile(context, node->left); int argc = Compiler_compile(context, node->right); int slot = Compiler_compile(context, node->data.node); Block_append(context->block, OP_SEND, context->reg, obj, slot, argc); return context->reg++; }
static int Compiler_compileBranchNode(Context* context, Node* node) { Reg ret; if (node->left) { ret = Compiler_compile(context, node->left); } if (node->right) { ret = Compiler_compile(context, node->right); } return ret; }
static int Compiler_compileWhileNode(Context* context, Node* node) { int start = Block_position(context->block) - 1; Reg cond = Compiler_compile(context, node->left); int cond_jmp = Block_append(context->block, OP_JNS, cond, 0) + 2; Compiler_compile(context, node->right); int diff = start - Block_position(context->block); int end = Block_append(context->block, OP_JMP, diff); Block_replace(context->block, cond_jmp, end); return cond; }
static int Compiler_compileBinOpNode(Context* context, Node* node) { int lhs = Compiler_compile(context, node->left); int rhs = Compiler_compile(context, node->right); int op = Compiler_compile(context, node->data.node); // push rhs onto the stack Block_append(context->block, OP_PUSH, rhs); // send the operator as message to lhs Block_append(context->block, OP_SEND, context->reg, lhs, op, 1); return context->reg++; }
static int Compiler_compileArgsNode(Context* context, Node* node) { int argc; if (node->right) { argc = Compiler_compile(context, node->right) + 1; } else argc = 1; if (node->left) { int arg = Compiler_compile(context, node->left); Block_append(context->block, OP_PUSH, arg); } else if (!node->right) argc = 0; return argc; }
static int Compiler_compileDoNode(Context* context, Node* node) { // backup current block Block* oldBlock = context->block; // create context for the new function context->block = Block_new(); SymTab_enterScope(context->symtab); // pop the arguments from the stack // and save the registers to the symtab int argc = 0; Node* arg = node->left; while (arg) { Block_append(context->block, OP_POP, context->reg); SymTab_store(context->symtab, arg->data.sval, context->reg++); arg = arg->right; argc++; } // compile the function code int ret = Compiler_compile(context, node->right); Block_append(context->block, OP_RET, ret); int block = Module_addBlock(context->module, context->block); // restore the old context SymTab_leaveScope(context->symtab); context->block = oldBlock; // create the function Block_append(context->block, OP_FUN, context->reg, block, argc); return context->reg++; }
static int Compiler_compileCallNode(Context* context, Node* node) { if (node->left->tag == NameNode) { if (!strcmp(node->left->data.sval, "load")) { assert(node->right->left->tag == StringNode); const char* name = node->right->left->data.sval; int str = Block_const(context->block, CONST_STR, (void*)name); Block_append(context->block, OP_LOAD, context->reg, str); return context->reg++; } } int obj = Compiler_compile(context, node->left); int argc = Compiler_compile(context, node->right); Block_append(context->block, OP_CALL, context->reg, obj, argc); return context->reg++; }
static int Compiler_compileTryNode(Context* context, Node* node) { int catch_jmp = Block_append(context->block, OP_TRY, 0) + 1; int ret = Compiler_compile(context, node->left); Block_append(context->block, OP_ENDTRY); int skip_catch = Block_append(context->block, OP_JMP, 0) + 1; int diff; diff = Block_position(context->block) - catch_jmp; Block_replace(context->block, catch_jmp, diff); Compiler_compile(context, node->right); diff = Block_position(context->block) - skip_catch; Block_replace(context->block, skip_catch, diff); return ret; }
static int Compiler_compileAssignNode(Context* context, Node* node) { int reg = SymTab_lookup(context->symtab, node->data.sval); int obj = Compiler_compile(context, node->right); if (reg < 0) { SymTab_store(context->symtab, node->data.sval, context->reg); reg = context->reg++; } Block_append(context->block, OP_MOV, reg, obj); return reg; }
static int Compiler_compileHashArgsNode(Context* context, Node* node) { int argc; if (node->right) { argc = Compiler_compile(context, node->right) + 1; } else argc = 1; if (node->left) { assert(node->left->tag == HashElementNode); int key = Compiler_compile(context, node->left->left); int obj = Compiler_compile(context, node->left->right); Block_append(context->block, OP_PUSH, key); Block_append(context->block, OP_PUSH, obj); } else if (!node->right) argc = 0; return argc; }
static int Compiler_compileSubscriptNode(Context* context, Node* node) { int obj = Compiler_compile(context, node->left); int sub = Compiler_compile(context, node->right); int value = node->data.node ? Compiler_compile(context, node->data.node) : 0; // generate [] or []= symbol Node* sym = Node_new(SymbolNode, 0, 0); sym->data.sval = value ? "[]=" : "[]"; int op = Compiler_compile(context, sym); int args = 1; if (value) { Block_append(context->block, OP_PUSH, value); args = 2; } Block_append(context->block, OP_PUSH, sub); Block_append(context->block, OP_SEND, context->reg, obj, op, args); return context->reg++; }
static int Compiler_compileIfNode(Context* context, Node* node) { int diff; Reg res = context->reg++; // compile condition Reg cond = Compiler_compile(context, node->left); int cond_jmp = Block_append(context->block, OP_JNS, cond, 0) + 2; if (node->right->tag == ElseNode) { Reg res_a = Compiler_compile(context, node->right->left); Block_append(context->block, OP_MOV, res, res_a); } else { Reg res_a = Compiler_compile(context, node->right); Block_append(context->block, OP_MOV, res, res_a); } // add jump to the end int end_jmp = Block_append(context->block, OP_JMP, 0) + 1; // change condition jump to this position diff = Block_position(context->block) - cond_jmp + 1; Block_replace(context->block, cond_jmp, diff); if (node->right->tag == ElseNode) { Reg res_b = Compiler_compile(context, node->right->right); Block_append(context->block, OP_MOV, res, res_b); } else { Block_append(context->block, OP_NIL, res); } // change end jump to this position diff = Block_position(context->block) - end_jmp; Block_replace(context->block, end_jmp, diff); return res; }
int Compiler_compileRootNode(Context* context, Node* root) { context->block = Block_new(); int id = Module_addBlock(context->module, context->block); // this code is only executed if an error occurs in the // compilation process further down if (setjmp(context->error_buf)) { return -1; } if (root) { int ret = Compiler_compile(context, root); Block_append(context->block, OP_RET, ret); } else { Block_append(context->block, OP_NIL, context->reg); Block_append(context->block, OP_RET, context->reg++); } return id; }
int main(int argc, char *argv[]) { int ret = 0; int fd = -1; unsigned char *input = NULL; ByteCode *byte_code = NULL; #if DEBUG_MEM mtrace(); #endif if (argc != 2) { printf("usage: %s <grammar_file>\n", argv[0]); ret = 2; goto done; } struct stat st; if (stat(argv[1], &st) != 0) { perror(argv[1]); ret = 3; goto done; } input = (unsigned char*)malloc(st.st_size); if (!input) { ret = 255; goto done; } fd = open(argv[1], O_RDONLY); if (fd < 0) { perror(argv[1]); ret = 4; goto done; } int size = read(fd, input, st.st_size); if (size != st.st_size) { perror(argv[1]); ret = 5; goto done; } close(fd); fd = -1; byte_code = Compiler_compile(input, st.st_size, NULL, 0); ByteCode_print(byte_code); int cmp = ByteCode_compare(&peg_byte_code, byte_code); printf("ByteCode_compare(&peg_byte_code, byte_code) = %d\n", cmp); ret = 0; done: if (byte_code) { ByteCode_free(byte_code); } if (input) { free(input); } if (fd >= 0) { close(fd); } #if DEBUG_MEM muntrace(); #endif return ret; }
static int Compiler_compileHashNode(Context* context, Node* node) { int argc = Compiler_compile(context, node->left); Block_append(context->block, OP_HASH, context->reg, argc); return context->reg++; }