compileArrayIndexToReg(opts) {
        let scope              = this._scope;
        let program            = this._program;
        let indexAndExpression = tokenUtils.getIndexAfterTokenPairs(opts.expression, opts.index, [t.TOKEN_BRACKET_OPEN, t.TOKEN_BRACKET_CLOSE]);
        let indexExpression    = indexAndExpression.expression;
        opts.index = indexAndExpression.index - 1;
        if (indexExpression.length === 1) {
            let indexToken = indexExpression[0];
            opts.token = indexToken;
            if (indexToken.cls === t.TOKEN_NUMBER) {
                if (indexToken.value > 0) {
                    if (indexToken.value >= opts.maxArraySize) {
                        throw errors.createError(err.ARRAY_INDEX_OUT_OF_RANGE, indexToken, 'Array index out of range.');
                    }
                    helper.addToReg(this._program, opts.reg, $.T_NUM_C, indexToken.value * opts.identifierSize * opts.arraySize);
                } else if (indexToken.value < 0) {
                    throw errors.createError(err.INVALID_ARRAY_INDEX, indexToken, 'Invalid array index.');
                }
                if (!opts.identifier.getPointer() && opts.identifier.getType().typePointer &&
                    !opts.forWriting && (opts.selfPointerStackOffset === false)) {
                    opts = this.compileDerefecencePointer(opts);
                }
            } else if (indexToken.cls === t.TOKEN_IDENTIFIER) {
                opts.indexIdentifier = helper.findIdentifier(this._scope, indexToken);
                opts.paramType       = opts.indexIdentifier.getGlobal() ? $.T_NUM_G : $.T_NUM_L;
                opts.indexToken      = indexToken;
                if (opts.arraySize === 1) {
                    if (opts.identifierSize === 1) {
                        opts = this.compileAddIndexIdentifierToReg(opts);
                    } else {
                        this.addVarIndexToReg(opts);
                    }
                } else if (opts.identifierSize === 1) {
                    // Calculate the array offset...
                    this.compileCalculateAndAddIndexToReg(opts);
                } else {
                    this.addVarIndexToReg(opts);
                }
            }
        } else {
            // The index is a math expression...
            let lastRecordType     = this._lastRecordType;
            let mathExpressionNode = new MathExpression({
                    varExpression: this,
                    compiler:      this._compiler,
                    program:       program,
                    scope:         scope
                }).compile({tokens: indexExpression}, this._compiler.getPass());
            scope.incStackOffset();
            if (!mathExpressionNode.getValue()) {
                program.addCommand($.CMD_SET, $.T_NUM_L, scope.getStackOffset(), $.T_NUM_G, $.REG_PTR);
            }
            scope.incStackOffset();
            mathExpressionNode.compile(t.LEXEME_NUMBER);
            this._lastRecordType = lastRecordType;
            if (this._compiler.getRangeCheck()) {
                program
                    .addCommand(
                        $.CMD_SET, $.T_NUM_G, $.REG_RANGE0, $.T_NUM_C, opts.maxArraySize,
                        $.CMD_SET, $.T_NUM_G, $.REG_RANGE1, $.T_NUM_L, scope.getStackOffset(),
                        $.CMD_MOD, $.T_NUM_C, 0,            $.T_NUM_C, 0
                    )
                    .addInfoToLastCommand({token: indexExpression[0], scope: this._scope});
            }
            if (opts.identifierSize * opts.arraySize > 1) {
                program.addCommand($.CMD_MUL, $.T_NUM_L, scope.getStackOffset(), $.T_NUM_C, opts.identifierSize * opts.arraySize);
            }
            scope.decStackOffset();
            if (!mathExpressionNode.getValue()) {
                program.addCommand($.CMD_SET, $.T_NUM_G, $.REG_PTR, $.T_NUM_L, scope.getStackOffset());
            }
            scope.decStackOffset();
            helper.addToReg(this._program, opts.reg, $.T_NUM_L, this._scope.getStackOffset() + 2);
            if (!opts.identifier.getPointer() && opts.identifier.getType().typePointer &&
                !opts.forWriting && (opts.selfPointerStackOffset === false)) {
                opts = this.compileDerefecencePointer(opts);
            }
        }
    }
/**
     * Compile the index of an array and add the offset to a register
    **/
