示例#1
0
    IEnumerable <LazyString> MethodHeaderActions(MethodInfo method)
    {
        var firstActions = new LazyString[]
        {
            () => $"Abort If (Not({FunctionCondition(method)()}));",
            () => "Wait(0, Abort When False);",
            SetGlobal(Variables.Temporary, JumpOffsetStack.GetLastElement(0)),
        };

        LazyString actionCountStr = () =>
        {
            var instruction = method.Instructions.First();
            var nextInChain = FindNextSkipChain(method, instruction);
            var actionCount = nextInChain == null ? 99999999 : CalcNumActionsToSkip(method, nextInChain) - CalcNumActionsToSkip(method, instruction);
            return(actionCount.ToString());
        };

        var jumpToTarget = new[]
        {
            SetGlobal(Variables.Temporary2, GetGlobal(Variables.Temporary)),
            SetGlobal(Variables.Temporary, Subtract(GetGlobal(Variables.Temporary), Add(actionCountStr, () => "4"))),
            SkipIf(
                NotEqual(GetGlobal(Variables.Temporary2), () => "0"),
                Min(GetGlobal(Variables.Temporary2), Add(actionCountStr, () => "1"))),
        };

        return(firstActions.Concat(JumpOffsetStack.Pop(1)).Concat(jumpToTarget));
    }
示例#2
0
    void ConvertMethodToRule(StringWriter ruleWriter, MethodInfo method)
    {
        var writer    = new StringWriter();
        var writeLine = (Action <object>)(str => writer.WriteLine($"        {str}"));

        writeLine("// Header");
        foreach (var line in MethodHeaderActions(method))
        {
            writeLine(line());
        }
        writeLine("");

        var actionCount = 0;

        writeLine("// Body");
        foreach (var instr in method.Instructions)
        {
            var numActions = ToWorkshopActions(method, instr).Count();
            writeLine($"    // [{actionCount}] {instr}");
            actionCount += numActions;
            foreach (var line in ToWorkshopActions(method, instr))
            {
                writeLine(line());
            }
        }

        var workshopEventAttr = GetCustomAttribute <WorkshopEventAttribute>(method);

        if (workshopEventAttr != null)
        {
            Debug.Assert(method.Definition.Parameters.Count == 3, $"Event function {method.Definition.Name} must have the following parameter list: (Player eventPlayer, float eventDamage, bool eventWasCriticalHit)");
            ruleWriter.WriteLine(GenerateRule(
                                     $"Event Task for: {method.Definition.Name}",
                                     GetCodeName(typeof(Workshop.Event).GetMember(workshopEventAttr.m_event.ToString()).First()),
                                     $"",
                                     PushTaskForEventMethod(method)()));
        }

        ruleWriter.WriteLine(GenerateRule(
                                 method.Definition.Name,
                                 "Ongoing - Global;",
                                 $"{FunctionCondition(method)()} == True;",
                                 writer.ToString()));
    }
示例#3
0
    private bool CheckAddCondition(FunctionCondition condition)
    {
        if (condition is FunctionCondition)
        {
            if (condition is FreeCondition)
            {
                freeCondition = (FreeCondition)condition;
                return(true);
            }
        }

        return(true);
    }
示例#4
0
    IEnumerable <LazyString> TaskRunnerActions(MethodDefinition updateMethod)
    {
        yield return(() => $"Abort If (Not({FunctionCondition(0)()}));");

        yield return(() => "Wait(0, Ignore Condition);");

        foreach (var action in TaskQueue.PopTaskTo(Variables.Temporary))
        {
            yield return(action);
        }

        var functionId = ArraySubscript(GetGlobal(Variables.Temporary), 0);

        // if there's no function, call Update (if it exists, otherwise just loop)
        var updateCallActions = updateMethod == null ? new LazyString[0] : Impl_Call_CustomMethod_Direct(updateMethod);

        yield return(SkipIf(NotEqual(functionId, () => "0"), () => (updateCallActions.Count() + 1).ToString()));

        foreach (var action in updateCallActions)
        {
            yield return(action);
        }
        yield return(() => "Loop;");

        // push event params onto stack before calling
        foreach (var action in ParameterStack.Push(ArraySlice(GetGlobal(Variables.Temporary), () => "1", () => "3")))
        {
            yield return(action);
        }

        foreach (var action in Impl_Call_CustomMethod_Direct(functionId, m_maxNumLocalVariables))
        {
            yield return(action);
        }

        yield return(() => "Loop;");
    }
