public static VMRoutine Assemble(VM vm, BHAV bhav) { var context = vm.Context; var routine = new VMRoutine(); routine.Locals = bhav.Locals; routine.Arguments = bhav.Args; routine.Type = bhav.Type; routine.VM = vm; routine.Rti = new VMFunctionRTI { Name = bhav.ChunkLabel }; VMInstruction[] instructions = new VMInstruction[bhav.Instructions.Length]; for (var i = 0; i < bhav.Instructions.Length; i++) { var bhavInstruction = bhav.Instructions[i]; var instruction = new VMInstruction(); instruction.Index = (byte)i; instruction.Opcode = bhavInstruction.Opcode; instruction.Operand = bhavInstruction.Operand; instruction.FalsePointer = bhavInstruction.FalsePointer; instruction.TruePointer = bhavInstruction.TruePointer; instruction.Function = routine; /** Routine call **/ if (instruction.Opcode >= 256) { var operand = new VMSubRoutineOperand(); operand.Read(bhavInstruction.Operand); instruction.Operand = operand; } else { var primitive = context.GetPrimitive(instruction.Opcode); if (primitive != null) { if (primitive.OperandModel != null) { VMPrimitiveOperand operand = (VMPrimitiveOperand)Activator.CreateInstance(primitive.OperandModel); operand.Read(bhavInstruction.Operand); instruction.Operand = operand; } } } instructions[i] = instruction; } routine.Instructions = instructions; return routine; }
private void ExecuteSubRoutine(VMStackFrame frame, BHAV bhav, GameIffResource codeOwner, VMSubRoutineOperand args) { if (bhav == null){ Pop(VMPrimitiveExitCode.ERROR); return; } System.Diagnostics.Debug.WriteLine("Invoke: " + bhav.ChunkLabel); System.Diagnostics.Debug.WriteLine(""); var routine = frame.VM.Assemble(bhav); var childFrame = new VMStackFrame { Routine = routine, Caller = frame.Caller, Callee = frame.Callee, CodeOwner = codeOwner, StackObject = frame.StackObject }; childFrame.Args = new short[routine.Arguments]; for (var i = 0; i < childFrame.Args.Length; i++){ var argValue = args.Arguments[i]; if (argValue == -1) { /** TODO: Is this the right rule? Maybe a flag decides when to copy from temp? **/ argValue = TempRegisters[i]; } childFrame.Args[i] = argValue; } Push(childFrame); }