static BaseExpression HandleExpression(BaseExpression right) { return(right switch { Variable v => new Increment(v.Name), ConstantNumber n => new ConstantNumber(new Add(n, new ConstantNumber((Number)1)).StaticEvaluate().Number), ConstantString s => new ConstantString(s.Value + " "), Bracketed b => HandleExpression(b.Parameter), _ => throw new InvalidOperationException(right.GetType().Name) });
protected override BaseExpression Visit(Bracketed brk) { var inner = Visit(brk.Parameter); return(inner switch { Variable v => v, ConstantNumber n => n, ConstantString s => s, Bracketed b => b, _ => base.Visit(new Bracketed(inner)), });
protected override BaseStatement Visit(If @if) { // Check that each branch contains just one statement... if (@if.FalseBranch.Statements.Count != 1) { return(@if); } if (@if.TrueBranch.Statements.Count != 1) { return(@if); } // ...and that those statements are goto statements if (!(@if.TrueBranch.Statements.Single() is Goto gotoTrue)) { return(@if); } if (!(@if.FalseBranch.Statements.Single() is Goto gotoFalse)) { return(@if); } // if A then goto B else goto C end var a = new Bracketed(new Or(@if.Condition, new ConstantNumber(0))); var b = new Bracketed(gotoTrue.Destination); var c = new Bracketed(gotoFalse.Destination); // goto A*(B-C)+C var g1 = new Goto(new Add(c, new Multiply(a, new Bracketed(new Subtract(b, c))))); // x=C goto A*(B-x)+x var x = new VariableName(_names.Name()); var g2 = new StatementList( new Assignment(x, c), new Goto(new Add(new Multiply(a, new Bracketed(new Subtract(b, new Variable(x)))), new Variable(x))) ); // Return the shortest one (ignoring the length of the temporary variable name, assume that's optimised to 1 char) var xl = x.Name.Length * 2; if (g1.ToString().Length <= g2.ToString().Length - xl + 2) { return(g1); } else { return(g2); } }
protected override BaseExpression Visit(Bracketed brk) { var inner = Visit(brk.Parameter); switch (inner) { case Variable v: return(v); case ConstantNumber n: return(n); case ConstantString s: return(s); case Bracketed b: return(b); } return(base.Visit(new Bracketed(inner))); }
public virtual TResult Visit(BaseExpression expression) { return(expression switch { Phi a => Visit(a), Increment a => Visit(a), Decrement a => Visit(a), ErrorExpression a => Visit(a), Bracketed a => Visit(a), Abs a => Visit(a), Sqrt a => Visit(a), Sine a => Visit(a), Cosine a => Visit(a), Tangent a => Visit(a), ArcSine a => Visit(a), ArcCos a => Visit(a), ArcTan a => Visit(a), PostIncrement a => Visit(a), PreIncrement a => Visit(a), PostDecrement a => Visit(a), PreDecrement a => Visit(a), Add a => Visit(a), Subtract a => Visit(a), Multiply a => Visit(a), Divide a => Visit(a), Modulo a => Visit(a), Negate a => Visit(a), Exponent a => Visit(a), Or a => Visit(a), And a => Visit(a), Not a => Visit(a), Factorial a => Visit(a), Variable a => Visit(a), ConstantNumber a => Visit(a), ConstantString a => Visit(a), EqualTo a => Visit(a), NotEqualTo a => Visit(a), GreaterThan a => Visit(a), GreaterThanEqualTo a => Visit(a), LessThan a => Visit(a), LessThanEqualTo a => Visit(a), _ => VisitUnknown(expression) });
[NotNull] private BaseStatement Replace([NotNull] If @if) { if (@if.FalseBranch.Statements.Count != 0) { return(@if); } if (@if.TrueBranch.Statements.Count != 1) { return(@if); } if (!(@if.TrueBranch.Statements.Single() is Goto @goto)) { return(@if); } // Replace: // `if A then goto B end <fallthrough to next line>` // With: // `goto B + (Next_Line * (A != 0))` var condition = @if.Condition.IsBoolean ? Invert(@if.Condition) : new Bracketed(new EqualTo(new Bracketed(@if.Condition), new ConstantNumber(0))); BaseExpression diff = new Bracketed(new Subtract(new ConstantNumber(_lineNumber + 1), @goto.Destination)); if (diff.IsConstant) { diff = new ConstantNumber(diff.StaticEvaluate().Number); } var dest2 = new Add(@goto.Destination, new Multiply(diff, new Bracketed(condition))); return(new Goto(dest2)); }
protected override bool Visit(Bracketed brk) => Visit(brk.Parameter);
[NotNull] protected abstract TResult Visit([NotNull] Bracketed brk);
protected override BaseExpression Visit(Bracketed brk) { using (AppendLine("()")) return(base.Visit(brk)); }
[NotNull] protected virtual BaseExpression Visit([NotNull] Bracketed brk) { return(new Bracketed(Visit(brk.Parameter))); }
protected override IDataFlowGraphExpressionNode Visit(Bracketed brk) { return(VisitUnary(new UnaryOp(Guid.NewGuid(), "()", Visit(brk.Parameter), a => new Bracketed(a)))); }
protected override IEnumerable <BaseStatement> Visit(Bracketed brk) => Visit(brk.Parameter);
public static string ToString(Grammar grammar) { var b = new StringBuilder(); Action <string> print = s => b.AppendLine(s); using (var tree = new Bracketed(print, "public abstract class Tree")) { tree.Print("public abstract PGF.Expression ToExpression();"); } using (var namespc = new Bracketed(print, $"namespace {grammar.Name}")) { Func <string, string> typeName = n => CategoryToCSharpDatatype(grammar.Name, n); foreach (var cat in grammar.Categories) { // Abstract class (category) using (var catClass = new Bracketed(namespc.Print, $"public abstract class {cat.Name} : Tree")) { catClass.Print("public abstract R Accept<R>(IVisitor<R> visitor);"); using (var visitorInterface = new Bracketed(catClass.Print, "public interface IVisitor<R>")) { foreach (var constr in cat.Constructors) { visitorInterface.Print($"R Visit{constr.Name}({ArgList(grammar.Name, constr.ArgumentTypes)});"); } } using (var visitorClass = new Bracketed(catClass.Print, "public class Visitor<R> : IVisitor<R>")) { var constrNames = cat.Constructors.Select(c => c.Name); var argLists = cat.Constructors.Select(c => ArgList(grammar.Name, c.ArgumentTypes)); var varLists = cat.Constructors.Select(c => String.Join(", ", VariableNames().Take(c.ArgumentTypes.Count()))); var lambdaTypes = cat.Constructors.Select(c => $"System.Func<{TypeList(grammar.Name, c.ArgumentTypes.Concat(new[] { VISITOR_PARAM }))}>"); var funcFields = constrNames.Zip(lambdaTypes, (name, type) => $"private {type} _Visit{name} {{ get; set; }}"); var constructorArgs = String.Join(", ", constrNames.Zip(lambdaTypes, (name, type) => $"{type} Visit{name}")); var constructorAssignments = constrNames.Select(c => $"this._Visit{c} = Visit{c};"); var interfaceImplementationDecl = constrNames.Zip(argLists, (name, args) => $"public R Visit{name}({args})"); var interfaceImplementationBody = constrNames.Zip(varLists, (name, vars) => $"_Visit{name}({vars});"); var interfaceImplementaion = interfaceImplementationDecl.Zip(interfaceImplementationBody, (decl, body) => $"{decl} => {body}"); foreach (var s in funcFields) { visitorClass.Print(s); } using (var visitorConstructor = new Bracketed(visitorClass.Print, $"public Visitor({constructorArgs})")) { foreach (var assign in constructorAssignments) { visitorConstructor.Print(assign); } } foreach (var impl in interfaceImplementaion) { visitorClass.Print(impl); } } // FromExpression using (var fromExpr = new Bracketed(catClass.Print, $"public static {cat.Name} FromExpression(PGF.Expression expr)")) { //fromExpr.Print($"var visitor = new Expression.Visitor<{cat.Name}>();"); using (var visitor = new Bracketed(fromExpr.Print, $"return expr.Accept(new PGF.Expression.Visitor<{cat.Name}>()", ");")) { using (var visitApp = new Bracketed(visitor.Print, $"fVisitApplication = (fname,args) => ")) { foreach (var constr in cat.Constructors) { visitApp.Print($"if(fname == nameof({constr.Name}) && args.Length == {constr.ArgumentTypes.Count()})"); var args = constr.ArgumentTypes.Select((t, i) => { if (IsBuiltinType(t)) { return($"((PGF.Literal{t})args[{i}]).Value"); } return($"{t}.FromExpression(args[{i}])"); }); visitApp.Print($" return new {constr.Name}({String.Join(", ", args)});"); } visitApp.Print("throw new System.ArgumentOutOfRangeException();"); } } } } foreach (var constr in cat.Constructors) { // Concrete class (category constructor) using (var constrClass = new Bracketed(namespc.Print, $"public class {constr.Name} : {cat.Name}")) { var fields = constr.ArgumentTypes.Zip(VariableNames(), (type, name) => $"public {typeName(type)} {name} {{get; set;}}"); var constructorArgs = String.Join(", ", constr.ArgumentTypes.Zip(VariableNames(), (type, name) => $"{typeName(type)} {name}")); var vars = VariableNames().Take(constr.ArgumentTypes.Count()); var varList = String.Join(", ", vars); var constructorAssignments = vars.Select(name => $"this.{name} = {name};"); // Fields (for constructor arguments) foreach (var f in fields) { constrClass.Print(f); } // Constructor using (var constrConstructor = new Bracketed(constrClass.Print, $"public {constr.Name}({constructorArgs})")) { foreach (var a in constructorAssignments) { constrConstructor.Print(a); } } // Visitor using (var visitorAccept = new Bracketed(constrClass.Print, "public override R Accept<R>(IVisitor<R> visitor)")) { visitorAccept.Print($"return visitor.Visit{constr.Name}({varList});"); } // FromExpression using (var fromExpr = new Bracketed(constrClass.Print, "public override PGF.Expression ToExpression()")) { var args = constr.ArgumentTypes.Zip(VariableNames(), (type, name) => { if (IsBuiltinType(type)) { return($"new PGF.Literal{type}({name})"); } return($"{name}.ToExpression()"); }); var argsArray = $"new PGF.Expression[]{{{String.Join(", ", args)}}}"; fromExpr.Print($"return new PGF.Application(nameof({constr.Name}), {argsArray});"); } } } } } return(b.ToString()); }