예제 #1
0
            private static unsafe Jsm.ExecutableSegment MakeScript(Operation *operation, UInt16 count)
            {
                List <JsmInstruction> instructions = new List <JsmInstruction>(count / 2);
                LabeledStack          stack        = new LabeledStack();
                LabelBuilder          labelBuilder = new LabelBuilder(count);

                for (Int32 i = 0; i < count; i++)
                {
                    Jsm.Opcode opcode    = operation->Opcode;
                    Int32      parameter = operation->Parameter;
                    operation++;

                    stack.CurrentLabel = i;
                    IJsmExpression expression = Jsm.Expression.TryMake(opcode, parameter, stack);
                    if (expression != null)
                    {
                        stack.Push(expression);
                        continue;
                    }

                    JsmInstruction instruction = JsmInstruction.TryMake(opcode, parameter, stack);
                    if (instruction != null)
                    {
                        labelBuilder.TraceInstruction(i, stack.CurrentLabel, new IndexedInstruction(instructions.Count, instruction));
                        instructions.Add(instruction);
                        continue;
                    }

                    throw new NotSupportedException(opcode.ToString());
                }

                if (stack.Count != 0)
                {
                    throw new InvalidProgramException("Stack unbalanced.");
                }

                if (!(instructions.First() is LBL))
                {
                    throw new InvalidProgramException("Script must start with a label.");
                }

                if (!(instructions.Last() is IRET))
                {
                    throw new InvalidProgramException("Script must end with a return.");
                }

                // Switch from opcodes to instructions
                HashSet <Int32> labelIndices = labelBuilder.Commit();

                // Merge similar instructions
                instructions = InstructionMerger.Merge(instructions, labelIndices);

                // Combine instructions to logical blocks
                IReadOnlyList <Jsm.IJsmControl> controls = Jsm.Control.Builder.Build(instructions);

                // Arrange instructions by segments and return root
                return(Jsm.Segment.Builder.Build(instructions, controls));
            }
예제 #2
0
        public static JsmInstruction TryMake(Jsm.Opcode opcode, Int32 parameter, IStack <IJsmExpression> stack)
        {
            if (Factories.TryGetValue(opcode, out var make))
            {
                return(make(parameter, stack));
            }

            return(null);
        }
예제 #3
0
            private static IJsmExpression TryMakeInternal(Jsm.Opcode opcode, int param, IStack <IJsmExpression> stack)
            {
                switch (opcode)
                {
                case Jsm.Opcode.PSHN_L:
                    return(new PSHN_L(param));

                case Jsm.Opcode.PSHAC:
                    return(new PSHAC(new Jsm.FieldObjectId(param)));

                case Jsm.Opcode.PSHI_L:
                    return(new PSHI_L(new ScriptResultId(param)));

                case Jsm.Opcode.PSHM_B:
                    return(new PSHM_B(new GlobalVariableId <byte>(param)));

                case Jsm.Opcode.PSHM_W:
                    return(new PSHM_W(new GlobalVariableId <ushort>(param)));

                case Jsm.Opcode.PSHM_L:
                    return(new PSHM_L(new GlobalVariableId <uint>(param)));

                case Jsm.Opcode.PSHSM_B:
                    return(new PSHSM_B(new GlobalVariableId <sbyte>(param)));

                case Jsm.Opcode.PSHSM_W:
                    return(new PSHSM_W(new GlobalVariableId <short>(param)));

                case Jsm.Opcode.PSHSM_L:
                    return(new PSHSM_L(new GlobalVariableId <int>(param)));

                case Jsm.Opcode.CAL:
                    return(CAL.Read(param, stack));
                    //case Opcode.MovieReady:
                    //    return new Instruction.MovieReady(stack.Pop(), stack.Pop());
                }

                return(null);
            }
            private static IJsmExpression TryMakeInternal(Jsm.Opcode opcode, Int32 param, IStack <IJsmExpression> stack)
            {
                switch (opcode)
                {
                case Jsm.Opcode.PSHN_L:
                    return(new PSHN_L(param));

                case Jsm.Opcode.PSHAC:
                    return(new PSHAC(new Jsm.FieldObjectId(param)));

                case Jsm.Opcode.PSHI_L:
                    return(new PSHI_L(new ScriptResultId(param)));

                case Jsm.Opcode.PSHM_B:
                    return(new PSHM_B(new GlobalVariableId <Byte>(param)));

                case Jsm.Opcode.PSHM_W:
                    return(new PSHM_W(new GlobalVariableId <UInt16>(param)));

                case Jsm.Opcode.PSHM_L:
                    return(new PSHM_L(new GlobalVariableId <UInt32>(param)));

                case Jsm.Opcode.PSHSM_B:
                    return(new PSHSM_B(new GlobalVariableId <SByte>(param)));

                case Jsm.Opcode.PSHSM_W:
                    return(new PSHSM_W(new GlobalVariableId <Int16>(param)));

                case Jsm.Opcode.PSHSM_L:
                    return(new PSHSM_L(new GlobalVariableId <Int32>(param)));

                case Jsm.Opcode.CAL:
                    return(CAL.Read(param, stack));
                    //case Opcode.MOVIEREADY:
                    //    return new Instruction.MOVIEREADY(stack.Pop(), stack.Pop());
                }

                return(null);
            }
예제 #5
0
            public static IJsmExpression TryMake(Jsm.Opcode opcode, int param, IStack <IJsmExpression> stack)
            {
                var result = TryMakeInternal(opcode, param, stack);

                return(result?.Evaluate(StatelessServices.Instance)); // Simplify the expression
            }