Exemplo n.º 1
0
/* InitCompiler - initialize the compiler and create a parse context */
ParseContext *InitCompiler(System *sys, int maxObjects)
{
    ImageHdr *image;
    ParseContext *c;
    uint8_t *freeMark;

    /* allocate space for the image header */
    if (!(image = (ImageHdr *)AllocateFreeSpace(sys, sizeof(ImageHdr))))
        ParseError(c, "insufficient space for image header");
        
    /* mark the current position in free space to allow compiler data structures to be freed */
    freeMark = sys->freeNext;

    /* allocate space for the object table */
    if (!(image->objects = (VMVALUE *)AllocateFreeSpace(sys, maxObjects * sizeof(VMVALUE))))
        ParseError(c, "insufficient space for object table\n");

    /* allocate and initialize the parse context */
    if (!(c = (ParseContext *)AllocateFreeSpace(sys, sizeof(ParseContext))))
        ParseError(c, "insufficient space for parse context\n");
    memset(c, 0, sizeof(ParseContext));
    c->sys = sys;
    c->freeMark = freeMark;
    c->image = image;
    c->maxObjects = maxObjects;
    
    /* return the new parse context */
    return c;
}
Exemplo n.º 2
0
/* Compile - compile a program */
ImageHdr *Compile(ParseContext *c)
{
    System *sys = c->sys;
    ImageHdr *image = c->image;
    size_t maxHeapUsed = c->maxHeapUsed;
    VMVALUE *variables;
    VMUVALUE totalSize;
    Symbol *sym;
    
    /* setup an error target */
    if (setjmp(c->errorTarget) != 0)
        return NULL;

    /* initialize the scratch buffer */
    BufRewind();

    /* allocate space for the object table */
    image->objectCount = 0;
    image->objectDataSize = 0;

    /* use the rest of the free space for the compiler heap */
    c->nextGlobal = sys->freeNext;
    c->nextLocal = sys->freeTop;
    c->heapSize = sys->freeTop - sys->freeNext;
    c->maxHeapUsed = 0;

    /* initialize the global variable count */
    image->variableCount = 0;

    /* initialize block nesting table */
    c->btop = (Block *)((char *)c->blockBuf + sizeof(c->blockBuf));
    c->bptr = c->blockBuf - 1;

    /* initialize the code staging buffer */
    c->ctop = c->codeBuf + sizeof(c->codeBuf);
    c->cptr = c->codeBuf;

    /* initialize the string and label tables */
    c->strings = NULL;
    c->labels = NULL;

    /* start in the main code */
    c->codeType = CODE_TYPE_MAIN;

    /* initialize the global symbol table */
    InitSymbolTable(&c->globals);

    /* add the intrinsic functions */
    AddIntrinsic(c, "ABS",              FN_ABS);
    AddIntrinsic(c, "RND",              FN_RND);
    AddIntrinsic(c, "printStr",         FN_printStr);
    AddIntrinsic(c, "printInt",         FN_printInt);
    AddIntrinsic(c, "printTab",         FN_printTab);
    AddIntrinsic(c, "printNL",          FN_printNL);
    AddIntrinsic(c, "printFlush",       FN_printFlush);
#ifdef PROPELLER
    AddIntrinsic(c, "IN",               FN_IN);
    AddIntrinsic(c, "OUT",              FN_OUT);
    AddIntrinsic(c, "HIGH",             FN_HIGH);
    AddIntrinsic(c, "LOW",              FN_LOW);
    AddIntrinsic(c, "TOGGLE",           FN_TOGGLE);
    AddIntrinsic(c, "DIR",              FN_DIR);
    AddIntrinsic(c, "GETDIR",           FN_GETDIR);
    AddIntrinsic(c, "CNT",              FN_CNT);
    AddIntrinsic(c, "PAUSE",            FN_PAUSE);
    AddIntrinsic(c, "PULSEIN",          FN_PULSEIN);
    AddIntrinsic(c, "PULSEOUT",         FN_PULSEOUT);
#endif

    /* initialize scanner */
    c->inComment = VMFALSE;
    
    /* get the next line */
    while (GetLine(c)) {
        Token tkn;
        if ((tkn = GetToken(c)) != T_EOL)
            ParseStatement(c, tkn);
    }

    /* end the main code with a halt */
    putcbyte(c, OP_HALT);
    
    /* write the main code */
    StartCode(c, "main", CODE_TYPE_MAIN);
    image->mainCode = c->code;
    StoreCode(c);

    /* allocate the global variable table */
    if (!(variables = (VMVALUE *)AllocateFreeSpace(sys, image->variableCount * sizeof(VMVALUE))))
        ParseError(c, "insufficient space for variable table");

    /* store the initial values of the global variables */
    for (sym = c->globals.head; sym != NULL; sym = sym->next) {
        if (!(sym->value & INTRINSIC_FLAG))
            variables[sym->value] = sym->initialValue;
    }

    /* write out the variable and object tables */
    if (!BufWriteWords(variables, image->variableCount) || !BufWriteWords(image->objects, image->objectCount))
        ParseError(c, "insufficient scratch space");
        
    /* free up the space the compiler was consuming */
    sys->freeNext = c->freeMark;

    /* allocate space for the object data and variables */
    totalSize = (image->objectDataSize + image->variableCount + image->objectCount) * sizeof(VMVALUE);
    if (!(image->objectData = (VMVALUE *)AllocateFreeSpace(sys, totalSize)))
        ParseError(c, "insufficient space for objects and variables");
    image->variables = image->objectData + image->objectDataSize;
    image->objects = image->variables + image->variableCount;
    
    /* read the object data and variables from the scratch buffer */
    BufRewind();
    if (!BufReadWords(image->objectData, totalSize))
        ParseError(c, "error reading objects and variables");

    {
        int objectTableSize = image->objectCount  * sizeof(VMVALUE);
        int objectDataSize = image->objectDataSize  * sizeof(VMVALUE);
        int dataSize = objectTableSize + objectDataSize + image->variableCount * sizeof(VMVALUE);
#if 0
        DumpSymbols(&c->globals, "symbols");
#endif
        VM_printf("H:%d", maxHeapUsed);
        VM_printf(" O:%d", image->objectCount);
        VM_printf(" D:%d", objectDataSize);
        VM_printf(" V:%d", image->variableCount);
        VM_printf(" T:%d\n", dataSize);
    }

    /* return the image */
    return image;
}
Exemplo n.º 3
0
/* Execute - execute the main code */
int Execute(System *sys, ObjHeap *heap, VMHANDLE main)
{
    size_t stackSize;
    Interpreter *i;
    VMVALUE tmp, tmp2, ind;
    VMHANDLE obj, htmp;
    int8_t tmpb;

    /* allocate the interpreter state */
    if (!(i = (Interpreter *)AllocateFreeSpace(sys, sizeof(Interpreter))))
        return VMFALSE;

    /* make sure there is space left for the stack */
    if ((stackSize = (sys->freeTop - sys->freeNext) / sizeof(VMVALUE)) <= 0)
        return VMFALSE;
        
    /* setup the heap before/after compact functions */
    heap->beforeCompact = NULL;
    heap->afterCompact = AfterCompact;
    heap->compactCookie = i;
    
    /* initialize the interpreter state */
    i->sys = sys;
    i->heap = heap;
    i->stack = (VMVALUE *)((uint8_t *)i + sizeof(Interpreter));
    i->stackTop = i->stack + stackSize;
    
    /* setup to execute the main function */
    i->code = main;
    ObjAddRef(i->code);
    i->cbase = i->pc = GetCodePtr(main);
    i->sp = i->fp = i->stackTop;
    i->hsp = i->hfp = (VMHANDLE *)i->stack - 1;

    if (setjmp(i->sys->errorTarget)) {
        while (i->hsp > (VMHANDLE *)i->stack)
            ObjRelease(i->heap, PopH(i));
        ObjRelease(i->heap, i->code);
        return VMFALSE;
    }

    for (;;) {
#if 0
        ShowStack(i);
        DecodeInstruction(0, 0, i->pc);
#endif
        switch (VMCODEBYTE(i->pc++)) {
        case OP_HALT:
            return VMTRUE;
        case OP_BRT:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (Pop(i))
                i->pc += tmp;
            break;
        case OP_BRTSC:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (*i->sp)
                i->pc += tmp;
            else
                Drop(i, 1);
            break;
        case OP_BRF:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (!Pop(i))
                i->pc += tmp;
            break;
        case OP_BRFSC:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            if (!*i->sp)
                i->pc += tmp;
            else
                Drop(i, 1);
            break;
        case OP_BR:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            i->pc += tmp;
            break;
        case OP_NOT:
            *i->sp = (*i->sp ? VMFALSE : VMTRUE);
            break;
        case OP_NEG:
            *i->sp = -*i->sp;
            break;
        case OP_ADD:
            tmp = Pop(i);
            *i->sp += tmp;
            break;
        case OP_SUB:
            tmp = Pop(i);
            *i->sp -= tmp;
            break;
        case OP_MUL:
            tmp = Pop(i);
            *i->sp *= tmp;
            break;
        case OP_DIV:
            tmp = Pop(i);
            *i->sp = (tmp == 0 ? 0 : *i->sp / tmp);
            break;
        case OP_REM:
            tmp = Pop(i);
            *i->sp = (tmp == 0 ? 0 : *i->sp % tmp);
            break;
        case OP_CAT:
            StringCat(i);
            break;
        case OP_BNOT:
            *i->sp = ~*i->sp;
            break;
        case OP_BAND:
            tmp = Pop(i);
            *i->sp &= tmp;
            break;
        case OP_BOR:
            tmp = Pop(i);
            *i->sp |= tmp;
            break;
        case OP_BXOR:
            tmp = Pop(i);
            *i->sp ^= tmp;
            break;
        case OP_SHL:
            tmp = Pop(i);
            *i->sp <<= tmp;
            break;
        case OP_SHR:
            tmp = Pop(i);
            *i->sp >>= tmp;
            break;
        case OP_LT:
            tmp = Pop(i);
            *i->sp = (*i->sp < tmp ? VMTRUE : VMFALSE);
            break;
        case OP_LE:
            tmp = Pop(i);
            *i->sp = (*i->sp <= tmp ? VMTRUE : VMFALSE);
            break;
        case OP_EQ:
            tmp = Pop(i);
            *i->sp = (*i->sp == tmp ? VMTRUE : VMFALSE);
            break;
        case OP_NE:
            tmp = Pop(i);
            *i->sp = (*i->sp != tmp ? VMTRUE : VMFALSE);
            break;
        case OP_GE:
            tmp = Pop(i);
            *i->sp = (*i->sp >= tmp ? VMTRUE : VMFALSE);
            break;
        case OP_GT:
            tmp = Pop(i);
            *i->sp = (*i->sp > tmp ? VMTRUE : VMFALSE);
            break;
        case OP_LIT:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPush(i, tmp);
            break;
        case OP_GREF:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            obj = (VMHANDLE)tmp;
            CPush(i, GetSymbolPtr(obj)->v.iValue);
            break;
        case OP_GSET:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            obj = (VMHANDLE)tmp;
            GetSymbolPtr(obj)->v.iValue = Pop(i);
            break;
        case OP_LREF:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            CPush(i, i->fp[(int)tmpb]);
            break;
        case OP_LSET:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            i->fp[(int)tmpb] = Pop(i);
            break;
        case OP_VREF:
            ind = *i->sp;
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            *i->sp = GetIntegerVectorBase(obj)[ind];
            DropH(i, 1);
            break;
        case OP_VSET:
            tmp2 = Pop(i);
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            GetIntegerVectorBase(obj)[ind] = tmp2;
            DropH(i, 1);
            break;
       case OP_LITH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPushH(i, (VMHANDLE)tmp);
            ObjAddRef(*i->hsp);
            break;
        case OP_GREFH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            CPushH(i, GetSymbolPtr((VMHANDLE)tmp)->v.hValue);
            ObjAddRef(*i->hsp);
            break;
        case OP_GSETH:
            get_VMVALUE(tmp, VMCODEBYTE(i->pc++));
            ObjRelease(i->heap, GetSymbolPtr((VMHANDLE)tmp)->v.hValue);
            GetSymbolPtr((VMHANDLE)tmp)->v.hValue = PopH(i);
            break;
        case OP_LREFH:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            CPushH(i, i->hfp[(int)tmpb]);
            ObjAddRef(*i->hsp);
            break;
        case OP_LSETH:
            tmpb = (int8_t)VMCODEBYTE(i->pc++);
            ObjRelease(i->heap, i->hfp[(int)tmpb]);
            i->hfp[(int)tmpb] = PopH(i);
            break;
        case OP_VREFH:
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            *i->hsp = GetStringVectorBase(obj)[ind];
            ObjAddRef(*i->hsp);
            break;
        case OP_VSETH:
            htmp = PopH(i);
            ind = Pop(i);
            obj = *i->hsp;
            if (ind < 0 || ind >= GetHeapObjSize(obj))
                Abort(i->sys, str_subscript_err, ind);
            ObjRelease(i->heap, GetStringVectorBase(obj)[ind]);
            GetStringVectorBase(obj)[ind] = htmp;
            DropH(i, 1);
            break;
        case OP_RESERVE:
            tmp = VMCODEBYTE(i->pc++);
            tmp2 = VMCODEBYTE(i->pc++);
            Reserve(i, tmp);
            ReserveH(i, tmp2);
            break;
         case OP_CALL:
            StartCode(i);
            break;
        case OP_RETURN:
            tmp = *i->sp;
            PopFrame(i);
            Push(i, tmp);
            break;
        case OP_RETURNH:
            htmp = *i->hsp;
            PopFrame(i);
            PushH(i, htmp);
            break;
        case OP_RETURNV:
            PopFrame(i);
            break;
        case OP_DROP:
            Drop(i, 1);
            break;
        case OP_DROPH:
            ObjRelease(i->heap, *i->hsp);
            DropH(i, 1);
            break;
        default:
            Abort(i->sys, str_opcode_err, VMCODEBYTE(i->pc - 1));
            break;
        }
    }
}