Esempio n. 1
0
 public static PacmanValue Ret(int address, PacmanEnvironmentFrame environmentFrame, int profileAddress)
 {
     return new PacmanValue(PacmanTag.Ret) { IntValue = address, EnvironmentFrameValue = environmentFrame, ProfileAddress = profileAddress };
 }
Esempio n. 2
0
        private static PacmanEnvironmentFrame GetEnvironmentFrame(
            PacmanEnvironmentFrame currentEnvironmentFrame,
            int n)
        {
            var ans = currentEnvironmentFrame;
            for (var i = 0; i < n; ++i)
            {
                ans = ans.Parent;
            }

            if (!ans.IsValid)
            {
                throw new Exception(); // TODO
            }

            return ans;
        }
Esempio n. 3
0
 public static PacmanValue Closure(int address, PacmanEnvironmentFrame environmentFrame)
 {
     return new PacmanValue(PacmanTag.Closure) { IntValue = address, EnvironmentFrameValue = environmentFrame };
 }
Esempio n. 4
0
        private static PacmanValue ExecuteAi(
            List<PacmanInstruction> code,
            int pc,
            PacmanEnvironmentFrame initialEnvironmentFrame,
            int tick)
        {
            const bool PROFILE = false;

            var iter = 0;
            var dataStack = new List<PacmanValue>();
            var controlStack = new List<PacmanValue>() { new PacmanValue(PacmanTag.Stop) };
            var currentEnvironmentFrame = initialEnvironmentFrame;
            var profileData = new Dictionary<string, int>();
            var funcCallData = new Dictionary<int, int>();

            while (true)
            {
                if (PROFILE)
                {
                    var profileKey = string.Join(", ", controlStack
                        .Where(i => i.Tag == PacmanTag.Ret)
                        .Select(i => i.ProfileAddress.ToString())
                        .LastOrDefault());
                    int profileValue;
                    profileData.TryGetValue(profileKey, out profileValue);
                    profileData[profileKey] = profileValue + 1;
                }

                ++iter;
                PacmanValue xx, yy;
                PacmanEnvironmentFrame frame, newFrame;
                PacmanInstruction inst = code[pc];
                int funcCallDataValue;

                switch (inst.Opcode)
                {
                    case PacmanOpcode.Ldc:
                        dataStack.Add(PacmanValue.Int(inst.Operands[0]));
                        ++pc;
                        break;
                    case PacmanOpcode.Ld:
                        frame = GetEnvironmentFrame(currentEnvironmentFrame, inst.Operands[0]);
                        dataStack.Add(frame.Values[inst.Operands[1]]);
                        ++pc;
                        break;
                    case PacmanOpcode.Add:
                        DoMath(dataStack, (x, y) => x + y);
                        ++pc;
                        break;
                    case PacmanOpcode.Sub:
                        DoMath(dataStack, (x, y) => x - y);
                        ++pc;
                        break;
                    case PacmanOpcode.Mul:
                        DoMath(dataStack, (x, y) => x * y);
                        ++pc;
                        break;
                    case PacmanOpcode.Div:
                        DoMath(dataStack, (x, y) => (int)Math.Floor((double)x / (double)y));
                        ++pc;
                        break;
                    case PacmanOpcode.Ceq:
                        DoMath(dataStack, (x, y) => x == y ? 1 : 0);
                        ++pc;
                        break;
                    case PacmanOpcode.Cgt:
                        DoMath(dataStack, (x, y) => x > y ? 1 : 0);
                        ++pc;
                        break;
                    case PacmanOpcode.Cgte:
                        DoMath(dataStack, (x, y) => x >= y ? 1 : 0);
                        ++pc;
                        break;
                    case PacmanOpcode.Atom:
                        xx = dataStack.Pop();
                        dataStack.Add(PacmanValue.Int(xx.Tag == PacmanTag.Int ? 1 : 0));
                        ++pc;
                        break;
                    case PacmanOpcode.Cons:
                        yy = dataStack.Pop();
                        xx = dataStack.Pop();
                        dataStack.Add(PacmanValue.Cons(xx, yy));
                        ++pc;
                        break;
                    case PacmanOpcode.Car:
                        xx = dataStack.Pop();
                        xx.VerifyTag(PacmanTag.Cons);
                        dataStack.Add(xx.Item1);
                        ++pc;
                        break;
                    case PacmanOpcode.Cdr:
                        xx = dataStack.Pop();
                        xx.VerifyTag(PacmanTag.Cons);
                        dataStack.Add(xx.Item2);
                        ++pc;
                        break;
                    case PacmanOpcode.Sel:
                    case PacmanOpcode.Tsel:
                        xx = dataStack.Pop();
                        xx.VerifyTag(PacmanTag.Int);
                        if (inst.Opcode == PacmanOpcode.Sel)
                        {
                            controlStack.Add(PacmanValue.Join(pc + 1));
                        }
                        pc = xx.IntValue == 0 ? inst.Operands[1] : inst.Operands[0];
                        break;
                    case PacmanOpcode.Join:
                        xx = controlStack.Pop();
                        xx.VerifyTag(PacmanTag.Join);
                        pc = xx.IntValue;
                        break;
                    case PacmanOpcode.Ldf:
                        dataStack.Add(PacmanValue.Closure(inst.Operands[0], currentEnvironmentFrame));
                        ++pc;
                        break;
                    case PacmanOpcode.Tap:
                    case PacmanOpcode.Ap:
                        xx = dataStack.Pop();
                        xx.VerifyTag(PacmanTag.Closure);

                        newFrame = new PacmanEnvironmentFrame()
                        {
                            Parent = currentEnvironmentFrame,
                            IsValid = true,
                            Values = new List<PacmanValue>()
                        };

                        for (var i = 0; i < inst.Operands[0]; ++i)
                        {
                            newFrame.Values.Add(dataStack.Pop());
                        }
                        newFrame.Values.Reverse();

                        if (inst.Opcode == PacmanOpcode.Ap)
                        {
                            controlStack.Add(PacmanValue.Ret(pc + 1, currentEnvironmentFrame, xx.IntValue));
                            if (PROFILE)
                            {
                                funcCallData.TryGetValue(xx.IntValue, out funcCallDataValue);
                                funcCallData[xx.IntValue] = funcCallDataValue + 1;
                            }
                        }

                        currentEnvironmentFrame = newFrame;
                        pc = xx.IntValue;
                        break;
                    case PacmanOpcode.Rtn:
                        xx = controlStack.Pop();
                        if (xx.Tag == PacmanTag.Stop)
                        {
                            Program.LogDebug(tick, "iters = {0}", iter);
                            if (PROFILE)
                            {
                                Program.LogProfileInfo(tick, profileData, funcCallData);
                            }
                            return dataStack.Pop();
                        }
                        xx.VerifyTag(PacmanTag.Ret);
                        pc = xx.IntValue;
                        currentEnvironmentFrame = xx.EnvironmentFrameValue;
                        break;
                    case PacmanOpcode.Dum:
                        newFrame = new PacmanEnvironmentFrame()
                        {
                            Parent = currentEnvironmentFrame,
                            IsValid = false,
                            Values = new List<PacmanValue>()
                        };

                        for (var i = 0; i < inst.Operands[0]; ++i)
                        {
                            newFrame.Values.Add(null);
                        }

                        currentEnvironmentFrame = newFrame;
                        ++pc;
                        break;
                    case PacmanOpcode.Rap:
                    case PacmanOpcode.Trap:
                        xx = dataStack.Pop();
                        xx.VerifyTag(PacmanTag.Closure);
                        newFrame = xx.EnvironmentFrameValue;
                        if (newFrame.IsValid ||
                            newFrame.Values.Count != inst.Operands[0] ||
                            currentEnvironmentFrame != newFrame)
                        {
                            throw new Exception(); // TODO
                        }

                        newFrame.Values.Clear();
                        for (var i = 0; i < inst.Operands[0]; ++i)
                        {
                            newFrame.Values.Add(dataStack.Pop());
                        }
                        newFrame.Values.Reverse();

                        if (inst.Opcode == PacmanOpcode.Rap)
                        {
                            controlStack.Add(PacmanValue.Ret(pc + 1, currentEnvironmentFrame.Parent, xx.IntValue));

                            if (PROFILE)
                            {
                                funcCallData.TryGetValue(xx.IntValue, out funcCallDataValue);
                                funcCallData[xx.IntValue] = funcCallDataValue + 1;
                            }
                        }

                        newFrame.IsValid = true;
                        currentEnvironmentFrame = newFrame;
                        pc = xx.IntValue;
                        break;
                    case PacmanOpcode.Stop:
                        return dataStack.Pop();
                    case PacmanOpcode.St:
                        frame = GetEnvironmentFrame(currentEnvironmentFrame, inst.Operands[0]);
                        xx = dataStack.Pop();
                        frame.Values[inst.Operands[1]] = xx;
                        ++pc;
                        break;
                    case PacmanOpcode.Dbug:
                        xx = dataStack.Pop();
                        Program.LogDebug(tick, "DBUG: '{0}'", xx);
                        ++pc;
                        break;
                    case PacmanOpcode.Brk:
                        ++pc;
                        break;
                    default:
                        throw new Exception(); // TODO
                }
            }
        }