Esempio n. 1
0
 public ProgramContext(bool interpreterContext)
 {
     Program = new List<Opcode>();
     InstructionPointer = 0;
     Triggers = new List<int>();
     builder = interpreterContext ? new ProgramBuilderInterpreter() : new ProgramBuilder();
     flyByWire = new Dictionary<string, bool>();
 }
Esempio n. 2
0
        public void OnLoad(ConfigNode node)
        {
            try
            {
                var scriptBuilder = new StringBuilder();

                foreach (ConfigNode contextNode in node.GetNodes("context"))
                {
                    foreach (ConfigNode varNode in contextNode.GetNodes("variables"))
                    {
                        foreach (ConfigNode.Value value in varNode.values)
                        {
                            string varValue = PersistenceUtilities.DecodeLine(value.value);
                            scriptBuilder.AppendLine(string.Format("set {0} to {1}.", value.name, varValue));
                        }
                    }
                }

                if (shared.ScriptHandler == null || scriptBuilder.Length <= 0) return;

                var programBuilder = new ProgramBuilder();
                // TODO: figure out how to store the filename and reload it for arg 1 below:
                // (Possibly all of OnLoad needs work because it never seemed to bring
                // back the context fully right anyway, which is why this hasn't been
                // addressed yet).
                try
                {
                    SafeHouse.Logger.Log("Parsing Context:\n\n" + scriptBuilder);

                    // TODO - make this set up compiler options and pass them in properly, so we can detect built-ins properly.
                    // (for the compiler to detect the difference between a user function call and a built-in, it needs to be
                    // passed the FunctionManager object from Shared.)
                    // this isn't fixed mainly because this OnLoad() code is a major bug fire already anyway and needs to be
                    // fixed, but that's way out of scope for the moment:
                    programBuilder.AddRange(shared.ScriptHandler.Compile("reloaded file", 1, scriptBuilder.ToString()));
                    List<Opcode> program = programBuilder.BuildProgram();
                    RunProgram(program, true);
                }
                catch (NullReferenceException ex)
                {
                    SafeHouse.Logger.Log("program builder failed on load. " + ex.Message);
                }
            }
            catch (Exception e)
            {
                if (shared.Logger != null) shared.Logger.Log(e);
            }
        }
Esempio n. 3
0
File: Misc.cs Progetto: gisikw/KOS
        public override void Execute(SharedObjects shared)
        {
            // run() is strange.  It needs two levels of args - the args to itself, and the args it is meant to
            // pass on to the program it's invoking.  First, these are the args to run itself:
            object volumeId = PopValueAssert(shared, true);
            string fileName = PopValueAssert(shared, true).ToString();
            AssertArgBottomAndConsume(shared);

            // Now the args it is going to be passing on to the program:
            var progArgs = new List<Object>();
            int argc = CountRemainingArgs(shared);
            for (int i = 0; i < argc; ++i)
                progArgs.Add(PopValueAssert(shared, true));
            AssertArgBottomAndConsume(shared);

            if (shared.VolumeMgr == null) return;
            if (shared.VolumeMgr.CurrentVolume == null) throw new Exception("Volume not found");

            ProgramFile file = shared.VolumeMgr.CurrentVolume.GetByName(fileName, true);
            if (file == null) throw new Exception(string.Format("File '{0}' not found", fileName));
            if (shared.ScriptHandler == null) return;

            if (volumeId != null)
            {
                Volume targetVolume = shared.VolumeMgr.GetVolume(volumeId);
                if (targetVolume != null)
                {
                    if (shared.ProcessorMgr != null)
                    {
                        string filePath = string.Format("{0}/{1}", shared.VolumeMgr.GetVolumeRawIdentifier(targetVolume), fileName);
                        var options = new CompilerOptions { LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager };
                        List<CodePart> parts = shared.ScriptHandler.Compile(filePath, 1, file.StringContent, "program", options);
                        var builder = new ProgramBuilder();
                        builder.AddRange(parts);
                        List<Opcode> program = builder.BuildProgram();
                        shared.ProcessorMgr.RunProgramOn(program, targetVolume);
                    }
                }
                else
                {
                    throw new KOSFileException("Volume not found");
                }
            }
            else
            {
                // clear the "program" compilation context
                shared.ScriptHandler.ClearContext("program");
                string filePath = shared.VolumeMgr.GetVolumeRawIdentifier(shared.VolumeMgr.CurrentVolume) + "/" + fileName;
                var options = new CompilerOptions { LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager };
                var programContext = ((CPU)shared.Cpu).SwitchToProgramContext();

                List<CodePart> codeParts;
                if (file.Category == FileCategory.KSM)
                {
                    string prefix = programContext.Program.Count.ToString();
                    codeParts = shared.VolumeMgr.CurrentVolume.LoadObjectFile(filePath, prefix, file.BinaryContent);
                }
                else
                {
                    try
                    {
                        codeParts = shared.ScriptHandler.Compile(filePath, 1, file.StringContent, "program", options);
                    }
                    catch (Exception)
                    {
                        // If it died due to a compile error, then we won't really be able to switch to program context
                        // as was implied by calling Cpu.SwitchToProgramContext() up above.  The CPU needs to be
                        // told that it's still in interpreter context, or else it fails to advance the interpreter's
                        // instruction pointer and it will just try the "call run()" instruction again:
                        shared.Cpu.BreakExecution(false);
                        throw;
                    }
                }
                programContext.AddParts(codeParts);
            }

            // Because run() returns FIRST, and THEN the CPU jumps to the new program's first instruction that it set up,
            // it needs to put the return stack in a weird order.  Its return value needs to be buried UNDER the args to the
            // program it's calling:
            UsesAutoReturn = false;

            shared.Cpu.PushStack(0); // dummy return that all functions have.

            // Put the args for the program being called back on in the same order they were in before (so read the list backward):
            shared.Cpu.PushStack(new KOSArgMarkerType());
            for (int i = argc - 1; i >= 0; --i)
                shared.Cpu.PushStack(progArgs[i]);
        }