Exemple #1
0
        private void ProcessLoad(ScriptBuilder sb)
        {
            if (Arguments.Length != 2)
            {
                throw new CompilerException(LineNumber, ERR_INCORRECT_NUMBER);
            }

            if (Arguments[0].IsRegister())
            {
                var reg = Arguments[0].AsRegister();

                if (Arguments[1].IsBytes())
                {
                    sb.EmitLoad(reg, Arguments[1].AsBytes());
                }
                else
                if (Arguments[1].IsBool())
                {
                    sb.EmitLoad(reg, Arguments[1].AsBool());
                }
                else
                if (Arguments[1].IsString())
                {
                    sb.EmitLoad(reg, Arguments[1].AsString());
                }
                else
                if (Arguments[1].IsNumber())
                {
                    sb.EmitLoad(reg, Arguments[1].AsNumber());
                }
                else
                {
                    throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT);
                }
            }
            else
            {
                throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT);
            }
        }
        private void ProcessLoad(ScriptBuilder sb)
        {
            if (Arguments.Length != 2 && Arguments.Length != 3)
            {
                throw new CompilerException(LineNumber, ERR_INCORRECT_NUMBER);
            }

            if (Arguments[0].IsRegister())
            {
                var reg = Arguments[0].AsRegister();

                VMType type = VMType.None;

                if (Arguments.Length == 3)
                {
                    if (!Enum.TryParse(Arguments[2], out type))
                    {
                        throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT);
                    }
                }

                if (Arguments[1].IsBytes())
                {
                    sb.EmitLoad(reg, Arguments[1].AsBytes());
                }
                else
                if (Arguments[1].IsBool())
                {
                    sb.EmitLoad(reg, Arguments[1].AsBool());
                }
                else
                if (Arguments[1].IsString())
                {
                    sb.EmitLoad(reg, Arguments[1].AsString());
                }
                else
                if (Arguments[1].IsNumber())
                {
                    if (type == VMType.Enum)
                    {
                        var num = (uint)Arguments[1].AsNumber();

                        using (var stream = new MemoryStream())
                        {
                            using (var writer = new BinaryWriter(stream))
                            {
                                writer.Write((byte)reg);
                                writer.Write((byte)VMType.Enum);
                                writer.Write((byte)4);

                                var numBytes = BitConverter.GetBytes(num);
                                writer.Write(numBytes);
                            }

                            var bytes = stream.ToArray();
                            sb.Emit(Opcode.LOAD, bytes);
                        }
                    }
                    else
                    if (type != VMType.None)
                    {
                        throw new CompilerException(LineNumber, ERR_INVALID_TYPE);
                    }
                    else
                    {
                        sb.EmitLoad(reg, Arguments[1].AsNumber());
                    }
                }
                else
                {
                    throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT);
                }
            }
            else
            {
                throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT);
            }
        }
        public void TranslateInstruction(Instruction i)
        {
            switch (i.op)
            {
            case Instruction.Opcode.Label:
            {
                _output.EmitLabel(i.target);
                break;
            }

            case Instruction.Opcode.Push:
            {
                var reg = FetchRegister(i.target);
                _output.EmitPush(reg);
                break;
            }

            case Instruction.Opcode.Pop:
            {
                var reg = FetchRegister(i.target);
                _output.Emit(VM.Opcode.POP, new byte[] { reg });
                break;
            }

            case Instruction.Opcode.Assign:
            {
                if (i.literal != null)
                {
                    switch (i.literal.kind)
                    {
                    case LiteralKind.String:
                    {
                        var reg = FetchRegister(i.target);
                        _output.EmitLoad(reg, (string)i.literal.value);
                        break;
                    }

                    case LiteralKind.Boolean:
                    {
                        var reg = FetchRegister(i.target);
                        _output.EmitLoad(reg, (bool)i.literal.value);
                        break;
                    }

                    case LiteralKind.Integer:
                    {
                        var        reg = FetchRegister(i.target);
                        BigInteger val;

                        if (i.literal.value is BigInteger)
                        {
                            val = (BigInteger)i.literal.value;
                        }
                        else
                        if (i.literal.value is int)
                        {
                            val = new BigInteger((int)i.literal.value);
                        }
                        else
                        {
                            throw new Exception($"Could not convert {i.literal.value.GetType().Name} to BigInteger");
                        }

                        _output.EmitLoad(reg, val);
                        break;
                    }

                    default: throw new Exception("Unsuported " + i.literal.kind);
                    }
                }
                else
                {
                    var src = i.varName != null?FetchRegister(i.varName) : FetchRegister(i.a.target);

                    var dst = FetchRegister(i.target);
                    _output.EmitMove(src, dst);
                }
                break;
            }

            case Instruction.Opcode.Add: { InsertOp(i, VM.Opcode.ADD); break; }

            case Instruction.Opcode.Sub: { InsertOp(i, VM.Opcode.SUB); break; }

            case Instruction.Opcode.Mul: { InsertOp(i, VM.Opcode.MUL); break; }

            case Instruction.Opcode.Div: { InsertOp(i, VM.Opcode.DIV); break; }

            case Instruction.Opcode.Mod: { InsertOp(i, VM.Opcode.MOD); break; }

            case Instruction.Opcode.Shr: { InsertOp(i, VM.Opcode.SHR); break; }

            case Instruction.Opcode.Shl: { InsertOp(i, VM.Opcode.SHL); break; }

            case Instruction.Opcode.Equals: { InsertOp(i, VM.Opcode.EQUAL); break; }

            case Instruction.Opcode.LessThan: { InsertOp(i, VM.Opcode.LT); break; }

            case Instruction.Opcode.GreaterThan: { InsertOp(i, VM.Opcode.GT); break; }

            case Instruction.Opcode.LessOrEqualThan: { InsertOp(i, VM.Opcode.LTE); break; }

            case Instruction.Opcode.GreaterOrEqualThan: { InsertOp(i, VM.Opcode.GTE); break; }


            case Instruction.Opcode.Jump: InsertJump(i, VM.Opcode.JMP); break;

            case Instruction.Opcode.JumpIfFalse: InsertJump(i, VM.Opcode.JMPNOT); break;

            case Instruction.Opcode.JumpIfTrue: InsertJump(i, VM.Opcode.JMPIF); break;

            case Instruction.Opcode.Call:
                _output.EmitCall(i.target, 8);     // TODO remove hardcoded register count
                break;

            case Instruction.Opcode.Return:
                _output.Emit(VM.Opcode.RET);
                break;

            case Instruction.Opcode.Negate:
            {
                var src = FetchRegister(i.a.target);
                var dst = FetchRegister(i.target);
                _output.Emit(VM.Opcode.NEGATE, new byte[] { src, dst }); break;
            }

            case Instruction.Opcode.Not:
            {
                var src = FetchRegister(i.a.target);
                var dst = FetchRegister(i.target);
                _output.Emit(VM.Opcode.NOT, new byte[] { src, dst }); break;
            }

            default: throw new Exception("Unsupported Opcode: " + i.op);
            }
        }