Compile the index of an array and add the offset to a register
Compile the index of an array and add the offset to a register
compileArrayIndexToReg(opts) {
        let scope              = this._scope;
        let program            = this._program;
        let indexAndExpression = tokenUtils.getIndexAfterTokenPairs(opts.expression, opts.index, [t.TOKEN_BRACKET_OPEN, t.TOKEN_BRACKET_CLOSE]);
        let indexExpression    = indexAndExpression.expression;
        opts.index = indexAndExpression.index - 1;
        if (indexExpression.length === 1) {
            let indexToken = indexExpression[0];
            opts.token = indexToken;
            if (indexToken.cls === t.TOKEN_NUMBER) {
                if (indexToken.value > 0) {
                    if (indexToken.value >= opts.maxArraySize) {
                        throw errors.createError(err.ARRAY_INDEX_OUT_OF_RANGE, indexToken, 'Array index out of range.');
                    }
                    helper.addToReg(this._program, opts.reg, $.T_NUM_C, indexToken.value * opts.identifierSize * opts.arraySize);
                } else if (indexToken.value < 0) {
                    throw errors.createError(err.INVALID_ARRAY_INDEX, indexToken, 'Invalid array index.');
                }
                if (!opts.identifier.getPointer() && opts.identifier.getType().typePointer &&
                    !opts.forWriting && (opts.selfPointerStackOffset === false)) {
                    opts = this.compileDerefecencePointer(opts);
                }
            } else if (indexToken.cls === t.TOKEN_IDENTIFIER) {
                opts.indexIdentifier = helper.findIdentifier(this._scope, indexToken);
                opts.paramType       = opts.indexIdentifier.getGlobal() ? $.T_NUM_G : $.T_NUM_L;
                opts.indexToken      = indexToken;
                if (opts.arraySize === 1) {
                    if (opts.identifierSize === 1) {
                        opts = this.compileAddIndexIdentifierToReg(opts);
                    } else {
                        this.addVarIndexToReg(opts);
                    }
                } else if (opts.identifierSize === 1) {
                    this.compileCalculateAndAddIndexToReg(opts);
                } else {
                    this.addVarIndexToReg(opts);
                }
            }
        } else {
            let lastRecordType     = this._lastRecordType;
            let mathExpressionNode = new MathExpression({
                    varExpression: this,
                    compiler:      this._compiler,
                    program:       program,
                    scope:         scope
                }).compile({tokens: indexExpression}, this._compiler.getPass());
            scope.incStackOffset();
            if (!mathExpressionNode.getValue()) {
                program.addCommand($.CMD_SET, $.T_NUM_L, scope.getStackOffset(), $.T_NUM_G, $.REG_PTR);
            }
            scope.incStackOffset();
            mathExpressionNode.compile(t.LEXEME_NUMBER);
            this._lastRecordType = lastRecordType;
            if (this._compiler.getRangeCheck()) {
                program
                    .addCommand(
                        $.CMD_SET, $.T_NUM_G, $.REG_RANGE0, $.T_NUM_C, opts.maxArraySize,
                        $.CMD_SET, $.T_NUM_G, $.REG_RANGE1, $.T_NUM_L, scope.getStackOffset(),
                        $.CMD_MOD, $.T_NUM_C, 0,            $.T_NUM_C, 0
                    )
                    .addInfoToLastCommand({token: indexExpression[0], scope: this._scope});
            }
            if (opts.identifierSize * opts.arraySize > 1) {
                program.addCommand($.CMD_MUL, $.T_NUM_L, scope.getStackOffset(), $.T_NUM_C, opts.identifierSize * opts.arraySize);
            }
            scope.decStackOffset();
            if (!mathExpressionNode.getValue()) {
                program.addCommand($.CMD_SET, $.T_NUM_G, $.REG_PTR, $.T_NUM_L, scope.getStackOffset());
            }
            scope.decStackOffset();
            helper.addToReg(this._program, opts.reg, $.T_NUM_L, this._scope.getStackOffset() + 2);
            if (!opts.identifier.getPointer() && opts.identifier.getType().typePointer &&
                !opts.forWriting && (opts.selfPointerStackOffset === false)) {
                opts = this.compileDerefecencePointer(opts);
            }
        }
    }
