示例#1
0
/* StoreCode - store the function or method under construction */
void StoreCode(ParseContext *c)
{
    int codeSize;

    /* check for unterminated blocks */
    switch (CurrentBlockType(c)) {
    case BLOCK_IF:
    case BLOCK_ELSE:
        ParseError(c, "expecting END IF");
    case BLOCK_FOR:
        ParseError(c, "expecting NEXT");
    case BLOCK_DO:
        ParseError(c, "expecting LOOP");
    case BLOCK_NONE:
        break;
    }

    /* fixup the RESERVE instruction at the start of the code */
    if (c->codeType != CODE_TYPE_MAIN) {
        c->codeBuf[1] = c->localOffset;
        putcbyte(c, OP_RETURN);
    }

    /* make sure all referenced labels were defined */
    CheckLabels(c);

    /* place string literals defined in this function */
    PlaceStrings(c);
    
    /* determine the code size */
    codeSize = (int)(c->cptr - c->codeBuf);

#if 0
    VM_printf("%s:\n", c->codeName);
    DecodeFunction((uint8_t *)c->image, (c->image->objectDataSize + GetObjSizeInWords(sizeof(VectorObjectHdr))) * sizeof(VMVALUE), c->codeBuf, codeSize);
    DumpSymbols(&c->arguments, "arguments");
    DumpSymbols(&c->locals, "locals");
    VM_printf("\n");
#endif

    /* store the vector object */
    StoreBVectorData(c, c->code, PROTO_CODE, c->codeBuf, codeSize);

    /* empty the local heap */
    c->nextLocal = c->sys->freeTop;
    InitSymbolTable(&c->arguments);
    InitSymbolTable(&c->locals);
    c->labels = NULL;

    /* reset to compile the next code */
    c->codeType = CODE_TYPE_MAIN;
    c->cptr = c->codeBuf;
}
示例#2
0
/* ParseLoop - parse the 'LOOP' statement */
static void ParseLoop(ParseContext *c)
{
    int inst;
    switch (CurrentBlockType(c)) {
    case BLOCK_DO:
        inst = putcbyte(c, OP_BR);
        putcword(c, c->bptr->u.DoBlock.nxt - inst - 1 - sizeof(VMUVALUE));
        fixupbranch(c, c->bptr->u.DoBlock.end, codeaddr(c));
        PopBlock(c);
        break;
    default:
        ParseError(c, "LOOP without a matching DO");
        break;
    }
    FRequire(c, T_EOL);
}
示例#3
0
/* ParseElse - parse the 'ELSE' statement */
static void ParseElse(ParseContext *c)
{
    int end;
    switch (CurrentBlockType(c)) {
    case BLOCK_IF:
        putcbyte(c, OP_BR);
        end = putcword(c, c->bptr->u.IfBlock.end);
        fixupbranch(c, c->bptr->u.IfBlock.nxt, codeaddr(c));
        c->bptr->type = BLOCK_ELSE;
        c->bptr->u.ElseBlock.end = end;
        break;
    default:
        ParseError(c, "ELSE without a matching IF");
        break;
    }
    FRequire(c, T_EOL);
}
示例#4
0
/* ParseEndIf - parse the 'END IF' statement */
static void ParseEndIf(ParseContext *c)
{
    switch (CurrentBlockType(c)) {
    case BLOCK_IF:
        fixupbranch(c, c->bptr->u.IfBlock.nxt, codeaddr(c));
        fixupbranch(c, c->bptr->u.IfBlock.end, codeaddr(c));
        PopBlock(c);
        break;
    case BLOCK_ELSE:
        fixupbranch(c, c->bptr->u.ElseBlock.end, codeaddr(c));
        PopBlock(c);
        break;
    default:
        ParseError(c, "END IF without a matching IF/ELSE IF/ELSE");
        break;
    }
    FRequire(c, T_EOL);
}
示例#5
0
/* ParseElseIf - parse the 'ELSE IF' statement */
static void ParseElseIf(ParseContext *c)
{
    switch (CurrentBlockType(c)) {
    case BLOCK_IF:
        putcbyte(c, OP_BR);
        c->bptr->u.IfBlock.end = putcword(c, c->bptr->u.IfBlock.end);
        fixupbranch(c, c->bptr->u.IfBlock.nxt, codeaddr(c));
        c->bptr->u.IfBlock.nxt = 0;
        ParseRValue(c);
        FRequire(c, T_THEN);
        putcbyte(c, OP_BRF);
        c->bptr->u.IfBlock.nxt = putcword(c, 0);
        FRequire(c, T_EOL);
        break;
    default:
        ParseError(c, "ELSE IF without a matching IF");
        break;
    }
}
示例#6
0
/* ParseNext - parse the 'NEXT' statement */
static void ParseNext(ParseContext *c)
{
    ParseTreeNode *var;
    int inst;
    switch (CurrentBlockType(c)) {
    case BLOCK_FOR:
        FRequire(c, T_IDENTIFIER);
        var = GetSymbolRef(c, c->token);
        /* BUG: check to make sure it matches the symbol used in the FOR */
        inst = putcbyte(c, OP_BR);
        putcword(c, c->bptr->u.ForBlock.nxt - inst - 1 - sizeof(VMUVALUE));
        fixupbranch(c, c->bptr->u.ForBlock.end, codeaddr(c));
        PopBlock(c);
        break;
    default:
        ParseError(c, "NEXT without a matching FOR");
        break;
    }
    FRequire(c, T_EOL);
}
示例#7
0
/* StoreCode - store the function or method under construction */
VMVALUE StoreCode(ParseContext *c)
{
    size_t codeSize;
    VMVALUE code;
    uint8_t *p;

    /* check for unterminated blocks */
    switch (CurrentBlockType(c)) {
    case BLOCK_IF:
    case BLOCK_ELSE:
        ParseError(c, "expecting END IF");
    case BLOCK_FOR:
        ParseError(c, "expecting NEXT");
    case BLOCK_DO:
        ParseError(c, "expecting LOOP");
    case BLOCK_NONE:
        break;
    }

    /* fixup the RESERVE instruction at the start of the code */
    if (c->codeType != CODE_TYPE_MAIN) {
        c->codeBuf[1] = 2 + c->localOffset;
        putcbyte(c, OP_RETURN);
    }

    /* make sure all referenced labels were defined */
    CheckLabels(c);
    
    /* allocate code space */
    codeSize = (int)(c->codeFree - c->codeBuf);
    p = (uint8_t *)ImageTextAlloc(c, codeSize);
    memcpy(p, c->codeBuf, codeSize);
    
    /* get the address of the compiled code */
    code = (VMVALUE)(p - (uint8_t *)c->image);

#ifdef COMPILER_DEBUG
{
    VM_printf("%s:\n", c->codeSymbol ? c->codeSymbol->name : "<main>");
    DecodeFunction((uint8_t *)c->image, (uint8_t *)c->image + code, codeSize);
    DumpSymbols(&c->arguments, "arguments");
    DumpSymbols(&c->locals, "locals");
    VM_printf("\n");
}
#endif

    /* prepare the buffer for the next function */
    c->codeFree = c->codeBuf;

    /* empty the local heap */
    c->localFree = c->heapBase;
    InitSymbolTable(&c->arguments);
    InitSymbolTable(&c->locals);
    c->labels = NULL;

    /* reset to compile the next code */
    c->codeType = CODE_TYPE_MAIN;
    
    /* return the code vector */
    return code;
}