private static bool SimplifyScans(AbstractSyntaxTree root) { if (root.Count > 1) { bool RetVal = false; foreach (AbstractSyntaxTree ast in root.ChildNodes) { RetVal |= SimplifyScans(ast); } return(RetVal); } if (root.Count == 1) { if (root[0].Op == OpCode.AddPtr) { root.RemoveAt(0); root.Op = OpCode.ScanRight; return(true); } if (root[0].Op == OpCode.SubPtr) { root.RemoveAt(0); root.Op = OpCode.ScanLeft; return(true); } } return(false); }
private static bool SimplifyAssignZeroLoops(AbstractSyntaxTree root) { bool RetVal = false; bool Predicate(AbstractSyntaxTree ast) => (ast.AllChildrenAssignZero || ast.AllChildrenDecVal || ast.AllChildrenIncVal) && ast.Count % 2 != 0; // ToList hack allows the original list to be changed. foreach (AbstractSyntaxTree ast in root.ChildNodes) { RetVal |= SimplifyAssignZeroLoops(ast); if (ast.Op == OpCode.Loop && Predicate(ast)) { OpCode op = ast[0].Op; if (op == OpCode.AssignZero || op.ModifiesValue()) { ast.ChildNodes.RemoveAt(0); ast.Op = OpCode.AssignZero; RetVal = true; } } } return(RetVal); }
private static bool EliminateDeadStores(AbstractSyntaxTree root, bool trueRoot) { bool RetVal = false; for (int i = root.Count - 2; i >= 0; i--) { RetVal |= EliminateDeadStores(root[i], false); if (root[i + 1].Op == OpCode.AssignZero || root[i + 1].Op == OpCode.AssignVal) { AbstractSyntaxTree ast = root[i]; if (ast.Op.AssignsValue() || ast.Op == OpCode.AssignZero || ast.Op.ModifiesValue()) { root.Remove(ast); } } } if (root.Count > 0 && root[0].Op == OpCode.AssignZero && trueRoot) { root.RemoveAt(0); return(true); } return(RetVal); }
private static bool EliminateUnreachableLoops(AbstractSyntaxTree root, bool trueRoot) { bool RetVal = false; for (int i = 1; i < root.Count; i++) { RetVal |= EliminateUnreachableLoops(root[i], false); if (root[i].Op == OpCode.Loop && (root[i - 1].Op == OpCode.Loop || root[i - 1].Op == OpCode.AssignZero)) { root.RemoveAt(i); RetVal = true; i--; } } if (trueRoot) { if (root.Count > 0 && root[0].Op == OpCode.Loop) { root.RemoveAt(0); return(true); } if (root.Count == 0 && root.Op == OpCode.Loop) { root.Op = OpCode.Nop; return(true); } } return(RetVal); }
/// <summary> /// Converts given user code into a IL program which can then be compiled. /// </summary> /// <param name="settings">The settings.</param> /// <returns></returns> public static (ErrorCodes errorCode, List <Instruction> Il) CompileAst(CompilerSettings settings) { AbstractSyntaxTree tree = Lexer.LexAst(settings.InputCode); Optimizer.Optimize(tree, settings); List <Instruction> Il = tree.ToIl(); Optimizer.Optimize(Il, settings); return(ErrorCodes.Successful, Il); }
internal static bool EliminateConflictingInstructions(AbstractSyntaxTree ast) { bool RetVal = false; if (ast.Count > 0) { RetVal |= EliminateConflictingInstructions(ast[0]); } for (int i = 1; i < ast.Count; i++) { RetVal |= EliminateConflictingInstructions(ast[i]); if (ast[i - 1].Op.IsReversable() && ast[i - 1].Op.GetReversedOpCode() == ast[i].Op) { ast.RemoveAt(i); ast.RemoveAt(i - 1); i += 2; RetVal = true; } } return(RetVal); }
internal static void Optimize(AbstractSyntaxTree ast, CompilerSettings settings) { bool Continue = true; while (Continue) { Continue = false; if (settings.SimplifyAssignZeroLoops) { Continue |= SimplifyAssignZeroLoops(ast); ast.ColapseNops(); } if (settings.EliminateDeadStores) { Continue |= EliminateDeadStores(ast, true); ast.ColapseNops(); } if (settings.EliminateUnreachableLoops) { Continue |= EliminateUnreachableLoops(ast, true); ast.ColapseNops(); } if (settings.EliminateConflictingInstructions) { Continue |= EliminateConflictingInstructions(ast); ast.ColapseNops(); } if (true) { Continue |= SimplifyScans(ast); ast.ColapseNops(); } } }
private static AbstractSyntaxTree GenerateTree(ref int index, string code, bool isRoot, OpCode bundleType) { AbstractSyntaxTree tree = new AbstractSyntaxTree(OpCode.Loop); while (index < code.Length) { switch (code[index++]) { case '[': tree.Add(GenerateTree(ref index, code, false, OpCode.StartLoop)); break; case ']': if (isRoot) { throw new InvalidOperationException(); // Unbalanced ']' } if (bundleType != OpCode.StartLoop) { index--; } return(tree); case '+': tree.Add(new AbstractSyntaxTree(OpCode.AddVal)); break; case '-': tree.Add(new AbstractSyntaxTree(OpCode.SubVal)); break; case '>': tree.Add(new AbstractSyntaxTree(OpCode.AddPtr)); break; case '<': tree.Add(new AbstractSyntaxTree(OpCode.SubPtr)); break; case '.': tree.Add(new AbstractSyntaxTree(OpCode.SetOutput)); break; case ',': tree.Add(new AbstractSyntaxTree(OpCode.GetInput)); break; default: throw new InvalidOperationException(); } } if (!isRoot) { throw new InvalidOperationException(); // Unbalanced '[' } tree.Op = OpCode.Nop; return(tree); }