示例#5
0
        public void BuiltinTest()
        {
            Production prod = new Production();

            prod.Label = "find-stack-of-two-blocks-to-the-left-of-a-red-block";
            Variable x = new Variable("x");
            Variable y = new Variable("y");
            Variable z = new Variable("z");

            prod.AddConditionToLHS(new PositiveCondition("C1", x, "on", y));
            prod.AddConditionToLHS(new PositiveCondition("C2", y, "left of", z));
            prod.AddConditionToLHS(new PositiveCondition("C3", z, "color", "red"));

            FunctionCondition funCond = new FunctionCondition("F4", x, new FuncTerm("funcEquals", new funcEquals()), new StringTerm("B1"));

            funCond.ConditionType = ConditionType.Function;
            prod.AddConditionToLHS(funCond);

            prod.AddConditionToRHS(new AssertCondition("C4", x, "is", "on top"));

            Rete rete = new Rete();

            rete.AddProduction(prod);

            NetworkPrinter printer = new NetworkPrinter();

            rete.DummyTopNode.Accept(printer);

            using (StreamWriter writer = new StreamWriter(@"C:\Temp\TestBuiltin.log", false))
            {
                writer.Write(printer.Output);
                writer.WriteLine();
                writer.WriteLine();
                writer.WriteLine();
                writer.WriteLine();
                writer.WriteLine("-----------------------------------------------");
                writer.Flush();
            }

            WME wme1 = new WME("W1");

            wme1.Fields[0] = "B1";
            wme1.Fields[1] = "on";
            wme1.Fields[2] = "B2";
            rete.AddWME(wme1);

            WME wme2 = new WME("W2");

            wme2.Fields[0] = "B1";
            wme2.Fields[1] = "on";
            wme2.Fields[2] = "B3";
            rete.AddWME(wme2);

            WME wme3 = new WME("W3");

            wme3.Fields[0] = "B1";
            wme3.Fields[1] = "color";
            wme3.Fields[2] = "red";
            rete.AddWME(wme3);

            WME wme4 = new WME("W4");

            wme4.Fields[0] = "B2";
            wme4.Fields[1] = "on";
            wme4.Fields[2] = "table";
            rete.AddWME(wme4);

            WME wme5 = new WME("W5");

            wme5.Fields[0] = "B2";
            wme5.Fields[1] = "left of";
            wme5.Fields[2] = "B3";
            rete.AddWME(wme5);

            WME wme6 = new WME("W6");

            wme6.Fields[0] = "B2";
            wme6.Fields[1] = "color";
            wme6.Fields[2] = "blue";
            rete.AddWME(wme6);

            WME wme7 = new WME("W7");

            wme7.Fields[0] = "B3";
            wme7.Fields[1] = "left of";
            wme7.Fields[2] = "B4";
            rete.AddWME(wme7);

            WME wme8 = new WME("W8");

            wme8.Fields[0] = "B3";
            wme8.Fields[1] = "on";
            wme8.Fields[2] = "table";
            rete.AddWME(wme8);

            WME wme9 = new WME("W9");

            wme9.Fields[0] = "B3";
            wme9.Fields[1] = "color";
            wme9.Fields[2] = "red";
            rete.AddWME(wme9);

            printer = new NetworkPrinter();
            rete.DummyTopNode.Accept(printer);

            using (StreamWriter writer = new StreamWriter(@"C:\Temp\TestBuiltin.log", true))
            {
                writer.WriteLine();
                writer.WriteLine();
                writer.WriteLine();
                writer.WriteLine();
                writer.Write(printer.Output);
                writer.Flush();
            }

            Assert.IsTrue(prod.InferredFacts.Count == 1, "Wrong number of conclusions");
            Assert.IsTrue(rete.WorkingMemory.Count == 9, "Bad");
        }
示例#6
0
    public string TranspileToRules(string source)
    {
        var references = new[]
        {
            MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
            MetadataReference.CreateFromFile(Path.Combine(
                                                 Path.GetDirectoryName(typeof(object).Assembly.Location),
                                                 "System.Runtime.dll")),
            MetadataReference.CreateFromFile("C:\\projects\\IL2Workshop\\WorkshopStub\\bin\\Debug\\netcoreapp3.0\\WorkshopStub.dll"),
        };

        var options     = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Release);
        var syntaxTree  = SyntaxFactory.ParseSyntaxTree(source);
        var compilation = CSharpCompilation.Create(
            "AsmBuild",
            new[] { syntaxTree },
            references,
            options);
        var semanticModel = compilation.GetSemanticModel(syntaxTree);

        var substituter        = new MethodSubstituter(semanticModel, m_generatedMethodToWorkshopCode);
        var newRoot            = substituter.Visit(syntaxTree.GetRoot());
        var newTree            = SyntaxFactory.SyntaxTree(newRoot);
        var generatedClassTree = substituter.GetGeneratedClass();

        compilation = compilation.RemoveAllSyntaxTrees();
        compilation = compilation.AddSyntaxTrees(newTree, generatedClassTree);

        Console.WriteLine(generatedClassTree.ToString());

        var result = compilation.Emit("AsmBuild.dll");

        if (!result.Success)
        {
            foreach (var diag in result.Diagnostics)
            {
                Console.WriteLine(diag);
            }
            throw new System.Exception("Fail!");
        }

        var module    = ModuleDefinition.ReadModule("AsmBuild.dll");
        var mainClass = module.GetType("MainClass");
        var methods   = mainClass.Methods;

        GenerateFunctionIds(methods);
        m_maxNumLocalVariables = methods.Max(m => m.Body.Variables.Count);

        var ruleWriter = new StringWriter();

        var staticConstructor     = methods.SingleOrDefault(m => m.Name == ".cctor");
        var mainMethod            = methods.Single(m => m.Name == "Main");
        var entryPointActionsText = EntryPointActions(staticConstructor, mainMethod).Select(a => $"        {a()}").ListToString("\n");

        ruleWriter.WriteLine(GenerateRule("EntryPoint", "Ongoing - Global;", "", entryPointActionsText));

        var updateMethod          = methods.SingleOrDefault(m => m.Name == "Update");
        var taskRunnerActionsText = TaskRunnerActions(updateMethod).Select(a => $"        {a()}").ListToString("\n");

        ruleWriter.WriteLine(GenerateRule("TaskRunner", "Ongoing - Global;", $"{FunctionCondition(0)()} == True;", taskRunnerActionsText));

        foreach (var method in methods)
        {
            var methodInfo = new MethodInfo
            {
                Definition   = method,
                Instructions = method.Body.Instructions.ToList(),
            };

            InsertSkipChainInstructions(methodInfo);

            // TODO: add analyzer to prevent storing un-storable variables on stack (Array, Player, etc)

            Console.WriteLine(method);
            foreach (var instr in methodInfo.Instructions)
            {
                Console.WriteLine(instr);
            }
            Console.WriteLine();

            ConvertMethodToRule(ruleWriter, methodInfo);
        }

        return(ruleWriter.ToString());
    }
