Пример #1
0
static void deleteToken (tokenInfo *const token)
{
	vStringDelete (token->string);
	vStringDelete (token->scope);
	eFree (token);
}
Пример #2
0
void eval( Node *node )
{
    int             i, j;
    Number          n1, n2, n3, n4;
    char            *string1;
    Symbol          *s;
    Node            *n;
    Array           *a;

/* debugging */
#ifdef __DEBUG_TRACE__
    SourceCode *sc;
#endif


/* init vars */
    n1=0;
    n2=0;
    n3=0;
    n4=0;


    if (node == NULL) {
        return;
    }

    /* test node */
    eMemTest( "eval: node is corrupt", node );
    eMemTest( "eval: node->left is corrupt", node->left );
    eMemTest( "eval: node->right is corrupt", node->right );

    /* tracing */
    if (node->trace != -1) {
        runLineId = node->trace;
#ifdef __DEBUG_TRACE__
        sc = eFindSource( runLineId );
        eConsole("%d: %s\n", sc->lineNum, sc->text );
#endif
	/* sdlBasic_debugging */
	if (debug==1){
	    screendebug(); ////////////////////////////////////
	}
    }

/* debugging */
#ifdef __DEBUG_TRACE__
    eConsole( "Op:%s\n", opcodeName[node->op] );
#endif

    switch( node->op ) {

    //case NULL:
    //    break;

    case OpAdd:
        eval( node->left );
        eval( node->right );

        /* add or concat? */
        if (getStackType( tos ) == DATA_STRING) {
            basConcat();
        } else {
            n2 = popNumber();
            n1 = popNumber();
            pushNumber( n1 + n2 );
        }
        break;

    case OpAnd:
        /* short circuit */
        eval( node->left );
        if (!popNumber()) {
            pushNumber( (Number)0 );
        } else {
            eval( node->right );
            if (popNumber()) {
                pushNumber( (Number)1 );
            } else {
                pushNumber( (Number)0 );
            }
        }
        break;

    case OpArgList:
        eval( node->left );
        eval( node->right );
        break;

    case OpArrayGet:
        eval( node->left );     /* indices and index */
        getArrayElement( node->value.symbol );
        break;

    case OpArrayPtr:
        pushArray( node->value.symbol );
        break;

    case OpArraySet:
        eval( node->right );    /* value to store */
        eval( node->left );     /* indices and index */
        setArrayElement( node->value.symbol );
        break;

    case OpAssign:

        /* value to be assigned. note the *right* node is used */
        eval( node->right );

        /* variable to assign to */
        setVar( node->value.symbol );
        break;

    case OpBuiltin:
    case OpBuiltinCall:

        /* for argcount */
        n1 = tos;

        /* mark start of created objects */
        pushCreateStack( 0 );

        /* the args */
        eval( node->left );

        /* builtin symbol */
        s = node->value.symbol;

        if (s == NULL) {
            ePrintf( Runtime, "builtin pointer is null");
        }

        /* set args */
        argCount = (int)(tos - n1);

        /* call the c function */
        (*s->builtin)();

        /* destroy created objects */
        clearCreateStack();

        /* drop result? */
        if (node->op == OpBuiltinCall) {
            dropTos();
        }

        break;

    case OpCaseSelect:
        /* top level of a case statement */

        /* value to compare */
        eval( node->left );

        /* resolve into real data */
        switch (getStackType( tos )) {

        case DATA_NUMBER:
            pushNumber( popNumber() );
            break;

        case DATA_STRING:
            pushString( popString() );
            break;

        default:
            ePrintf( Runtime, "OpCaseSelect: can't resolve type %s",
                datumName[getStackType( tos )] );
        }

        /* get first test */
        if (node == NULL) {
            /* no tests */
            break;
        } else {
            node = node->right;
        }

        /* walk the chain of cases */
        while (1) {
            /* get a test/action pair */
            n = node->left;

            /* perform the tests */
            eval( n->left );

            /* true? */
            if (popNumber()) {
                /* perform action and leave loop */
                eval( n->right );
                break;
            }

            /* move to next test */
            node = node->right;
            if (node == NULL) {
                break;
            }
        }

        /* drop the test value from the stack */
        dropTos();
        break;

    case OpCaseCmp:
    case OpCaseRange:
    case OpCaseElse:
        /* perform chain of tests until true or end */
        while (1) {
            switch (node->op) {
            case OpCaseCmp:
                /* value to compare */
                eval(node->left);

                /* what type of test? */
                switch (getStackType( tos-1 )) {
                case DATA_NUMBER:
                    numberCompare( node->value.iValue, 0 );
                    break;

                case DATA_STRING:
                    stringCompare( node->value.iValue, 0 );
                    break;

                default:
                    ePrintf( Runtime, "OpCaseCmp: bad data type" );
                }
                break;

            case OpCaseRange:
                /* values to compare */
                n = node->left;
                eval( n->left );
                eval( n->right );

                /* what type of comparison? */
                switch (getStackType( tos-2 )) {
                case DATA_NUMBER:
                    numberRangeCompare();
                    break;

                case DATA_STRING:
                    stringRangeCompare();
                    break;

                default:
                    ePrintf( Runtime, "OpCaseRange: bad data type" );
                    break;
                }
                break;

            case OpCaseElse:
                /* put true on stack */
                pushNumber( 1 );
                break;

            default:
                ePrintf( Runtime, "opcode %s found in Case test chain",
                    opcodeName[node->op] );
            }

            /* was result true? */
            if (stack[tos].value.number) {
                /* leave true flag on stack and exit */
                break;
            }

            /* move to next test */
            node = node->right;
            if (node == NULL) {
                /* exit with false flag */
                break;
            }

            /* drop test result flag */
            dropTos();
        }
        break;

    case OpClassMethod:
    case OpClassMethodCall:

        /* the args */
        n1 = tos;

        /* mark start of created objects */
        pushCreateStack( 0 );

        /* the args */
        eval( node->right );

        argCount = (int)(tos - n1);
        me = 0;
        runMethod( node->left->value.symbol->klass, node->value.string );

        /* destroy created objects */
        clearCreateStack();

        /* drop result? */
        if (node->op == OpClassMethodCall) {
            dropTos();
        }

        break;

    case OpClose:
        if (node->left == NULL) {
            fileCloseAll();
        } else {
            eval( node->left );
            i = (int)popNumber();
            fileClose( i );
        }
        break;

    case OpCmp:
        eval( node->left );
        eval( node->right );

        switch(getStackType(tos)) {
        case DATA_NUMBER:
            numberCompare( node->value.iValue, 1 );
            break;

        case DATA_STRING:
            stringCompare( node->value.iValue, 1 );
            break;

        default:
            ePrintf( Runtime, "opCmp: can't handle datatype" );

        }
        break;

    case OpComma:

        /* optimized for linked lists */
        while (1) {
            /* exit flag set? */
            if (exitForFlag != 0 ||
                exitRoutineFlag != 0 ||
                exitDoFlag != 0 ||
                exitWhileFlag != 0 ||
                continueFlag ) {
                break;
            }

            if (node->left != NULL ) {
                eval( node->left );
            }

            /* end of list? */
            if (node->right == NULL ) {
                break;

            /* linked list? */
            } else if (node->right->op == OpComma) {
                node = node->right;

            /* not a list */
            } else {
                eval( node->right );
                break;
            }
        }
        break;

    case OpConcat:
        eval( node->left );
        eval( node->right );
        basConcat();
        break;

    case OpConstGet:
        s = node->value.symbol;
        i = s->stackPos;
        /* this better not be indirected! */
        switch (stack[i].datatype) {
        case DATA_STRING:
            pushString( stack[i].value.string );
            break;

        case DATA_NUMBER:
            pushNumber( stack[i].value.number );
            break;

        default:
            ePrintf( Runtime, "Can't fetch Const type %s",
                datumName[stack[i].datatype] );
            break;
        }
        break;

    case OpConstSet:
        s = node->value.symbol;
        eval( node->left );
        switch (stack[tos].datatype) {
        case DATA_STRING:
            stack[s->stackPos].datatype = DATA_STRING;
            stack[s->stackPos].value.string = stack[tos].value.string;
            stack[tos].datatype = DATA_NUMBER;
            tos--;
            break;

        case DATA_NUMBER:
            stack[s->stackPos].datatype = DATA_NUMBER;
            stack[s->stackPos].value.number = stack[tos].value.number;
            tos--;
            break;

        default:
            ePrintf( Runtime, "Can't set Const to %s", datumName[stack[tos].datatype] );
            break;
        }
        break;

    case OpDelete:
        eval( node->left );
        runDestructor( (int)popNumber(), OpDelete );
        break;

    case OpDestroy:
        eval( node->left );
        runDestructor( (int)popNumber(), OpDestroy );
        break;

    case OpContinue:
        continueFlag = 1;
        break;

    case OpDiv:
        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        if (n2 == 0.0) {
            ePrintf( Runtime, "Division by zero" );
        }

        pushNumber( n1 / n2 );
        break;

    case OpDo:
        while (1) {
            /* test */
            eval( node->left );
            /*if (!popNumber()){
                break;
            }*/

            /* code */
            eval( node->right );
	    //printf("exitDoFlag:%d\n",exitDoFlag);
            if (exitDoFlag != 0) {
                exitDoFlag = 0;
                break;
            }
	    else if (continueFlag) {
                continueFlag = 0;
            }
        }
        break;

    case OpEnd:
        eShutdown(0);
        break;

    case OpErase:
        if (node->left == NULL) {
            /* erase entire array */
            eraseArray( node->value.symbol );
        } else {
            /* evaluate the indexes */
            eval( node->left );

            /* erase single element from array */
            eraseArrayElement( node->value.symbol );
        }
        break;

    case OpExitDo:
        exitDoFlag = 1;
        break;

    case OpExitFor:
        exitForFlag = 1;
        break;

    case OpExitRoutine:
	currentScope=oldScope[oldScopeP--];
        exitRoutineFlag = 1;
        break;

    case OpExitWhile:
        exitWhileFlag = 1;
        break;

    case OpFloat:
        pushNumber( node->value.fValue );
        break;

    case OpFor:
        s = node->value.symbol;
        eval( node->left );
        n2 = popNumber();
        n1 = popNumber();

        /* initial value */
        pushNumber( n3 );
        setVar( s );

        for( n3=n1; n3 <= n2; n3++ ) {
            /* set loop variable */
            pushNumber( n3 );
            setVar( s );

            /* run code */
            eval( node->right );

            /* special exit condition? */
            if (exitForFlag) {
                exitForFlag = 0;
                break;
            } else if (continueFlag) {
                continueFlag = 0;
            }

            /* get loop value (in case it changed) */
            getVar( s );
            n3 = popNumber();

        }
        break;

    case OpForEach:
        /* variable to assign */
        s = node->value.symbol;

        /* array to read from */
        a = getArray( node->left->value.symbol );

        /* iterate through keys */
        i = 0;
        /* put key on stack, or exit */
        while (getDynamicKey( a, i )) {

            /* assign to variable */
            setVar( s );

            /* run block */
            eval( node->right );

            /* next */
            i += 1;
        }
        break;


    case OpForStep:
        s = node->value.symbol;
        eval( node->left );
        n3 = popNumber();       /* step  */
        n2 = popNumber();       /* end   */
        n1 = popNumber();       /* start */

        /* which direction? */
        if (n3 > 0) {
            n2 += ALLOWABLE_ERROR;
            for( n4=n1; n2 >= n4; n4 += n3 ) {
                /* set loop variable */
                pushNumber( n4 );
                setVar( s );

                /* run code */
                eval( node->right );

                /* special exit condition? */
                if (exitForFlag) {
                    exitForFlag = 0;
                    break;
                } else if (continueFlag) {
                    continueFlag = 0;
                }

                /* get loop value (in case it changed) */
                getVar( s );
                n4 = popNumber();

            }
        } else {
            n2 -= ALLOWABLE_ERROR;
            for( n4=n1; n2 <= n4; n4 += n3 ) {
                /* set loop variable */
                pushNumber( n4 );
                setVar( s );

                /* run code */
                eval( node->right );

                /* special exit condition? */
                if (exitForFlag) {
                    exitForFlag = 0;
                    break;
                } else if (continueFlag) {
                    continueFlag = 0;
                }

                /* get loop value (in case it changed) */
                getVar( s );
                n4 = popNumber();

            }
        }

        break;

    case OpFunction:
    case OpFunctionCall:
        callFunction( node );
        break;

    case OpInitArray:
        if (node->left == NULL) {
            createDynamicArray( node->value.symbol );
        } else {
            eval( node->left );
            createStaticArray( node->value.symbol );
        }
        break;

    case OpInput:
        if (node->value.iValue == 1) {
            eval( node->left );
            i = (int)popNumber();

            string1 = fileLineInput( i );
            pushString( string1  );

        } else {
            /* command line */
            ePrintf( Runtime, "Input statement is not currently supported" );

        }
        break;

    case OpInt:
        pushNumber( node->value.iValue );
        break;

    case OpMethod:
    case OpMethodCall:

        /* the index */
        eval( node->left );
        n1 = popNumber();

        /* method name */
        string1 = node->value.string;

        /* mark start of created objects */
        pushCreateStack( 0 );

        /* args */
        n2 = tos;
        eval( node->right );
        argCount = (int)(tos - n2);

        /* resolve and run method */
        resolveMethod( (int)n1, string1 );

        /* drop result? */
        if (node->op == OpMethodCall) {
            dropTos();
        }

        /* destroy created objects */
        clearCreateStack();

        break;

    case OpMod:
        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        //pushNumber( (long)n1 % (long)n2 );
        pushNumber( fmod(n1,n2) );
        
        break;

    case OpMul:
        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        pushNumber( n1 * n2 );
        break;

    case OpOpen:
        /* file name */
        eval( node->left );
        string1 = popString();

        /* mode */
        i = node->value.iValue;

        /* file number */
        eval( node->right );
        n1 = popNumber();

        fileOpen( string1, i, (int)n1 );
        free( string1 );

        break;

    case OpOr:
        /* short circuit */
        eval( node->left );
        if (popNumber()) {
            pushNumber( (Number)1 );
        } else {
            eval( node->right );
            if (popNumber()) {
                pushNumber( (Number)1 );
            } else {
                pushNumber( (Number)0 );
            }
        }
        break;

    case OpOrBits:
        eval( node->left );
        eval( node->right);
        i = popNumber();
        j = popNumber();
        pushNumber( i | j );
        break;

    case OpIDiv:
        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        /* check for division by zero */
        if (n2 == 0.0) {
            ePrintf( Runtime, "Division by zero" );
        }

        pushNumber( floor(n1 / n2) );
        break;

    case OpIf:
        n = node->left;

        /* test */
        eval( n->left );
        n1 = popNumber();
        if (n1 != 0) {
            /* true portion */
            eval( n->right );
        } else {
            /* false portion */
            eval( node->right );
        }
        break;

    case OpIfTrue:
        ePrintf( Runtime, "OpIfTrue: internal error" );
        break;

    case OpIn:
        /* evaluate key */
        eval( node->left );

        /* look for it in array */
        pushNumber( inArray( node->value.symbol ) );

        break;

    case OpInv:
        ePrintf( Runtime, "Inv is not implemented yet" );
        break;

    case OpNegate:
        eval( node->left );
        n1 = popNumber();
        pushNumber( -n1 );
        break;

    case OpNew:
    case OpNewTmp:

        /* mark start of created objects */
        pushCreateStack( 0 );

        /* the args */
        n1 = tos;
        eval( node->left );
        argCount = (int)(tos - n1);
        runMethod( node->value.symbol->klass, "new" );

        /* destroy created objects *before* adding new object to stack */
        clearCreateStack();

        /* add new object to create stack? */
        if (node->op == OpNewTmp) {
            /* track on stack */
            copyStackItem( tos );
            pushCreateStack( (int)popNumber() );
        }

        break;

    case OpNoOp:
        break;

    case OpNot:
        eval( node->left );
        n1 = popNumber();
        pushNumber( !n1 );
        break;

    case OpPower:
        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        pushNumber( pow( n1, n2 ) );
        break;

    case OpPrint:
        if (node->left == NULL) {
            i = 0;
        } else {
            eval( node->left );
            i = (int)popNumber();
        }

        node = node->right;


        /* empty print statement */
        if (node == NULL) {
            if (i==0) {
                eConsole("\n");
            } else {
                filePrintString( i, "\n" );
            }
        }

        /* process nodes */
        while(node != NULL) {

            /* data value */
            if (node->left != NULL) {
                eval( node->left );
                string1 = popString();
                if (i==0) {
                    eConsole("%s", string1 );
                } else {
                    filePrintString( i, string1 );
                }
                eFree( string1 );
            }

            /* field delimiter */
            switch (node->value.iValue) {
            case PRINT_TAB:
                if (i==0) {
                    eConsole("\t");
                } else {
                    filePrintString( i, "\t" );
                }
                break;
            case PRINT_NEWLINE:
                if (i==0) {
                    eConsole("\n");
                } else {
                    filePrintString( i, "\n" );
                }
                break;
            default:
                /* no action */
                break;
            }

            /* link */
            node = node->right;

        }
        break;


    case OpReturnValue:
        eval( node->left );
        setReturn();
        exitRoutineFlag = 1;
        break;


    case OpReturnSetValue:
        eval( node->left );
        setReturn();
        break;

    case OpShl:
        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        pushNumber( (long)n1 << (long)n2 );
        break;

    case OpShr:
        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        pushNumber( (long)n1 >> (long)n2 );
        break;

    case OpString:
        pushStringCopy( node->value.string );
        break;

    case OpSub:

        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        pushNumber( n1 - n2 );
        break;

    case OpUndefined:
        ePrintf( Runtime, "Opcode is undefined" );
        break;

    case OpVar:
        /* check type */
        getVar( node->value.symbol );
        if (getStackType(tos) == DATA_UNDEFINED) {
            ePrintf( Runtime, "the value of %s is undefined",
                node->value.symbol->name );
        }
        break;

    case OpWhile:
        while (1) {
            /* test */
            eval( node->left );
            if (!popNumber()){
                break;
            }

            /* code */
            eval( node->right );

            if (exitWhileFlag != 0) {
                exitWhileFlag = 0;
                break;

            } else if (continueFlag) {
                continueFlag = 0;
            }
        }
        break;


    case OpXor:
        eval( node->left );
        eval( node->right );

        n2 = popNumber();
        n1 = popNumber();

        pushNumber( (long)n1 ^ (long)n2 );
        break;

    default:
        ePrintf( Runtime, "Unknown Opcode: %d", node->op );

    }
}
Пример #3
0
extern void freeRoutineResources (void)
{
	if (CurrentDirectory != NULL)
		eFree (CurrentDirectory);
}
Пример #4
0
extern void freeTagFileResources (void)
{
	if (TagFile.directory != NULL)
		eFree (TagFile.directory);
	vStringDelete (TagFile.vLine);
}
Пример #5
0
extern void circularRefCheckerDestroy (struct circularRefChecker * checker)
{
	hashTableDelete (checker->visitTable);
	checker->visitTable = NULL;
	eFree (checker);
}