Exemple #1
0
        public override void EmitGet(InstructionWriter writer, AllocatedLocal dest)
        {
            var leftStack  = _leftStack ?? dest;
            var rightStack = _rightStack ?? dest;

            if (_left.GetSingleType() != _type || _right.GetSingleType() != _type)
            {
                //Needs conversion in MOV and ISTC.
                throw new NotImplementedException();
            }
            if (leftStack.Offset > 255 || rightStack.Offset > 255 || dest.Offset > 255)
            {
                throw new NotImplementedException();
            }

            //  emit leftStack = _left
            //  ISFC/ISTC dest, leftStack, exitLabel
            //  emit rightStack = _right
            //  MOV dest, rightStack
            //exitLabel:

            var exitLabel = new LabelStatementSyntaxNode();

            _left.EmitPrep(writer);
            _left.EmitGet(writer, leftStack);
            writer.WriteUUS(_opcode, dest.Offset, leftStack.Offset, 0);
            writer.AddLabelFix(exitLabel, InstructionWriter.FixUUSJump);
            _right.EmitPrep(writer);
            _right.EmitGet(writer, rightStack);
            //We already wrote to dest. No need to MOV.
            Debug.Assert(rightStack.Offset == dest.Offset);
            writer.MarkLabel(exitLabel);
        }
Exemple #2
0
        public override void Emit(InstructionWriter writer)
        {
            var restartLabel = new LabelStatementSyntaxNode();
            var exitLabel    = new LabelStatementSyntaxNode();

            if (_e1Stack.Offset > 255 || _loopVar.Offset > 255)
            {
                throw new NotImplementedException();
            }

            //Calc expressions.
            _e1.EmitPrep(writer);
            _e1.EmitGet(writer, _e1Stack);
            _e2.EmitPrep(writer);
            _e2.EmitGet(writer, _e2Stack);
            _e3.EmitPrep(writer);
            _e3.EmitGet(writer, _e3Stack);

            //Init instruction (check type, check exit condition).
            writer.WriteUSx(_initOp, _e1Stack.Offset, 0);
            writer.AddLabelFix(exitLabel, InstructionWriter.FixUSxJump);

            //This is where we restart.
            writer.MarkLabel(restartLabel);

            //Start of the actual block (creates upvals).
            _forBlock.EmitUpvalLists(writer);
            //Copy hidden control variable to the visible loop var.
            writer.WriteUUU(Opcodes.MOV, _loopVar.Offset, _e1Stack.Offset, 0);

            //Emit inner aux block.
            _forBlock.EmitStatements(writer);

            //Loop instruction.
            writer.WriteUSx(_loopOp, _e1Stack.Offset, 0);
            writer.AddLabelFix(restartLabel, InstructionWriter.FixUSxJump);

            writer.MarkLabel(exitLabel);
        }
Exemple #3
0
        public override void EmitGet(InstructionWriter writer, AllocatedLocal dest)
        {
            //The two special cases.
            if (_mode == CalcMode.LeftToDest)
            {
                if (_right.TryGetFromStack(out var rightStack) && rightStack.Offset == dest.Offset)
                {
                    _left.EmitPrep(writer);
                    _left.EmitGet(writer, _rightTemp.Value);
                    EmitInstruction(writer, dest, _rightTemp.Value, rightStack);
                    return;
                }
            }
            else if (_mode == CalcMode.RightToDest)
            {
                if (_left.TryGetFromStack(out var leftStack) && leftStack.Offset == dest.Offset)
                {
                    _right.EmitPrep(writer);
                    _right.EmitGet(writer, _leftTemp.Value);
                    EmitInstruction(writer, dest, leftStack, _leftTemp.Value);
                    return;
                }
            }

            switch (_mode)
            {
            case CalcMode.LeftToDest:
            {
                _left.EmitPrep(writer);
                _left.EmitGet(writer, dest);
                if (!_right.TryGetFromStack(out var rightStack))
                {
                    rightStack = _rightTemp.Value;
                    _right.EmitPrep(writer);
                    _right.EmitGet(writer, rightStack);
                }
                EmitInstruction(writer, dest, dest, rightStack);
                break;
            }

            case CalcMode.RightToDest:
            {
                if (!_left.TryGetFromStack(out var leftStack))
                {
                    leftStack = _leftTemp.Value;
                    _left.EmitPrep(writer);
                    _left.EmitGet(writer, leftStack);
                }
                _right.EmitPrep(writer);
                _right.EmitGet(writer, dest);
                EmitInstruction(writer, dest, leftStack, dest);
                break;
            }

            case CalcMode.Normal:
            {
                if (!_left.TryGetFromStack(out var leftStack))
                {
                    leftStack = _leftTemp.Value;
                    _left.EmitPrep(writer);
                    _left.EmitGet(writer, leftStack);
                }
                if (!_right.TryGetFromStack(out var rightStack))
                {
                    rightStack = _rightTemp.Value;
                    _right.EmitPrep(writer);
                    _right.EmitGet(writer, rightStack);
                }
                EmitInstruction(writer, dest, leftStack, rightStack);
                break;
            }
            }
        }
Exemple #4
0
 public override void Emit(InstructionWriter writer)
 {
     _expr.EmitPrep(writer);
     _expr.EmitDiscard(writer);
 }