public static void SolveDoubleJumps(SchemeFunction function) { bool changed = true; var commands = function.Commands; while (changed) { changed = false; for (int i = 0; i < commands.Count; ++i) { ISchemeCommand cmd = commands[i]; if (cmd is CommandJumpBase) { CommandJumpBase jumpCmd = (cmd as CommandJumpBase); int line = jumpCmd.Line; if (line < commands.Count && commands[line] is CommandJump) { CommandJump jumpCmd2 = commands[line] as CommandJump; if (jumpCmd.Line != jumpCmd2.Line) { jumpCmd.SetLine(jumpCmd2.Line); changed = true; } } } } } }
private void Test() { SchemeFunction f = new SchemeFunction(); f.AddCommand(new CommandAddAction("grab")); f.AddCommand(new CommandAddAction("examine")); f.AddCommand(new CommandRemoveAction("grab")); f.AddCommand(new CommandAddAction("drop")); MapObject @object = new MapObject(); @object.Name = "some_object"; @object.Variables.Add(new ObjectVariable("logical", "isDwarf", false)); @object.Variables.Add(new ObjectVariable("logical", "isElf", false)); @object.Scheme = new Scheme("some_scheme"); @object.Scheme.CompiledScheme = new CompiledScheme(); @object.Scheme.CompiledScheme.AddAction(new SchemeFunction("grab")); @object.Scheme.CompiledScheme.AddAction(new SchemeFunction("examine")); @object.Scheme.CompiledScheme.AddAction(new SchemeFunction("drop")); Config config = new Config(); config.AddScheme(@object.Scheme); Game game = new Game(config); game._AddObject(@object); //Execute function on object f.Execute(@object, new Character(), game); }
public override object VisitEnd_of_action([NotNull] scheme_langParser.End_of_actionContext context) { //Add completed action to scheme CompiledScheme.AddAction(currentFunc); currentFunc = null; VariableManager.EndBlock(); return(base.VisitEnd_of_action(context)); }
/* *** */ public Visitor(Scheme scheme, Config config) { Scheme = scheme; Config = config; Scheme.CompiledScheme = CompiledScheme; bodyFunction = new SchemeFunction("_body"); CompiledScheme.SetBody(bodyFunction); currentFunc = bodyFunction; }
public int ExecuteAction(string actionName, Object actor, Game game) { SchemeFunction action = Scheme?.GetFunctionByName(actionName); if (action == null) { throw new GameException("Given action does not exist."); } return(action.Execute(this, actor, game)); }
public static void Optimize(SchemeFunction function) { if (function == null) { return; } SolveDoubleJumps(function); SolveSimpleValueRegs(function); SolveRegisterBuffers(function); SolveDeadCode(function); }
private static void RemoveCommandsAt(SchemeFunction function, HashSet <int> indexes) { var commands = function.Commands; for (int i = commands.Count - 1; i >= 0; --i) { if (indexes.Contains(i)) { commands.RemoveAt(i); DecreaseJumpLocations(commands, i); } } }
public override object VisitInit_block([NotNull] scheme_langParser.Init_blockContext context) { if (CompiledScheme.GetFunctionByName("init") != null) { Errors.Add(new ErrorDescriptor($"This scheme already contains an init block.", context)); } //Sign start of init block currentFunc = new SchemeFunction("init"); VariableManager.NewBlock(); return(base.VisitInit_block(context)); }
public int GetMovementCost(SquareType squareType, Config config) { if (Scheme == null || squareType.ActionName == null || squareType.ActionName == "") { return(config.CharacterConfig.MovementActionPoints); } SchemeFunction action = Scheme.GetFunctionByName(squareType.ActionName); if (action == null) { return(config.CharacterConfig.MovementActionPoints); } return(action.ActionPoints); }
public void ExecuteSquareAction(SquareType squareType, Character actor, Game game) { if (squareType == null || Scheme == null || squareType.ActionName == null || squareType.ActionName == "") { return; } SchemeFunction action = Scheme.GetFunctionByName(squareType.ActionName); if (action == null) { throw new GameException($"No such action in map: {squareType.ActionName}"); } action.Execute(SchemeObject, actor, game); }
private Scheme GetLeverScheme() { Scheme leverScheme = new Scheme(); leverScheme.CompiledScheme = new CompiledScheme(); SchemeFunction use = new SchemeFunction(); use.Name = "use"; use.AddCommand(new CommandOf("ready", "box", "_0")); use.AddCommand(new CommandNot("_0", "_0")); use.AddCommand(new CommandSetOf("ready", "box", "_0")); use.AddCommand(new CommandDesc("LEVER_DESC_2")); leverScheme.CompiledScheme.AddAction(use); return(leverScheme); }
//Returns starting position of each basic block in the given function's code private static HashSet <int> GetBlockPositions(SchemeFunction function) { HashSet <int> positions = new HashSet <int>(); var commands = function.Commands; for (int i = 0; i < commands.Count; ++i) { ISchemeCommand cmd = commands[i]; if (cmd is CommandJumpBase) { int line = ((CommandJumpBase)cmd).Line; positions.Add(line); positions.Add(i + 1); } } return(positions); }
private Scheme GetBoxScheme() { Scheme boxScheme = new Scheme(); boxScheme.CompiledScheme = new CompiledScheme(); boxScheme.CompiledScheme.AddVariable(new ObjectVariable(VariableTypes.Logical, "ready", false)); SchemeFunction pickup = new SchemeFunction(); pickup.Name = "pickup"; pickup.ActionPoints = 1; pickup.AddCommand(new CommandJumpIfFalse("ready", 3)); pickup.AddCommand(new CommandPrint("Picked up")); pickup.AddCommand(new CommandJump(4)); pickup.AddCommand(new CommandPrint("Box is stuck")); boxScheme.CompiledScheme.AddAction(pickup); return(boxScheme); }
public static void SolveSimpleValueRegs(SchemeFunction function) { //We iterate commands //If we find a SET(<reg>, <simple value>) command, we // //remove this SET command // //Iterate over the subsequent commands in the base block // //If we find any command with input <reg> we change it to <simple value> // //If we find any command with output <reg> we stop and goto 1. (continuing from the SET command we found) var commands = function.Commands; HashSet <int> removableIndexes = new HashSet <int>(); for (int i = 0; i < commands.Count; ++i) { ISchemeCommand cmd = commands[i]; if (cmd is CommandSetVariable) { CommandSetVariable cmdSet = (CommandSetVariable)cmd; string targetVar = cmdSet.GetVariableName(); string value = cmdSet.GetValue(); if (SchemeExecutor.IsRegister(targetVar)) { removableIndexes.Add(i); for (int i2 = i + 1; i2 < commands.Count; ++i2) { ISchemeCommand cmd2 = commands[i2]; cmd2.ChangeInputs(targetVar, value); if (cmd2 is CommandJumpBase || cmd2.HasOutput(targetVar)) { break; } } } } } RemoveCommandsAt(function, removableIndexes); }
public override object VisitAction_block([NotNull] scheme_langParser.Action_blockContext context) { //Sign start of action string name = context.action_name()?.GetText(); int actionPoints = 0; if (context.action_point() != null) { int.TryParse(context.action_point().GetText(), out actionPoints); } //else //Errors.Add(new ErrorDescriptor("Missing action points")); if (CompiledScheme.GetFunctionByName(name) != null) { Errors.Add(new ErrorDescriptor($"This scheme already contains an action named '{name}'.", context.action_name())); } currentFunc = new SchemeFunction(name, actionPoints); VariableManager.NewBlock(); return(base.VisitAction_block(context)); }
public SchemeFunction GetFunctionByName(string functionName) { SchemeFunction matchingFunction = CompiledScheme.GetFunctionByName(functionName); //If given name was not found in this scheme, we try the parents if (matchingFunction == null) { foreach (Scheme parent in Parents) { matchingFunction = parent.GetFunctionByName(functionName); if (matchingFunction != null) { return(matchingFunction); } } } else { return(matchingFunction); } return(null); }
public static void SolveRegisterBuffers(SchemeFunction function) { // if an operation stores its result in a register <reg>, and it is followed by a SET(<var>, <reg>) command // we delete the SET command and set the opperation's output to <var> // we iterate over the following commands and change any <reg> to <var> // we stop if <reg> is set again or we leave the block var commands = function.Commands; HashSet <int> removableIndexes = new HashSet <int>(); for (int i = 0; i < commands.Count; ++i) { ISchemeCommand cmd = commands[i]; var outputs = cmd.GetOutputs(); if (outputs == null) { continue; } // check if any output is a register foreach (var reg in outputs) { if (SchemeExecutor.IsRegister(reg)) { string variable = null; for (int j = i + 1; j < commands.Count; ++j) { ISchemeCommand cmd2 = commands[j]; if (cmd2 is CommandJumpBase) { break; // break if we leave the block } if (cmd2.HasOutput(reg)) { break; // break if the register is set again } if (cmd2 is CommandSetVariable && cmd2.HasInput(reg)) { CommandSetVariable setCmd = (CommandSetVariable)cmd2; variable = setCmd.GetVariableName(); if (SchemeExecutor.IsRegister(variable)) { variable = null; } else { cmd.ChangeOutput(reg, variable); removableIndexes.Add(j); } } if (variable != null && cmd2.HasInput(reg)) { cmd2.ChangeInputs(reg, variable); } } } } } RemoveCommandsAt(function, removableIndexes); }
public void AddAction(SchemeFunction action) { ActionFunctions.Add(action); }
public void SetInit(SchemeFunction init) { InitFunction = init; }
public void SetBody(SchemeFunction bodyFunction) { BodyFunction = bodyFunction; }
public static void SolveDeadCode(SchemeFunction function) { //For each command C: //. If C uses local variable X that is in V, as input, we remove X from V and the corresponding line from L //. If C has local variable output X that is in V, then we remove the line of code that is connected to X (found in L) //. If C has local variable output, we store the output variable's name in array V, and the code line in L //. If we reach new basic block, we clear V and L bool changed = true; while (changed) { changed = false; HashSet <int> blocks = GetBlockPositions(function); var commands = function.Commands; HashSet <int> removableIndexes = new HashSet <int>(); Dictionary <string, int> lastSetLines = new Dictionary <string, int>(); for (int i = 0; i < commands.Count; ++i) { if (blocks.Contains(i)) { lastSetLines.Clear(); } ISchemeCommand cmd = commands[i]; if (cmd is CommandCreateVariable) { continue; //We don't want to remove CREATE commands } List <string> inputs = cmd.GetInputs(); List <string> outputs = cmd.GetOutputs(); if (inputs != null) { foreach (string input in inputs) { if (SchemeExecutor.IsVariable(input)) { lastSetLines.Remove(input); } } } if (outputs != null) { foreach (string output in outputs) { if (SchemeExecutor.IsVariable(output)) { if (lastSetLines.ContainsKey(output)) { removableIndexes.Add(lastSetLines[output]); } lastSetLines[output] = i; } } } } if (removableIndexes.Count > 0) { changed = true; RemoveCommandsAt(function, removableIndexes); } } }