compileArrayIndexToReg ( opts ) { let scope = this . _scope ; let program = this . _program ; let indexAndExpression = tokenUtils . getIndexAfterTokenPairs ( opts . expression , opts . index , [ t . TOKEN_BRACKET_OPEN , t . TOKEN_BRACKET_CLOSE ] ) ; let indexExpression = indexAndExpression . expression ; opts . index = indexAndExpression . index - 1 ; if ( indexExpression . length === 1 ) { let indexToken = indexExpression [ 0 ] ; opts . token = indexToken ; if ( indexToken . cls === t . TOKEN_NUMBER ) { if ( indexToken . value > 0 ) { if ( indexToken . value >= opts . maxArraySize ) { throw errors . createError ( err . ARRAY_INDEX_OUT_OF_RANGE , indexToken , 'Array index out of range.' ) ; } helper . addToReg ( this . _program , opts . reg , $ . T_NUM_C , indexToken . value * opts . identifierSize * opts . arraySize ) ; } else if ( indexToken . value < 0 ) { throw errors . createError ( err . INVALID_ARRAY_INDEX , indexToken , 'Invalid array index.' ) ; } if ( ! opts . identifier . getPointer ( ) && opts . identifier . getType ( ) . typePointer && ! opts . forWriting && ( opts . selfPointerStackOffset === false ) ) { opts = this . compileDerefecencePointer ( opts ) ; } } else if ( indexToken . cls === t . TOKEN_IDENTIFIER ) { opts . indexIdentifier = helper . findIdentifier ( this . _scope , indexToken ) ; opts . paramType = opts . indexIdentifier . getGlobal ( ) ? $ . T_NUM_G : $ . T_NUM_L ; opts . indexToken = indexToken ; if ( opts . arraySize === 1 ) { if ( opts . identifierSize === 1 ) { opts = this . compileAddIndexIdentifierToReg ( opts ) ; } else { this . addVarIndexToReg ( opts ) ; } } else if ( opts . identifierSize === 1 ) { this . compileCalculateAndAddIndexToReg ( opts ) ; } else { this . addVarIndexToReg ( opts ) ; } } } else { let lastRecordType = this . _lastRecordType ; let mathExpressionNode = new MathExpression ( { varExpression : this , compiler : this . _compiler , program : program , scope : scope } ) . compile ( { tokens : indexExpression } , this . _compiler . getPass ( ) ) ; scope . incStackOffset ( ) ; if ( ! mathExpressionNode . getValue ( ) ) { program . addCommand ( $ . CMD_SET , $ . T_NUM_L , scope . getStackOffset ( ) , $ . T_NUM_G , $ . REG_PTR ) ; } scope . incStackOffset ( ) ; mathExpressionNode . compile ( t . LEXEME_NUMBER ) ; this . _lastRecordType = lastRecordType ; if ( this . _compiler . getRangeCheck ( ) ) { program . addCommand ( $ . CMD_SET , $ . T_NUM_G , $ . REG_RANGE0 , $ . T_NUM_C , opts . maxArraySize , $ . CMD_SET , $ . T_NUM_G , $ . REG_RANGE1 , $ . T_NUM_L , scope . getStackOffset ( ) , $ . CMD_MOD , $ . T_NUM_C , 0 , $ . T_NUM_C , 0 ) . addInfoToLastCommand ( { token : indexExpression [ 0 ] , scope : this . _scope } ) ; } if ( opts . identifierSize * opts . arraySize > 1 ) { program . addCommand ( $ . CMD_MUL , $ . T_NUM_L , scope . getStackOffset ( ) , $ . T_NUM_C , opts . identifierSize * opts . arraySize ) ; } scope . decStackOffset ( ) ; if ( ! mathExpressionNode . getValue ( ) ) { program . addCommand ( $ . CMD_SET , $ . T_NUM_G , $ . REG_PTR , $ . T_NUM_L , scope . getStackOffset ( ) ) ; } scope . decStackOffset ( ) ; helper . addToReg ( this . _program , opts . reg , $ . T_NUM_L , this . _scope . getStackOffset ( ) + 2 ) ; if ( ! opts . identifier . getPointer ( ) && opts . identifier . getType ( ) . typePointer && ! opts . forWriting && ( opts . selfPointerStackOffset === false ) ) { opts = this . compileDerefecencePointer ( opts ) ; } } }
Compile the index of an array and add the offset to a register
Compile the index of an array and add the offset to a register
// Calculate the array offset... // The index is a math expression...