Пример #1
0
        public void Run(IntermediateOutput code, string function)
        {
            SheepFunction?sheepFunction = null;

            foreach (var f in code.Functions)
            {
                if (string.Equals(f.Name, function, StringComparison.OrdinalIgnoreCase))
                {
                    sheepFunction = f;
                    break;
                }
            }

            if (sheepFunction.HasValue == false)
            {
                throw new Exception("Unknown function");
            }

            SheepContext c = new SheepContext();

            c.FullCode          = code;
            c.CodeBuffer        = new SheepCodeBuffer(new System.IO.MemoryStream(sheepFunction.Value.Code));
            c.FunctionOffset    = sheepFunction.Value.CodeOffset;
            c.InstructionOffset = 0;

            prepareVariables(c);
            _context.Push(c);

            execute(c);

            _context.Pop();
        }
Пример #2
0
 void prepareVariables(SheepContext context)
 {
     for (int i = 0; i < context.FullCode.Symbols.Count; i++)
     {
         if (context.FullCode.Symbols[i].Type == SheepSymbolType.Int)
         {
             context.Variables.Add(new StackItem(SheepSymbolType.Int, context.FullCode.Symbols[i].InitialIntValue));
         }
         else if (context.FullCode.Symbols[i].Type == SheepSymbolType.Float)
         {
             context.Variables.Add(new StackItem(SheepSymbolType.Float, context.FullCode.Symbols[i].InitialIntValue));
         }
         else if (context.FullCode.Symbols[i].Type == SheepSymbolType.String)
         {
             context.Variables.Add(new StackItem(SheepSymbolType.String, context.FullCode.Symbols[i].InitialStringValue));
         }
         else
         {
             throw new Exception("Unsupported variable type");
         }
     }
 }