示例#7
0
        public void BasicOverrideTest()
        {
            Agenda agenda = new Agenda();

            agenda.ConflictResolutionStrategy = new SalienceResolver();

            Production prod = new Production();

            prod.Label = "Gold Customer";
            Variable customer  = new Variable("customer");
            Variable purchases = new Variable("purchases");

            prod.AddConditionToLHS(new PositiveCondition("C1", customer, "purchases", purchases));
            FunctionCondition gt = new FunctionCondition("C2", purchases, new FuncTerm("funcGreaterThan", new funcGreaterThan()), 10);

            gt.ConditionType = ConditionType.Function;
            prod.AddConditionToLHS(gt);
            AssertCondition rhs = new AssertCondition("R1", customer, "is", "gold");

            rhs.ConditionType = ConditionType.Assert;
            prod.AddConditionToRHS(rhs);
            agenda.AddProduction(prod);

            Production prod1 = new Production();

            prod1.Label = "Platinum Customer";

            prod1.AddConditionToLHS(new PositiveCondition("C1", customer, "purchases", purchases));
            FunctionCondition gt1 = new FunctionCondition("C2", purchases, new FuncTerm("funcGreaterThan", new funcGreaterThan()), 20);

            gt1.ConditionType = ConditionType.Function;
            prod1.AddConditionToLHS(gt1);
            AssertCondition rhs1 = new AssertCondition("R1", customer, "is", "Platinum");

            rhs.ConditionType = ConditionType.Assert;
            prod1.AddConditionToRHS(rhs1);
            agenda.AddProduction(prod1);

            Override me = new Override();

            me.Winner = "Platinum Customer";
            me.Loser  = "Gold Customer";

            agenda.AddOverride(me);

            WME wme1 = new WME("W1");

            wme1.Fields[0] = "joe";
            wme1.Fields[1] = "purchases";
            wme1.Fields[2] = "1";
            agenda.AddFact(wme1);

            WME wme2 = new WME("W2");

            wme2.Fields[0] = "ted";
            wme2.Fields[1] = "purchases";
            wme2.Fields[2] = "10";
            agenda.AddFact(wme2);

            WME wme3 = new WME("W3");

            wme3.Fields[0] = "ed";
            wme3.Fields[1] = "purchases";
            wme3.Fields[2] = "11";
            agenda.AddFact(wme3);

            WME wme4 = new WME("W4");

            wme4.Fields[0] = "phil";
            wme4.Fields[1] = "purchases";
            wme4.Fields[2] = "18";
            agenda.AddFact(wme4);

            WME wme5 = new WME("W5");

            wme5.Fields[0] = "mary";
            wme5.Fields[1] = "purchases";
            wme5.Fields[2] = "22";
            agenda.AddFact(wme5);

            WME wme6 = new WME("W6");

            wme6.Fields[0] = "jane";
            wme6.Fields[1] = "purchases";
            wme6.Fields[2] = "25";
            agenda.AddFact(wme6);

            WME wme7 = new WME("W7");

            wme7.Fields[0] = "fred";
            wme7.Fields[1] = "purchases";
            wme7.Fields[2] = "50";
            agenda.AddFact(wme7);

            WME wme8 = new WME("W8");

            wme8.Fields[0] = "harry";
            wme8.Fields[1] = "purchases";
            wme8.Fields[2] = "55";
            agenda.AddFact(wme8);

            WME wme9 = new WME("W9");

            wme9.Fields[0] = "jon";
            wme9.Fields[1] = "purchases";
            wme9.Fields[2] = "99";
            agenda.AddFact(wme9);

            agenda.Run();

            agenda.VisualizeNetworkToFile(@"C:\Temp\BasicOverrideTest.log", false);

            Assert.IsTrue(agenda.ActivatedRuleCount == 1, "Rule did not fire.");
            Assert.IsTrue(agenda.InferredFacts.Count == 5, "Bad");
        }