Beispiel #1
0
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++;
}
Beispiel #2
0
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++;
}
Beispiel #3
0
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++;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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++;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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++;
}
Beispiel #9
0
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++;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
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++;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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++;
}