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); } }