Пример #3
0
        void execute(SheepContext context)
        {
            context.CodeBuffer.BaseStream.Seek(context.InstructionOffset, System.IO.SeekOrigin.Begin);

            while (!context.Suspended && context.CodeBuffer.BaseStream.Position < context.CodeBuffer.BaseStream.Length)
            {
                if (context.InstructionOffset != context.CodeBuffer.BaseStream.Position)
                {
                    context.CodeBuffer.BaseStream.Seek(context.InstructionOffset, System.IO.SeekOrigin.Begin);
                }

                SheepInstruction instruction = (SheepInstruction)context.CodeBuffer.ReadByte();
                context.InstructionOffset++;

                int   iparam1, iparam2;
                float fparam1, fparam2;

                switch (instruction)
                {
                case SheepInstruction.SitnSpin:
                    break;

                case SheepInstruction.Yield:
                    throw new NotImplementedException();

                case SheepInstruction.CallSysFunctionV:
                    context.InstructionOffset += 4;
                    callVoidFunction(this, context.Stack, context.FullCode.Imports, context.CodeBuffer.ReadInt32());
                    break;

                case SheepInstruction.CallSysFunctionI:
                    context.InstructionOffset += 4;
                    callIntFunction(this, context.Stack, context.FullCode.Imports, context.CodeBuffer.ReadInt32());
                    break;

                case SheepInstruction.CallSysFunctionF:
                case SheepInstruction.CallSysFunctionS:
                    throw new NotImplementedException();

                case SheepInstruction.Branch:
                case SheepInstruction.BranchGoto:
                    context.InstructionOffset = context.CodeBuffer.ReadUInt32() - context.FunctionOffset;
                    break;

                case SheepInstruction.BranchIfZero:
                    if (context.Stack.Peek().Type == SheepSymbolType.Int)
                    {
                        if (context.Stack.Peek().IValue == 0)
                        {
                            context.InstructionOffset = context.CodeBuffer.ReadUInt32() - context.FunctionOffset;
                        }
                        else
                        {
                            context.CodeBuffer.ReadInt32();     // throw it away
                            context.InstructionOffset += 4;
                        }
                        context.Stack.Pop();
                    }
                    else
                    {
                        throw new Exception("expected integer on stack");
                    }
                    break;

                case SheepInstruction.BeginWait:
                    context.InWaitSection = true;
                    break;

                case SheepInstruction.EndWait:
                    context.InWaitSection = false;
                    // TODO: call end wait callback
                    break;

                case SheepInstruction.ReturnV:
                    return;

                case SheepInstruction.StoreI:
                    storeI(context.Stack, context.Variables, context.CodeBuffer.ReadInt32());
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.StoreF:
                    storeF(context.Stack, context.Variables, context.CodeBuffer.ReadInt32());
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.StoreS:
                    storeS(context.Stack, context.Variables, context.CodeBuffer.ReadInt32());
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.LoadI:
                    loadI(context.Stack, context.Variables, context.CodeBuffer.ReadInt32());
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.LoadF:
                    loadF(context.Stack, context.Variables, context.CodeBuffer.ReadInt32());
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.LoadS:
                    throw new NotImplementedException();

                case SheepInstruction.PushI:
                    context.Stack.Push(new StackItem(SheepSymbolType.Int, context.CodeBuffer.ReadInt32()));
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.PushF:
                    context.Stack.Push(new StackItem(SheepSymbolType.Float, context.CodeBuffer.ReadSingle()));
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.PushS:
                    context.Stack.Push(new StackItem(SheepSymbolType.String, context.CodeBuffer.ReadInt32()));
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.Pop:
                    context.Stack.Pop();
                    break;

                case SheepInstruction.AddI:
                    addI(context.Stack);
                    break;

                case SheepInstruction.AddF:
                    addF(context.Stack);
                    break;

                case SheepInstruction.SubtractI:
                    subI(context.Stack);
                    break;

                case SheepInstruction.SubtractF:
                    subF(context.Stack);
                    break;

                case SheepInstruction.MultiplyI:
                    mulI(context.Stack);
                    break;

                case SheepInstruction.MultiplyF:
                    mulF(context.Stack);
                    break;

                case SheepInstruction.DivideI:
                    divI(context.Stack);
                    break;

                case SheepInstruction.DivideF:
                    divF(context.Stack);
                    break;

                case SheepInstruction.NegateI:
                    negI(context.Stack);
                    break;

                case SheepInstruction.NegateF:
                    negF(context.Stack);
                    break;

                case SheepInstruction.IsEqualI:
                    get2Ints(context.Stack, out iparam1, out iparam2);
                    if (iparam1 == iparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsEqualF:
                    get2Floats(context.Stack, out fparam1, out fparam2);
                    if (fparam1 == fparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.NotEqualI:
                    get2Ints(context.Stack, out iparam1, out iparam2);
                    if (iparam1 != iparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.NotEqualF:
                    get2Floats(context.Stack, out fparam1, out fparam2);
                    if (fparam1 != fparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsGreaterI:
                    get2Ints(context.Stack, out iparam1, out iparam2);
                    if (iparam1 > iparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsGreaterF:
                    get2Floats(context.Stack, out fparam1, out fparam2);
                    if (fparam1 > fparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsLessI:
                    get2Ints(context.Stack, out iparam1, out iparam2);
                    if (iparam1 < iparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsLessF:
                    get2Floats(context.Stack, out fparam1, out fparam2);
                    if (fparam1 < fparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsGreaterEqualI:
                    get2Ints(context.Stack, out iparam1, out iparam2);
                    if (iparam1 >= iparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsGreaterEqualF:
                    get2Floats(context.Stack, out fparam1, out fparam2);
                    if (fparam1 >= fparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsLessEqualI:
                    get2Ints(context.Stack, out iparam1, out iparam2);
                    if (iparam1 <= iparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IsLessEqualF:
                    get2Floats(context.Stack, out fparam1, out fparam2);
                    if (fparam1 <= fparam2)
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 1));
                    }
                    else
                    {
                        context.Stack.Push(new StackItem(SheepSymbolType.Int, 0));
                    }
                    break;

                case SheepInstruction.IToF:
                    itof(context.Stack, context.CodeBuffer.ReadInt32());
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.FToI:
                    ftoi(context.Stack, context.CodeBuffer.ReadInt32());
                    context.InstructionOffset += 4;
                    break;

                case SheepInstruction.And:
                    andi(context.Stack);
                    break;

                case SheepInstruction.Or:
                    ori(context.Stack);
                    break;

                case SheepInstruction.Not:
                    noti(context.Stack);
                    break;

                case SheepInstruction.GetString:
                    if (context.Stack.Peek().Type != SheepSymbolType.String)
                    {
                        throw new Exception("Expected string on stack");
                    }
                    break;

                case SheepInstruction.DebugBreakpoint:
                    throw new Exception("DebugBreakpoint instruction not supported yet.");

                default:
                    throw new Exception("Unknown instruction");
                }
            }
        }