예제 #1
0
 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)),
            });
예제 #3
0
        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);
            }
        }
예제 #4
0
        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)));
        }
예제 #5
0
 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)
     });
예제 #6
0
        [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));
        }
예제 #7
0
 protected override bool Visit(Bracketed brk) => Visit(brk.Parameter);
예제 #8
0
 [NotNull] protected abstract TResult Visit([NotNull] Bracketed brk);
 protected override BaseExpression Visit(Bracketed brk)
 {
     using (AppendLine("()"))
         return(base.Visit(brk));
 }
예제 #10
0
 [NotNull] protected virtual BaseExpression Visit([NotNull] Bracketed brk)
 {
     return(new Bracketed(Visit(brk.Parameter)));
 }
예제 #11
0
 protected override IDataFlowGraphExpressionNode Visit(Bracketed brk)
 {
     return(VisitUnary(new UnaryOp(Guid.NewGuid(), "()", Visit(brk.Parameter), a => new Bracketed(a))));
 }
예제 #12
0
 protected override IEnumerable <BaseStatement> Visit(Bracketed brk) => Visit(brk.Parameter);
예제 #13
0
        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());
        }