コード例 #1
0
ファイル: ContractsMacro.out.cs プロジェクト: sizzles/ecsharp
        static LNode ProcessArgContractAttributes(LNode fn, int argsIndex, CodeContractRewriter rw, bool isLambda = false)
        {
            LNode fnArgs = fn.Args[argsIndex];

            if (fnArgs.CallsMin(isLambda ? S.Tuple : S.AltList, 1))
            {
                return(fn.WithArgChanged(argsIndex,
                                         fnArgs.WithArgs(arg => {
                    if (arg.HasAttrs)
                    {
                        return arg.WithAttrs(rw.Process(arg.Attrs, GetVarName(arg)));
                    }
                    return arg;
                })));
            }
            else if (isLambda)
            {
                var arg = fnArgs;                       // just one argument
                if (arg.HasAttrs)
                {
                    fn = fn.WithArgChanged(argsIndex,
                                           arg.WithAttrs(rw.Process(arg.Attrs, GetVarName(arg))));
                }
            }
            return(fn);
        }
コード例 #2
0
            LNode ConvertVarDeclToRunSequence(VList <LNode> attrs, LNode varType, LNode varName, LNode initValue)
            {
                initValue = BubbleUpBlocks(initValue);
                varType   = varType ?? F.Missing;
                LNode @ref;

                attrs = attrs.WithoutNodeNamed(S.Ref, out @ref);
                var varName_apos = varName.PlusAttr(_trivia_isTmpVar);

                if (@ref != null)
                {
                    varName_apos = varName_apos.PlusAttr(@ref);
                }
                {
                    LNode         resultValue;
                    VList <LNode> stmts;
                    if (initValue.CallsMin((Symbol)"#runSequence", 1) && (resultValue = initValue.Args[initValue.Args.Count - 1]) != null)
                    {
                        stmts = initValue.Args.WithoutLast(1);
                        var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, resultValue))));
                        return(initValue.WithArgs(stmts.Add(newVarDecl).Add(varName_apos)));
                    }
                    else
                    {
                        var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, initValue))));
                        return(LNode.Call((Symbol)"#runSequence", LNode.List(newVarDecl, varName_apos)));
                    }
                }
            }
コード例 #3
0
ファイル: Rule.cs プロジェクト: sizzles/ecsharp
 /// <summary>Returns Basis if it's a method signature; otherwise constructs a default signature.</summary>
 public LNode GetMethodSignature()
 {
     if (Basis != null && Basis.Calls(S.Fn) && Basis.ArgCount.IsInRange(3, 4))
     {
         var parts = Basis.Args;
         if (parts.Count == 4)
         {
             parts.RemoveAt(3);
         }
         if (IsRecognizer)
         {
             parts[0] = F.Bool;
         }
         parts[1] = F.Id(Name);
         // remove OneLiner style to avoid suppresing newlines in output for one-line rules
         return(Basis.WithArgs(parts).SetStyle(Basis.Style & ~NodeStyle.OneLiner));
     }
     else
     {
         var method = F.Fn(IsRecognizer ? F.Bool : F.Void, F.Id(Name), F.List());
         if (IsPrivate == true)
         {
             method = F.Attr(F.Id(S.Private), method);
         }
         else if (IsStartingRule | IsToken)
         {
             method = F.Attr(F.Id(S.Public), method);
         }
         return(method);
     }
 }
コード例 #4
0
 LNode EliminateBlockExprsInExecStmt(LNode stmt)
 {
     if (!stmt.IsCall)
     {
         return(stmt);
     }
     {
         LNode         cond;
         VList <LNode> blocks;
         if (stmt.Calls(CodeSymbols.Braces))
         {
             return(stmt.WithArgs(EliminateBlockExprs(stmt.Args, false)));
         }
         else if (stmt.CallsMin(CodeSymbols.If, 1) && (cond = stmt.Args[0]) != null)
         {
             blocks = new VList <LNode>(stmt.Args.Slice(1));
             return(ProcessBlockCallStmt(stmt, 1));
         }
         else if (stmt.HasSpecialName && stmt.ArgCount >= 1 && stmt.Args.Last.Calls(S.Braces))
         {
             return(ProcessBlockCallStmt(stmt, stmt.ArgCount - 1));
         }
         else
         {
             stmt = BubbleUpBlocks(stmt);
             if (stmt.CallsMin(__runSequence, 1))
             {
                 return(stmt.Args.AsLNode(S.Splice));
             }
         }
     }
     return(stmt);
 }
コード例 #5
0
 /// <summary>Returns Basis if it's a method signature; otherwise constructs a default signature.</summary>
 public LNode GetMethodSignature()
 {
     if (Basis != null && Basis.Calls(S.Fn) && Basis.ArgCount.IsInRange(3, 4))
     {
         var parts = Basis.Args;
         if (parts.Count == 4)
         {
             parts.RemoveAt(3);
         }
         if (IsRecognizer)
         {
             parts[0] = F.Bool;
         }
         parts[1] = F.Id(Name);
         return(Basis.WithArgs(parts));
     }
     else
     {
         var method = F.Fn(IsRecognizer ? F.Bool : F.Void, F.Id(Name), F.List());
         if (IsPrivate)
         {
             method = F.Attr(F.Id(S.Private), method);
         }
         else if (IsStartingRule | IsToken)
         {
             method = F.Attr(F.Id(S.Public), method);
         }
         return(method);
     }
 }
コード例 #6
0
 // Creates a temporary for an LValue (left side of `=`, or `ref` parameter)
 // e.g. f(x).Foo becomes f(x_N).Foo, and `var x_N = x` is added to `stmtSequence`,
 // where N is a unique integer for the temporary variable.
 LNode MaybeCreateTemporaryForLValue(LNode expr, ref VList <LNode> stmtSequence)
 {
     {
         LNode _, lhs;
         if (expr.Calls(CodeSymbols.Dot, 2) && (lhs = expr.Args[0]) != null || expr.CallsMin(CodeSymbols.Of, 1) && (lhs = expr.Args[0]) != null)
         {
             return(expr.WithArgChanged(0, MaybeCreateTemporaryForLValue(lhs, ref stmtSequence)));
         }
         else if ((_ = expr) != null && !_.IsCall)
         {
             return(expr);
         }
         else
         {
             var args = expr.Args.ToWList();
             int i    = 0;
             if (expr.CallsMin(S.IndexBracks, 1) || expr.CallsMin(S.NullIndexBracks, 1))
             {
                 // Consider foo[i]. We cannot always store `foo` in a temporary, as
                 // this may change the code's behavior in case `foo` is a struct.
                 i = 1;
             }
             for (; i < args.Count; i++)
             {
                 if (!args[i].IsLiteral && !args[i].Attrs.Contains(_trivia_isTmpVar))
                 {
                     LNode tmpVarName;
                     stmtSequence.Add(TempVarDecl(Context, args[i], out tmpVarName));
                     args[i] = tmpVarName.PlusAttr(_trivia_isTmpVar);
                 }
             }
             return(expr.WithArgs(args.ToVList()));
         }
     }
 }
コード例 #7
0
 protected virtual LNode MakeSuperExpr(LNode lhs, ref LNode primary, RVList <LNode> rhs)
 {
     if (primary == null)
     {
         return(lhs);                // an error should have been printed already
     }
     if (lhs == primary)
     {
         if (primary.BaseStyle == NodeStyle.Operator)
         {
             primary = F.Call(primary, rhs);
         }
         else
         {
             primary = lhs.WithArgs(lhs.Args.AddRange(rhs));
         }
         MarkSpecial(primary);
         return(primary);
     }
     else
     {
         Debug.Assert(lhs != null && lhs.IsCall && lhs.ArgCount > 0);
         Debug.Assert(lhs.BaseStyle != NodeStyle.Special);
         int   c  = lhs.ArgCount - 1;
         LNode ce = MakeSuperExpr(lhs.Args[c], ref primary, rhs);
         return(lhs.WithArgChanged(c, ce));
     }
 }
コード例 #8
0
ファイル: Prelude.Les.cs プロジェクト: jonathanvdc/Loyc
        public static LNode of(LNode node, IMessageSink sink)
        {
            LNode kind;

            if (node.ArgCount == 2 && (kind = node.Args[0]).IsId)
            {
                if (kind.IsIdNamed(_array))
                {
                    return(node.WithArgChanged(0, kind.WithName(S.Array)));
                }
                if (kind.IsIdNamed(_opt))
                {
                    return(node.WithArgChanged(0, kind.WithName(S.QuestionMark)));
                }
                if (kind.IsIdNamed(_ptr))
                {
                    return(node.WithArgChanged(0, kind.WithName(S._Pointer)));
                }
            }
            else if (node.ArgCount == 3 && (kind = node.Args[0]).IsIdNamed(_array) && node.Args[1].IsLiteral)
            {
                return(node.WithArgs(kind.WithName(S.GetArrayKeyword((int)node.Args[1].Value)), node.Args[2]));
            }
            return(null);
        }
コード例 #9
0
        public static LNode Try(LNode node, IMacroContext context)
        {
            var a = node.Args.ToWList();

            for (int i = 1; i < a.Count; i++)
            {
                var clause = a[i];
                if (clause.Calls(S.Catch) || clause.Calls(__except))
                {
                    if (clause.ArgCount == 1)
                    {
                        a[i] = clause.WithArgs(F.Missing, F.Missing, a[i].Args[0]);
                    }
                    else
                    if (clause.ArgCount == 2)
                    {
                        if (clause.Args[0].Calls(__when, 2))
                        {
                            a[i] = clause.WithArgs(clause[0][0], clause[0][1], clause[1]);
                        }
                        else
                        {
                            a[i] = clause.WithArgs(clause[0], F.Missing, clause[1]);
                        }
                    }
                }
            }
            if (a.ToLNodeList() != node.Args)
            {
                return(node.WithArgs(a.ToVList()));
            }
            return(null);
        }
コード例 #10
0
 public static LNode priorityTestPCB(LNode node, IMessageSink sink)
 {
     if (node.ArgCount == 2)
     {
         return(node.WithArgs(node[1], node[0]));
     }
     return(null);
 }
コード例 #11
0
 public static LNode Namespace(LNode node, IMacroContext context)
 {
     if (node.ArgCount == 2 && !node.Args.Last.Calls(S.Braces))
     {
         context.DropRemainingNodes = true;
         return(node.WithArgs(node.Args.Add(F.Braces(context.RemainingNodes))));
     }
     return(null);
 }
コード例 #12
0
ファイル: CompileTimeMacro.cs プロジェクト: dadhi/ecsharp
        // Given Foo(x, y, a = 1, c = 2), extracts { a = 1, c = 2 } to a separate list
        private static LNodeList SeparateAttributeSetters(ref LNode attribute)
        {
            LNodeList setters = LNode.List();

            while (attribute.Args.LastOrDefault()?.Calls(S.Assign) == true)
            {
                setters.Insert(0, attribute.Args.Last);
                attribute = attribute.WithArgs(attribute.Args.WithoutLast(1));
            }
            return(setters);
        }
コード例 #13
0
ファイル: Prelude.Les.cs プロジェクト: jonathanvdc/Loyc
 public static LNode @case(LNode node, IMessageSink sink)
 {
     if (node.ArgCount == 1)
     {
         return(node.WithTarget(S.Case));
     }
     else if (node.ArgCount == 2 && node.Args[1].Calls(S.Braces))
     {
         return(F.Call(S.Splice, new VList <LNode>(node.WithArgs(node.Args.First(1)), node.Args[1])));
     }
     return(null);
 }
コード例 #14
0
 public static LNode runSequence(LNode node, IMacroContext context)
 {
     if (context.Parent.Calls(S.Braces))
     {
         if (node.ArgCount == 1 && node.Args[0].Calls(S.Braces))
         {
             return(node.WithArgs(node.Args[0].Args));
         }
         return(node.WithTarget(S.Splice));
     }
     return(Reject(context, node, "#useVarDeclExpressions is required to make #runSequence work"));
 }
コード例 #15
0
 LNode EliminateSequenceExpressionsInExecStmt(LNode stmt)
 {
     {
         LNode     block, collection, cond, init, initValue, loopVar, name, tmp_11, tmp_12, tmp_13, type, varType;
         LNodeList attrs, incs, inits;
         if (stmt.Calls(CodeSymbols.Braces))
         {
             return(stmt.WithArgs(EliminateSequenceExpressions(stmt.Args, false)));
         }
         else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.Fixed, 2) && (init = stmt.Args[0]) != null && (block = stmt.Args[1]) != null)
         {
             init  = EliminateSequenceExpressionsInExecStmt(init);
             block = EliminateSequenceExpressionsInChildStmt(block);
             if (UnwrapRunSequence(ref init, out var initSeq))
             {
                 return(LNode.Call(LNode.List(attrs), CodeSymbols.Braces, LNode.List().AddRange(initSeq.WithoutLast(1)).Add(LNode.Call(CodeSymbols.Fixed, LNode.List(initSeq.Last, block)))).SetStyle(NodeStyle.StatementBlock));
             }
             else
             {
                 return(stmt.WithArgs(init, block));
             }
         }
コード例 #16
0
            LNode ESEInTryStmt(LNode stmt)
            {
                var args = stmt.Args.ToWList();

                args[0] = EliminateSequenceExpressionsInChildStmt(args[0]);
                for (int i = 1; i < args.Count; i++)
                {
                    var part = args[i];
                    if (part.Calls(S.Finally, 1) || part.Calls(S.Catch, 3))
                    {
                        int lasti = part.ArgCount - 1;
                        args[i] = part.WithArgChanged(lasti, EliminateSequenceExpressionsInChildStmt(part.Args[lasti]));
                    }
                }
                return(stmt.WithArgs(args.ToVList()));
            }
コード例 #17
0
        public static LNode IfUnless(LNode node, IMacroContext context)
        {
            // #if(cond1, {...}, #elsif(cond2, {...}), #else({...}));
            // #unless(cond1, {...}, #else({...}));
            var  args     = node.Args;
            bool isUnless = node.Calls(__unless) && args.Count >= 2;

            if (isUnless)
            {
                node = node.WithArgChanged(0, F.Call(S.Not, args[0]));
            }

            if (args.Count >= 3)
            {
                LNode clause   = args[2];
                bool  isElseIf = clause.Calls(__elsif) || clause.Calls(__elseif);
                if (clause.Calls(S.Else, 2) && clause[0].Calls("if", 1))
                {
                    // Although it's possible to accept "else if (foo)", "else if foo {...}"
                    // would be parsed quite wrongly as "else (if foo {...})"! So issue a
                    // warning to discourage the bad habit of writing "else if".
                    context.Warning(clause[0].Target, "'else if' should be one word (elsif or elseif)");
                    isElseIf = true;
                    clause   = clause.WithArgChanged(0, clause[0][0]);
                }
                if (isElseIf)
                {
                    var first3 = args.WithoutLast(args.Count - 3);
                    // node: #if(cond1, {...}, #elsif(cond2, {...}), #elsif(cond3, {...}), #else({...}))
                    //                        ^^^^^^^clause^^^^^^^
                    //          ^^^^^^^^^^^^first3^^^^^^^^^^^^^^^^
                    // returns: #if(cond1, {...}, #if(cond2, {...}, #elsif(cond3, {...}), #else({...})))
                    LNode @else = clause.WithTarget(S.If);
                    if (args.Count > 3)
                    {
                        @else = @else.WithArgs(@else.Args.AddRange(args.Slice(3)));
                    }
                    return(node.WithArgs(first3.WithoutLast(1).Add(@else)));
                }
                if (clause.Calls(S.Else, 1) && args.Count == 3)
                {
                    return(node.WithArgChanged(2, clause[0]));
                }
            }

            return(isUnless ? node : null);
        }
コード例 #18
0
ファイル: CodeGenHelperBase.cs プロジェクト: dadhi/ecsharp
        /// <summary>Creates the default method definition wrapped around the body
        /// of the rule, which was generated by the caller. Returns <see cref="Basis"/>
        /// with the specified new method body. If Basis is null, a simple default
        /// method signature is used, e.g. <c>public void R() {...}</c> where R is
        /// the rule name.</summary>
        /// <param name="methodBody">The parsing code that was generated for this rule.</param>
        /// <returns>A method.</returns>
        public virtual LNode CreateRuleMethod(Rule rule, LNodeList methodBody)
        {
            LNode method = rule.GetMethodSignature();
            var   parts  = method.Args.ToWList();

            if (parts[0].IsIdNamed(S.Missing))
            {
                parts[0] = F.Id(rule.Name);
            }
            Debug.Assert(parts.Count == 3);
            if (rule.IsRecognizer)
            {
                methodBody.Add(F.Call(S.Return, F.True));
            }
            parts.Add(F.OnNewLine(F.Braces(methodBody)));
            return(method.WithArgs(parts.ToLNodeList()));
        }
コード例 #19
0
        /// <summary>Creates the default method definition to wrap around the body
        /// of the rule, which has already been generated. Returns <see cref="Basis"/>
        /// with the specified new method body. If Basis is null, a simple default
        /// method signature is used, e.g. <c>public void R() {...}</c> where R is
        /// the rule name.</summary>
        /// <param name="methodBody">The parsing code that was generated for this rule.</param>
        /// <returns>A method.</returns>
        public LNode CreateMethod(RVList <LNode> methodBody)
        {
            LNode method = GetMethodSignature();
            var   parts  = method.Args.ToRWList();

            if (parts[0].IsIdNamed(S.Missing))
            {
                parts[0] = F.Id(Name);
            }
            Debug.Assert(parts.Count == 3);
            if (IsRecognizer)
            {
                methodBody.Add(F.Call(S.Return, F.True));
            }
            parts.Add(F.Braces(methodBody));
            return(method.WithArgs(parts.ToRVList()));
        }
コード例 #20
0
 LNode BubbleUpBlocks(LNode expr)
 {
     if (!expr.IsCall)
     {
         return(expr);
     }
     {
         LNode         tmp_3 = null, value, varName, varType = null;
         VList <LNode> args, attrs;
         if (expr.Calls((Symbol)"#runSequence"))
         {
             args = expr.Args;
             if (args.Count == 1 && args[0].Calls(S.Braces))
             {
                 return(expr.WithArgs(args[0].Args));
             }
             return(expr);
         }
         else if (expr.Calls(CodeSymbols.Braces))
         {
             Context.Write(Severity.Error, expr, "A braced block is not supported directly within an expression. Did you mean to use `#runSequence {...}`?");
             return(expr);
         }
         else if ((attrs = expr.Attrs).IsEmpty | true && attrs.NodeNamed(S.Out) != null && expr.Calls(CodeSymbols.Var, 2) && (varType = expr.Args[0]) != null && (varName = expr.Args[1]) != null && varName.IsId)
         {
             if (varType.IsIdNamed(S.Missing))
             {
                 Context.Write(Severity.Error, expr, "The data type of this variable declaration must be stated explicitly.");
             }
             return(LNode.Call((Symbol)"#runSequence", LNode.List(expr.WithoutAttrNamed(S.Out), varName)));
         }
         else if ((attrs = expr.Attrs).IsEmpty | true && expr.Calls(CodeSymbols.Var, 2) && (varType = expr.Args[0]) != null && (tmp_3 = expr.Args[1]) != null && tmp_3.Calls(CodeSymbols.Assign, 2) && (varName = tmp_3.Args[0]) != null && (value = tmp_3.Args[1]) != null || (attrs = expr.Attrs).IsEmpty | true && expr.Calls(CodeSymbols.ColonColon, 2) && (value = expr.Args[0]) != null && IsQuickBindLhs(value) && (varName = expr.Args[1]) != null && varName.IsId)
         {
             return(ConvertVarDeclToRunSequence(attrs, varType ?? F.Missing, varName, value));
         }
     }
     if (expr.IsCall)
     {
         return(BubbleUp_GeneralCall(expr));
     }
     else
     {
         return(expr);
     }
 }
コード例 #21
0
            LNode ESEInTryStmt(LNode stmt)
            {
                var args = stmt.Args.ToWList();

                // Process `try` part
                args[0] = EliminateSequenceExpressionsInChildStmt(args[0]);
                // Process `catch` and `finally` clauses (`when` clause not supported)
                for (int i = 1; i < args.Count; i++)
                {
                    var part = args[i];
                    if (part.Calls(S.Finally, 1) || part.Calls(S.Catch, 3))
                    {
                        int lasti = part.ArgCount - 1;
                        args[i] = part.WithArgChanged(lasti, EliminateSequenceExpressionsInChildStmt(part.Args[lasti]));
                    }
                }
                return(stmt.WithArgs(args.ToVList()));
            }
コード例 #22
0
            Pair <VList <LNode>, LNode> BubbleUp_GeneralCall2(LNode expr)
            {
                var target           = expr.Target;
                var args             = expr.Args;
                var combinedSequence = LNode.List();

                target = BubbleUpBlocks(target);
                if (target.CallsMin(__runSequence, 1))
                {
                    combinedSequence = target.Args.WithoutLast(1);
                    expr             = expr.WithTarget(target.Args.Last);
                }
                args = args.SmartSelect(arg => BubbleUpBlocks(arg));
                int lastRunSeq = args.LastIndexWhere(a => a.CallsMin(__runSequence, 1));

                if (lastRunSeq >= 0)
                {
                    if (lastRunSeq > 0 && (args.Count == 2 && (target.IsIdNamed(S.And) || target.IsIdNamed(S.Or)) || args.Count == 3 && target.IsIdNamed(S.QuestionMark)))
                    {
                        Context.Write(Severity.Error, expr, "#useVarDeclExpressions is not designed to support sequences or variable declarations on the right-hand side of the `&&`, `||` or `?` operators. The generated code may be incorrect.");
                    }
                    var argsW = args.ToList();
                    for (int i = lastRunSeq - 1; i >= 0; i--)
                    {
                        if (!argsW[i].CallsMin(__runSequence, 1) && !argsW[i].IsLiteral)
                        {
                            LNode tmpVarName, tmpVarDecl = TempVarDecl(argsW[i], out tmpVarName);
                            argsW[i] = LNode.Call((Symbol)"#runSequence", LNode.List(tmpVarDecl, tmpVarName));
                        }
                    }
                    for (int i = 0; i <= lastRunSeq; i++)
                    {
                        LNode arg = argsW[i];
                        if (arg.CallsMin(__runSequence, 1))
                        {
                            combinedSequence.AddRange(arg.Args.WithoutLast(1));
                            argsW[i] = arg.Args.Last;
                        }
                    }
                    expr = expr.WithArgs(LNode.List(argsW));
                }
                return(Pair.Create(combinedSequence, expr));
            }
コード例 #23
0
        LNode ApplyMacrosToChildrenOf(LNode node, int maxExpansions)
        {
            if (maxExpansions <= 0)
            {
                return(null);
            }

            bool          changed = false;
            VList <LNode> old;
            var           newAttrs = ApplyMacrosToList(old = node.Attrs, maxExpansions, true);

            _s.IsAttribute = false;
            if (newAttrs != old)
            {
                node    = node.WithAttrs(newAttrs);
                changed = true;
            }
            LNode target = node.Target;

            if (target != null && target.Kind != LNodeKind.Literal)
            {
                DList <Pair <LNode, int> > _ = null;
                LNode newTarget = ApplyMacros(target, maxExpansions, true, true, ref _);
                if (newTarget != null)
                {
                    if (newTarget.Calls(S.Splice, 1))
                    {
                        newTarget = newTarget.Args[0];
                    }
                    node    = node.WithTarget(newTarget);
                    changed = true;
                }
            }
            var newArgs = ApplyMacrosToList(old = node.Args, maxExpansions, false);

            if (newArgs != old)
            {
                node    = node.WithArgs(newArgs);
                changed = true;
            }
            return(changed ? node : null);
        }
コード例 #24
0
        /// <summary>See <see cref="IPGCodeGenHelper.CreateTryWrapperForRecognizer"/> for more information.</summary>
        public LNode CreateTryWrapperForRecognizer()
        {
            Debug.Assert(TryWrapperName != null);

            LNode          method = GetMethodSignature();
            LNode          retType = method.Args[0], name = method.Args[1], args = method.Args[2];
            RVList <LNode> forwardedArgs = ForwardedArgList(args);

            LNode lookahead = F.Id("lookaheadAmt");

            Debug.Assert(args.Calls(S.List));
            args = args.WithArgs(args.Args.Insert(0, F.Var(F.Int32, lookahead)));

            LNode body = F.Braces(
                F.Call(S.UsingStmt, F.Call(S.New, F.Call(SavePosition, F.@this, lookahead)),
                       F.Call(S.Return, F.Call(name, forwardedArgs)))
                );

            return(method.WithArgs(retType, TryWrapperName, args, body));
        }
コード例 #25
0
            LNode ProcessBlockCallStmt(LNode stmt, int childStmtsStartAt)
            {
                List <LNode>  childStmts  = stmt.Slice(childStmtsStartAt).ToList();
                LNode         partialStmt = stmt.WithArgs(stmt.Args.First(childStmtsStartAt));
                VList <LNode> advanceSequence;

                if (ProcessBlockCallStmt(ref partialStmt, out advanceSequence, childStmts))
                {
                    stmt = partialStmt.PlusArgs(childStmts);
                    if (advanceSequence.Count != 0)
                    {
                        return(LNode.Call(CodeSymbols.Braces, LNode.List().AddRange(advanceSequence).Add(stmt)).SetStyle(NodeStyle.Statement));
                    }
                    return(stmt);
                }
                else
                {
                    return(stmt);
                }
            }
コード例 #26
0
        /// <summary>See <see cref="IPGCodeGenHelper.CreateTryWrapperForRecognizer"/> for more information.</summary>
        public LNode CreateTryWrapperForRecognizer(Rule rule)
        {
            Debug.Assert(rule.TryWrapperName != null);

            LNode         method = rule.GetMethodSignature();
            LNode         retType = method.Args[0], name = method.Args[1], args = method.Args[2];
            VList <LNode> forwardedArgs = ForwardedArgList(args);

            LNode lookahead = F.Id("lookaheadAmt");

            Debug.Assert(args.Calls(S.AltList));
            args = args.WithArgs(args.Args.Insert(0, F.Var(F.Int32, lookahead)));

            LNode savePosition = ApiType(F.Id(SavePosition));
            LNode @this        = InputSource ?? F.@this;
            LNode body         = F.Braces(
                F.Call(S.UsingStmt, F.Call(S.New, F.Call(savePosition, @this, lookahead)),
                       F.Call(S.Return, F.Call(name, forwardedArgs)))
                );

            return(method.WithArgs(retType, rule.TryWrapperName, args, body));
        }
コード例 #27
0
 public void PrependStmtsToGetterOrSetter(ref LNode braces, int getterIndex, LNode getter)
 {
     if (!PrependStmts.IsEmpty)
     {
         if (getter.ArgCount == 0)
         {
             Context.Write(Severity.Error, getter, "`{0}`: contracts cannot be applied to autoproperties. " + "A body is required, but you can use [field] on the property to add a body to `get` and `set` automatically.", getter);
             return;
         }
         else if (getter.ArgCount == 1)
         {
             var body = getter.Args[0];
             if (!body.Calls(S.Braces))
             {
                 body = LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(body)))).SetStyle(NodeStyle.Statement);
             }
             body   = body.WithArgs(body.Args.InsertRange(0, PrependStmts));
             getter = getter.WithArgs(body);
             braces = braces.WithArgChanged(getterIndex, getter);
         }
     }
 }
コード例 #28
0
            LNode ApplyMacrosToChildren(LNode node, int maxExpansions)
            {
                if (maxExpansions <= 0)
                {
                    return(null);
                }

                bool           changed = false;
                RVList <LNode> old;
                var            newAttrs = ApplyMacrosToList(old = node.Attrs, maxExpansions);

                if (newAttrs != old)
                {
                    node    = node.WithAttrs(newAttrs);
                    changed = true;
                }
                if (!node.HasSimpleHead())
                {
                    LNode target = node.Target, newTarget = ApplyMacros(target, maxExpansions);
                    if (newTarget != null)
                    {
                        if (newTarget.Calls(S.Splice, 1))
                        {
                            newTarget = newTarget.Args[0];
                        }
                        node    = node.WithTarget(newTarget);
                        changed = true;
                    }
                }
                var newArgs = ApplyMacrosToList(old = node.Args, maxExpansions);

                if (newArgs != old)
                {
                    node    = node.WithArgs(newArgs);
                    changed = true;
                }
                return(changed ? node : null);
            }
コード例 #29
0
        public static LNode VarDecl(LNode node, IMacroContext context)
        {
            var a = node.Args;

            if (a.Count == 2)
            {
                LNode name = a[0], type = a[1], nameAssignment = name;
                if (type.Calls(S.Assign, 2))
                {
                    nameAssignment = type.WithArgs(name, type[1]);
                    type           = type[0];
                }
                if (name.IsId)
                {
                    return(node.With(S.Var, type, nameAssignment).SetBaseStyle(NodeStyle.Default));
                }
                else
                {
                    context.Write(Severity.Note, node, "Unrecognized variable declaration syntax");
                    return(null);
                }
            }
            return(null);
        }
コード例 #30
0
		public static LNode priorityTestPCB(LNode node, IMessageSink sink)
		{
			if (node.ArgCount == 2)
				return node.WithArgs(node[1], node[0]);
			return null;
		}
コード例 #31
0
ファイル: Prelude.cs プロジェクト: BingjieGao/Loyc
		public static LNode @case(LNode node, IMessageSink sink)
		{
			if (node.ArgCount == 1)
				return node.WithTarget(S.Case);
			else if (node.ArgCount == 2 && node.Args[1].Calls(S.Braces))
				return F.Call(S.Splice, new RVList<LNode>(node.WithArgs(node.Args.First(1)), node.Args[1]));
			return null;
		}
コード例 #32
0
		void FinishPrimaryExpr(ref LNode e)
		{
			TokenType la1;
			// Line 541: greedy( (TT.ColonColon|TT.Dot|TT.PtrArrow|TT.QuickBind) AtomOrTypeParamExpr / PrimaryExpr_NewStyleCast / TT.LParen TT.RParen | TT.LBrack TT.RBrack | TT.QuestionMark TT.LBrack TT.RBrack | TT.IncDec | &(TParams ~(TT.ContextualKeyword|TT.Id)) ((TT.LT|TT.Not) | TT.Dot TT.LBrack) => TParams | BracedBlockOrTokenLiteral )*
			for (;;) {
				switch (LA0) {
				case TT.Dot:
					{
						if (Try_FinishPrimaryExpr_Test0(0)) {
							switch (LA(1)) {
							case TT.At: case TT.Base: case TT.Checked: case TT.ContextualKeyword:
							case TT.Default: case TT.Delegate: case TT.Dot: case TT.Id:
							case TT.Is: case TT.LBrace: case TT.Literal: case TT.LParen:
							case TT.New: case TT.Operator: case TT.Sizeof: case TT.Substitute:
							case TT.This: case TT.TypeKeyword: case TT.Typeof: case TT.Unchecked:
								goto match1;
							case TT.LBrack:
								TParams(false, ref e);
								break;
							default:
								goto stop;
							}
						} else {
							switch (LA(1)) {
							case TT.At: case TT.Base: case TT.Checked: case TT.ContextualKeyword:
							case TT.Default: case TT.Delegate: case TT.Dot: case TT.Id:
							case TT.Is: case TT.LBrace: case TT.Literal: case TT.LParen:
							case TT.New: case TT.Operator: case TT.Sizeof: case TT.Substitute:
							case TT.This: case TT.TypeKeyword: case TT.Typeof: case TT.Unchecked:
								goto match1;
							default:
								goto stop;
							}
						}
					}
					break;
				case TT.ColonColon: case TT.PtrArrow: case TT.QuickBind:
					{
						switch (LA(1)) {
						case TT.At: case TT.Base: case TT.Checked: case TT.ContextualKeyword:
						case TT.Default: case TT.Delegate: case TT.Dot: case TT.Id:
						case TT.Is: case TT.LBrace: case TT.Literal: case TT.LParen:
						case TT.New: case TT.Operator: case TT.Sizeof: case TT.Substitute:
						case TT.This: case TT.TypeKeyword: case TT.Typeof: case TT.Unchecked:
							goto match1;
						default:
							goto stop;
						}
					}
				case TT.LParen:
					{
						if (Down(0) && Up(LA0 == TT.As || LA0 == TT.Using || LA0 == TT.PtrArrow)) {
							la1 = LA(1);
							if (la1 == TT.RParen)
								e = PrimaryExpr_NewStyleCast(e);
							else
								goto stop;
						} else {
							la1 = LA(1);
							if (la1 == TT.RParen) {
								var lp = MatchAny();
								var rp = MatchAny();
								// line 545
								e = F.Call(e, ExprListInside(lp), e.Range.StartIndex, rp.EndIndex);
							} else
								goto stop;
						}
					}
					break;
				case TT.LBrack:
					{
						la1 = LA(1);
						if (la1 == TT.RBrack) {
							var lb = MatchAny();
							var rb = MatchAny();
							var list = new VList<LNode> { 
								e
							};
							e = F.Call(S.IndexBracks, AppendExprsInside(lb, list), e.Range.StartIndex, rb.EndIndex, lb.StartIndex, lb.EndIndex);
						} else
							goto stop;
					}
					break;
				case TT.QuestionMark:
					{
						la1 = LA(1);
						if (la1 == TT.LBrack) {
							var t = MatchAny();
							var lb = MatchAny();
							var rb = Match((int) TT.RBrack);
							// line 563
							e = F.Call(S.NullIndexBracks, e, F.List(ExprListInside(lb)), e.Range.StartIndex, rb.EndIndex, t.StartIndex, lb.EndIndex);
						} else
							goto stop;
					}
					break;
				case TT.IncDec:
					{
						var t = MatchAny();
						// line 565
						e = F.Call(t.Value == S.PreInc ? S.PostInc : S.PostDec, e, e.Range.StartIndex, t.EndIndex, t.StartIndex, t.EndIndex);
					}
					break;
				case TT.LT: case TT.Not:
					{
						if (Try_FinishPrimaryExpr_Test0(0))
							TParams(false, ref e);
						else
							goto stop;
					}
					break;
				case TT.At: case TT.LBrace:
					{
						la1 = LA(1);
						if (la1 == TT.LBrace || la1 == TT.LBrack || la1 == TT.RBrace) {
							var bb = BracedBlockOrTokenLiteral();
							// line 569
							if ((!e.IsCall || e.BaseStyle == NodeStyle.Operator)) {
								e = F.Call(e, bb, e.Range.StartIndex, bb.Range.EndIndex);
							} else {
								e = e.WithArgs(e.Args.Add(bb)).WithRange(e.Range.StartIndex, bb.Range.EndIndex);
							}
						} else
							goto stop;
					}
					break;
				default:
					goto stop;
				}
				continue;
			match1:
				{
					var op = MatchAny();
					var rhs = AtomOrTypeParamExpr();
					// line 542
					e = F.Call((Symbol) op.Value, e, rhs, e.Range.StartIndex, rhs.Range.EndIndex, op.StartIndex, op.EndIndex, NodeStyle.Operator);
				}
			}
		stop:;
		}
コード例 #33
0
ファイル: StandardMacros.cs プロジェクト: jonathanvdc/Loyc
		public static LNode runSequence(LNode node, IMacroContext context)
		{
			if (context.Parent.Calls(S.Braces)) { 
				if (node.ArgCount == 1 && node.Args[0].Calls(S.Braces))
					return node.WithArgs(node.Args[0].Args);
				return node.WithTarget(S.Splice);
			}
			return Reject(context, node, "#useVarDeclExpressions is required to make #runSequence work");
		}
コード例 #34
0
		private static bool DetectSetOrCreateMember(LNode arg, out Symbol relevantAttribute, out Symbol fieldName, out Symbol paramName, out LNode newArg, out LNode propOrFieldDecl)
		{
			relevantAttribute = null;
			fieldName = null;
			paramName = null;
			newArg = null;
			propOrFieldDecl = null;
			LNode _, type, name, defaultValue, propArgs;
			if (EcsValidators.IsPropertyDefinition(arg, out type, out name, out propArgs, out _, out defaultValue) && propArgs.ArgCount == 0) {
				// #property(Type, Name<T>, {...})
				relevantAttribute = S.Property;
				fieldName = EcsNodePrinter.KeyNameComponentOf(name);
				paramName = ChooseArgName(fieldName);
				if (defaultValue != null) { // initializer is Args[4]
					newArg = LNode.Call(S.Var, LNode.List(type, F.Assign(paramName, defaultValue)), arg);
					propOrFieldDecl = arg.WithArgs(arg.Args.First(4));
				} else {
					newArg = LNode.Call(S.Var, LNode.List(type, F.Id(paramName)), arg);
					propOrFieldDecl = arg;
				}
				DSOCM_DistributeAttributes(arg.Attrs, ref newArg, ref propOrFieldDecl);
				return true;
			} else if (IsVar(arg, out type, out paramName, out defaultValue)) {
				int a_i = 0;
				foreach (var attr in arg.Attrs) {
					if (attr.IsId) {
						var a = attr.Name;
						if (a == _set || FieldCreationAttributes.Contains(a))
						{
							relevantAttribute = a;
							fieldName = paramName;
							paramName = ChooseArgName(fieldName);
							if (a == _set) {
								newArg = F.Var(type, paramName, defaultValue).WithAttrs(arg.Attrs.Without(attr));
							} else {
								// in case of something like "[A] public params T arg = value", 
								// assume that "= value" represents a default value, not a field 
								// initializer. Most attributes stay on the argument.
								newArg = arg.WithArgChanged(1, 
									defaultValue != null ? F.Assign(paramName, defaultValue) : F.Id(paramName));
								propOrFieldDecl = LNode.Call(S.Var, LNode.List(type, F.Id(fieldName)), arg);
								DSOCM_DistributeAttributes(arg.Attrs, ref newArg, ref propOrFieldDecl);
							}
							break;
						}
					}
					a_i++;
				}
				return newArg != null;
			}
			return false;
		}
コード例 #35
0
		public static LNode SetOrCreateMember(LNode fn, IMessageSink sink)
		{
			// Expecting #fn(Type, Name, #(args), {body})
			if (fn.ArgCount < 3 || !fn.Args[2].Calls(S.AltList))
				return null;
			var args = fn.Args[2].Args;

			VList<LNode> propOrFieldDecls = VList<LNode>.Empty;
			Dictionary<Symbol, LNode> assignments = null;
			for (int i = 0; i < args.Count; i++) {
				var arg = args[i];
				Symbol relevantAttribute, fieldName, paramName;
				LNode plainArg, propOrFieldDecl;
				if (DetectSetOrCreateMember(arg, out relevantAttribute, out fieldName, out paramName, out plainArg, out propOrFieldDecl))
				{
					if (fn.ArgCount < 4)
						return Reject(sink, arg, Localize.Localized("'{0}': to set or create a field or property, the method must have a body in braces {{}}.", relevantAttribute));

					args[i] = plainArg;
					assignments = assignments ?? new Dictionary<Symbol, LNode>();
					assignments[fieldName] = F.Id(paramName);
					if (propOrFieldDecl != null)
						propOrFieldDecls.Add(propOrFieldDecl);
				}
			}

			if (assignments != null) // if this macro has been used...
			{
				var parts = fn.Args;
				parts[2] = parts[2].WithArgs(args);
				var body = parts[3];
				
				// Ensure the method has a normal braced body
				if (!body.Calls(S.Braces)) {
					if (parts[0].IsIdNamed(S.Void))
						body = F.Braces(body);
					else
						body = F.Braces(F.Call(S.Return, body));
				}

				// In case one constructor calls another, we have to ensure that the 
				// assignments are inserted _after_ that call, and if the constructor
				// call refers to properties or fields that will be set, we must remap
				// those references onto parameters, e.g.
				//   this(public int X) { base(X); } => this(int x) { base(x); X = x; }
				var bodyStmts = body.Args;
				int indexAtWhichToDoAssignments = 0;
				if (fn.Calls(S.Constructor)) {
					LNode baseCall = bodyStmts[0, LNode.Missing];
					if (baseCall.Calls(S.Base) || baseCall.Calls(S.This)) {
						bodyStmts[0] = baseCall.ReplaceRecursive(n => {
							LNode param;
							if (n.IsId && assignments.TryGetValue(n.Name, out param))
								return param;
							return null;
						});
						indexAtWhichToDoAssignments = 1;
					}
				}

				// Insert assignment statements
				parts[3] = body.WithArgs(bodyStmts.InsertRange(indexAtWhichToDoAssignments, assignments.Select(p => {
					if (p.Key == p.Value.Name)
						return F.Call(S.Assign, F.Dot(F.@this, F.Id(p.Key)), p.Value);
					else
						return F.Call(S.Assign, F.Id(p.Key), p.Value);
				}).ToList()));

				fn.Style &= ~NodeStyle.OneLiner;
				foreach (var p in parts)
					p.Style &= ~NodeStyle.OneLiner;

				// Return output code
				fn = fn.WithArgs(parts);
				if (propOrFieldDecls.IsEmpty)
					return fn;
				else {
					propOrFieldDecls.Add(fn);
					return F.Call(S.Splice, propOrFieldDecls);
				}
			}
			return null;
		}
コード例 #36
0
		public static LNode SetOrCreateMember(LNode fn, IMessageSink sink)
		{
			// Expecting #fn(Type, Name, #(args), {body})
			if (fn.ArgCount < 3 || !fn.Args[2].Calls(S.AltList))
				return null;
			var args = fn.Args[2].Args;
			LNode body = null;

			RVList<LNode> createStmts = RVList<LNode>.Empty;
			RVList<LNode> setStmts = RVList<LNode>.Empty;
			for (int i = 0; i < args.Count; i++) {
				var arg = args[i];
				Symbol a = S.Property;
				Symbol fieldName = null;
				Symbol paramName = null;
				LNode plainArg = null;
				LNode createStmt = null;
				if (arg.Calls(S.Property)) {
					// #property(Type, Name<T>, {...})
					var name = arg.Args[1];
					fieldName = Ecs.EcsNodePrinter.KeyNameComponentOf(name);
					paramName = ChooseArgName(fieldName);
					plainArg = F.Var(arg.Args[0], paramName);
					createStmt = arg;
				} else {
					LNode type, defaultValue;
					if (IsVar(arg, out type, out paramName, out defaultValue)) {
						int a_i = 0;
						foreach (var attr in arg.Attrs) {
							if (attr.IsId) {
								a = attr.Name;
								if (a == _set 
									|| a == S.Public || a == S.Internal || a == S.Protected || a == S.Private
									|| a == S.ProtectedIn || a == S.Static || a == S.Partial)
								{
									fieldName = paramName;
									paramName = ChooseArgName(fieldName);
									if (a == _set) {
										plainArg = F.Var(type, paramName, defaultValue).WithAttrs(arg.Attrs.RemoveAt(a_i));
									} else {
										// in case of something like "[A] public params T arg = value", 
										// assume that "= value" represents a default value, not a field 
										// initializer, that [A] belongs on the field, except `params` 
										// which stays on the argument.
										plainArg = F.Var(type, paramName, defaultValue);
										createStmt = arg;
										if (arg.Args[1].Calls(S.Assign, 2))
											createStmt = arg.WithArgChanged(1,
												arg.Args[1].Args[0]);
										int i_params = arg.Attrs.IndexWithName(S.Params);
										if (i_params > -1)
										{
											plainArg = plainArg.PlusAttr(arg.Attrs[i_params]);
											createStmt = createStmt.WithAttrs(createStmt.Attrs.RemoveAt(i_params));
										}
									}
									break;
								}
							}
							a_i++;
						}
					}
				}
				if (plainArg != null)
				{
					if (body == null)
					{
						if (fn.ArgCount < 4 || !fn.Args[3].Calls(S.Braces))
							return Reject(sink, arg, Localize.From("'{0}': to set or create a field or property, the method must have a body in braces {{}}.", a));
						body = fn.Args[3];
					}

					args[i] = plainArg;
					LNode assignment;
					if (fieldName == paramName)
						assignment = F.Call(S.Assign, F.Dot(F.@this, F.Id(fieldName)), F.Id(paramName));
					else
						assignment = F.Call(S.Assign, F.Id(fieldName), F.Id(paramName));
					setStmts.Add(assignment);
					if (createStmt != null)
						createStmts.Add(createStmt);
				}
			}
			if (body != null) // if this macro has been used...
			{
				var parts = fn.Args;
				parts[2] = parts[2].WithArgs(args);
				parts[3] = body.WithArgs(body.Args.InsertRange(0, setStmts));
				fn = fn.WithArgs(parts);
				if (createStmts.IsEmpty)
					return fn;
				else {
					createStmts.Add(fn);
					return F.Call(S.Splice, createStmts);
				}
			}
			return null;
		}
コード例 #37
0
			LNode ProcessBlockCallStmt(LNode stmt, int childStmtsStartAt)
			{
				List<LNode> childStmts = stmt.Args.Slice(childStmtsStartAt).ToList();
				LNode partialStmt = stmt.WithArgs(stmt.Args.First(childStmtsStartAt));
				VList<LNode> advanceSequence;
				if (ProcessBlockCallStmt2(ref partialStmt, out advanceSequence, childStmts)) {
					stmt = partialStmt.PlusArgs(childStmts);
					if (advanceSequence.Count != 0)
						return LNode.Call(CodeSymbols.Braces, LNode.List().AddRange(advanceSequence).Add(stmt)).SetStyle(NodeStyle.Statement);
					return stmt;	// only the child statements changed
				} else
					return stmt;	// no changes
			}
コード例 #38
0
			public LNode EliminateSequenceExpressions(LNode stmt, bool isDeclContext)
			{
				LNode retType, name, argList, bases, body, initValue;
				if (EcsValidators.SpaceDefinitionKind(stmt, out name, out bases, out body) != null) {
					// Space definition: class, struct, etc.
					return body == null ? stmt : stmt.WithArgChanged(2, EliminateSequenceExpressions(body, true));
				} else if (EcsValidators.MethodDefinitionKind(stmt, out retType, out name, out argList, out body, true) != null) {
					// Method definition
					return body == null ? stmt : stmt.WithArgChanged(3, EliminateSequenceExpressionsInLambdaExpr(body, retType));
				} else if (EcsValidators.IsPropertyDefinition(stmt, out retType, out name, out argList, out body, out initValue)) {
					// Property definition
					stmt = stmt.WithArgChanged(3, 
					body.WithArgs(part => {
						if (part.ArgCount == 1 && part[0].Calls(S.Braces))
							part = part.WithArgChanged(0, EliminateSequenceExpressions(part[0], false));
						return part;
					}));
					if (initValue != null) {
						var initMethod = EliminateRunSeqFromInitializer(retType, name, ref initValue);
						if (initMethod != null) {
							stmt = stmt.WithArgChanged(4, initValue);
							return LNode.Call((Symbol) "#runSequence", LNode.List(stmt, initMethod));
						}
					}
					return stmt;
				} else if (stmt.Calls(CodeSymbols.Braces)) {
					return stmt.WithArgs(EliminateSequenceExpressions(stmt.Args, isDeclContext));
				} else if (!isDeclContext) {
					return EliminateSequenceExpressionsInExecStmt(stmt);
				} else if (stmt.CallsMin(S.Var, 2)) {
					// Eliminate blocks from field member
					var results = new List<LNode> { 
						stmt
					};
					var vars = stmt.Args;
					var varType = vars[0];
					for (int i = 1; i < vars.Count; i++) {
						var @var = vars[i];
						if (@var.Calls(CodeSymbols.Assign, 2) && (name = @var.Args[0]) != null && (initValue = @var.Args[1]) != null) {
							var initMethod = EliminateRunSeqFromInitializer(varType, name, ref initValue);
							if (initMethod != null) {
								results.Add(initMethod);
								vars[i] = vars[i].WithArgChanged(1, initValue);
							}
						}
					}
					if (results.Count > 1) {
						results[0] = stmt.WithArgs(vars);
						return LNode.List(results).AsLNode(__numrunSequence);
					}
					return stmt;
				} else
					return stmt;
			}
コード例 #39
0
			// Creates a temporary for an LValue (left side of `=`, or `ref` parameter)
			// e.g. f(x).Foo becomes f(x_N).Foo, and `var x_N = x` is added to `stmtSequence`,
			// where N is a unique integer for the temporary variable.
			LNode MaybeCreateTemporaryForLValue(LNode expr, ref VList<LNode> stmtSequence)
			{
				{
					LNode _, lhs;
					if (expr.Calls(CodeSymbols.Dot, 2) && (lhs = expr.Args[0]) != null || expr.CallsMin(CodeSymbols.Of, 1) && (lhs = expr.Args[0]) != null)
						return expr.WithArgChanged(0, MaybeCreateTemporaryForLValue(lhs, ref stmtSequence));
					else if ((_ = expr) != null && !_.IsCall)
						return expr;
					else {
						var args = expr.Args.ToWList();
						int i = 0;
						if (expr.CallsMin(S.IndexBracks, 1) || expr.CallsMin(S.NullIndexBracks, 1)) {
							// Consider foo[i]. We cannot always store `foo` in a temporary, as
							// this may change the code's behavior in case `foo` is a struct.
							i = 1;
						}
						for (; i < args.Count; i++) {
							if (!args[i].IsLiteral && !args[i].Attrs.Contains(_trivia_isTmpVar)) {
								LNode tmpVarName;
								stmtSequence.Add(TempVarDecl(Context, args[i], out tmpVarName));
								args[i] = tmpVarName.PlusAttr(_trivia_isTmpVar);
							}
						}
						return expr.WithArgs(args.ToVList());
					}
				}
			}
コード例 #40
0
            public LNode EliminateBlockExprs(LNode stmt, bool isDeclContext)
            {
                LNode retType, name, argList, bases, body, initValue;

                if (EcsValidators.SpaceDefinitionKind(stmt, out name, out bases, out body) != null)
                {
                    return(body == null ? stmt : stmt.WithArgChanged(2, EliminateBlockExprs(body, true)));
                }
                else if (EcsValidators.MethodDefinitionKind(stmt, out retType, out name, out argList, out body, true) != null)
                {
                    return(body == null ? stmt : stmt.WithArgChanged(3, EliminateBlockExprs(body, false)));
                }
                else if (EcsValidators.IsPropertyDefinition(stmt, out retType, out name, out argList, out body, out initValue))
                {
                    stmt = stmt.WithArgChanged(3, EliminateBlockExprs(body, false));
                    if (initValue != null)
                    {
                        var initMethod = EliminateRunSeqFromInitializer(retType, name, ref initValue);
                        if (initMethod != null)
                        {
                            stmt = stmt.WithArgChanged(4, initValue);
                            return(LNode.Call(CodeSymbols.Splice, LNode.List(stmt, initMethod)));
                        }
                    }
                    return(stmt);
                }
                else if (!isDeclContext)
                {
                    return(EliminateBlockExprsInExecStmt(stmt));
                }
                else if (stmt.CallsMin(S.Var, 2))
                {
                    var results = new List <LNode> {
                        stmt
                    };
                    var vars    = stmt.Args;
                    var varType = vars[0];
                    for (int i = 1; i < vars.Count; i++)
                    {
                        {
                            var tmp_1 = vars[i];
                            if (tmp_1.Calls(CodeSymbols.Assign, 2) && (name = tmp_1.Args[0]) != null && (initValue = tmp_1.Args[1]) != null)
                            {
                                var initMethod = EliminateRunSeqFromInitializer(varType, name, ref initValue);
                                if (initMethod != null)
                                {
                                    results.Add(initMethod);
                                    vars[i] = vars[i].WithArgChanged(1, initValue);
                                }
                            }
                        }
                    }
                    if (results.Count > 1)
                    {
                        results[0] = stmt.WithArgs(vars);
                        return(LNode.List(results).AsLNode(S.Splice));
                    }
                    return(stmt);
                }
                else
                {
                    return(stmt);
                }
            }
コード例 #41
0
			LNode EliminateSequenceExpressionsInExecStmt(LNode stmt)
			{
				{
					LNode block, collection, cond, init, initValue, loopVar, name, tmp_11, tmp_12, type;
					VList<LNode> attrs, incs, inits;
					if (stmt.Calls(CodeSymbols.Braces))
						return stmt.WithArgs(EliminateSequenceExpressions(stmt.Args, false));
					else if (stmt.CallsMin(CodeSymbols.If, 1) || stmt.Calls(CodeSymbols.UsingStmt, 2) || stmt.Calls(CodeSymbols.Lock, 2) || stmt.Calls(CodeSymbols.Switch, 2) && stmt.Args[1].Calls(CodeSymbols.Braces))
						return ProcessBlockCallStmt(stmt, 1);
					else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.Fixed, 2) && (init = stmt.Args[0]) != null && (block = stmt.Args[1]) != null) {
						init = EliminateSequenceExpressionsInExecStmt(init);
						block = EliminateSequenceExpressionsInChildStmt(block);
						if (init.CallsMin(__numrunSequence, 1)) {
							return LNode.Call(LNode.List(attrs), CodeSymbols.Braces, LNode.List().AddRange(init.Args.WithoutLast(1)).Add(LNode.Call(CodeSymbols.Fixed, LNode.List(init.Args.Last, block)))).SetStyle(NodeStyle.Statement);
						} else
							return stmt.WithArgChanged(1, block);
					} else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.While, 2) && (cond = stmt.Args[0]) != null && (block = stmt.Args[1]) != null) {
						cond = BubbleUpBlocks(cond);
						block = EliminateSequenceExpressionsInChildStmt(block);
						if (cond.CallsMin(__numrunSequence, 1)) {
							return LNode.Call(LNode.List(attrs), CodeSymbols.For, LNode.List(LNode.Call(CodeSymbols.AltList), LNode.Missing, LNode.Call(CodeSymbols.AltList), LNode.Call(CodeSymbols.Braces, LNode.List().AddRange(cond.Args.WithoutLast(1)).Add(LNode.Call(CodeSymbols.If, LNode.List(cond.Args.Last, block, LNode.Call(CodeSymbols.Break))))).SetStyle(NodeStyle.Statement)));
						} else
							return stmt.WithArgChanged(1, block);
					} else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.DoWhile, 2) && (block = stmt.Args[0]) != null && (cond = stmt.Args[1]) != null) {
						block = EliminateSequenceExpressionsInChildStmt(block);
						cond = BubbleUpBlocks(cond);
						if (cond.CallsMin(__numrunSequence, 1)) {
							var continue_N = F.Id(NextTempName(Context, "continue_"));
							var bodyStmts = block.AsList(S.Braces);
							bodyStmts.AddRange(cond.Args.WithoutLast(1));
							bodyStmts.Add(LNode.Call(CodeSymbols.Assign, LNode.List(continue_N, cond.Args.Last)).SetStyle(NodeStyle.Operator));
							return LNode.Call(LNode.List(attrs), CodeSymbols.For, LNode.List(LNode.Call(CodeSymbols.AltList, LNode.List(LNode.Call(CodeSymbols.Var, LNode.List(LNode.Id(CodeSymbols.Bool), LNode.Call(CodeSymbols.Assign, LNode.List(continue_N, LNode.Literal(true))))))), continue_N, LNode.Call(CodeSymbols.AltList), LNode.Call(CodeSymbols.Braces, LNode.List(bodyStmts)).SetStyle(NodeStyle.Statement)));
						} else
							return stmt.WithArgChanged(0, block);
					} else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.For, 4) && stmt.Args[0].Calls(CodeSymbols.AltList) && (cond = stmt.Args[1]) != null && stmt.Args[2].Calls(CodeSymbols.AltList) && (block = stmt.Args[3]) != null) {
						inits = stmt.Args[0].Args;
						incs = stmt.Args[2].Args;
						return ESEInForLoop(stmt, attrs, inits, cond, incs, block);
					} else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.ForEach, 3) && (tmp_11 = stmt.Args[0]) != null && tmp_11.Calls(CodeSymbols.Var, 2) && (type = tmp_11.Args[0]) != null && (loopVar = tmp_11.Args[1]) != null && (collection = stmt.Args[1]) != null && (block = stmt.Args[2]) != null) {
						block = EliminateSequenceExpressionsInChildStmt(block);
						collection = BubbleUpBlocks(collection);
						if (collection.CallsMin(__numrunSequence, 1)) {
							return LNode.Call(LNode.List(attrs), CodeSymbols.Braces, LNode.List().AddRange(collection.Args.WithoutLast(1)).Add(LNode.Call(CodeSymbols.ForEach, LNode.List(LNode.Call(CodeSymbols.Var, LNode.List(type, loopVar)), collection.Args.Last, block)))).SetStyle(NodeStyle.Statement);
						} else {
							return stmt.WithArgChanged(stmt.Args.Count - 1, block);
						}
					} else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.Var, 2) && (type = stmt.Args[0]) != null && (tmp_12 = stmt.Args[1]) != null && tmp_12.Calls(CodeSymbols.Assign, 2) && (name = tmp_12.Args[0]) != null && (initValue = tmp_12.Args[1]) != null) {
						var initValue_apos = BubbleUpBlocks(initValue);
						if (initValue_apos != initValue) {
							{
								LNode last;
								VList<LNode> stmts;
								if (initValue_apos.CallsMin((Symbol) "#runSequence", 1) && (last = initValue_apos.Args[initValue_apos.Args.Count - 1]) != null) {
									stmts = initValue_apos.Args.WithoutLast(1);
									return LNode.Call((Symbol) "#runSequence", LNode.List().AddRange(stmts).Add(LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(type, LNode.Call(CodeSymbols.Assign, LNode.List(name, last))))));
								} else
									return LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(type, LNode.Call(CodeSymbols.Assign, LNode.List(name, initValue_apos))));
							}
						}
					} else if (stmt.CallsMin(S.Try, 2)) {
						return ESEInTryStmt(stmt);
					} else if (stmt.HasSpecialName && stmt.ArgCount >= 1 && stmt.Args.Last.Calls(S.Braces)) {
						return ProcessBlockCallStmt(stmt, stmt.ArgCount - 1);
					} else {
						// Ordinary expression statement
						return BubbleUpBlocks(stmt, stmtContext: true);
					}
				}
				return stmt;
			}
コード例 #42
0
			LNode ESEInTryStmt(LNode stmt)
			{
				var args = stmt.Args.ToWList();
				// Process `try` part
				args[0] = EliminateSequenceExpressionsInChildStmt(args[0]);
				// Process `catch` and `finally` clauses (`when` clause not supported)
				for (int i = 1; i < args.Count; i++) {
					var part = args[i];
					if (part.Calls(S.Finally, 1) || part.Calls(S.Catch, 3)) {
						int lasti = part.ArgCount - 1;
						args[i] = part.WithArgChanged(lasti, EliminateSequenceExpressionsInChildStmt(part.Args[lasti]));
					}
				}
				return stmt.WithArgs(args.ToVList());
			}
コード例 #43
0
ファイル: Prelude.cs プロジェクト: BingjieGao/Loyc
		public static LNode of(LNode node, IMessageSink sink)
		{
			LNode kind;
			if (node.ArgCount == 2 && (kind = node.Args[0]).IsId) {
				if (kind.IsIdNamed(_array)) return node.WithArgChanged(0, kind.WithName(S.Array));
				if (kind.IsIdNamed(_opt))   return node.WithArgChanged(0, kind.WithName(S.QuestionMark));
				if (kind.IsIdNamed(_ptr))   return node.WithArgChanged(0, kind.WithName(S._Pointer));
			} else if (node.ArgCount == 3 && (kind = node.Args[0]).IsIdNamed(_array) && node.Args[1].IsLiteral) {
				return node.WithArgs(kind.WithName(S.GetArrayKeyword((int)node.Args[1].Value)), node.Args[2]);
			}
			return null;
		}
コード例 #44
0
			LNode ConvertVarDeclToRunSequence(VList<LNode> attrs, LNode varType, LNode varName, LNode initValue)
			{
				initValue = BubbleUpBlocks(initValue);
				varType = varType ?? F.Missing;
				LNode @ref;
				attrs = attrs.WithoutNodeNamed(S.Ref, out @ref);
				var varName_apos = varName.PlusAttr(_trivia_isTmpVar);
				if (@ref != null)
					varName_apos = varName_apos.PlusAttr(@ref);
				{
					LNode resultValue;
					VList<LNode> stmts;
					if (initValue.CallsMin((Symbol) "#runSequence", 1) && (resultValue = initValue.Args[initValue.Args.Count - 1]) != null) {
						stmts = initValue.Args.WithoutLast(1);
						var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, resultValue))));
						return initValue.WithArgs(stmts.Add(newVarDecl).Add(varName_apos));
					
					} else {
						var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, initValue))));
						return LNode.Call((Symbol) "#runSequence", LNode.List(newVarDecl, varName_apos));
					}
				}
			}
コード例 #45
0
ファイル: StandardMacros.cs プロジェクト: jonathanvdc/Loyc
		public static LNode Namespace(LNode node, IMacroContext context)
		{
			if (node.ArgCount == 2 && !node.Args.Last.Calls(S.Braces))
			{
				context.DropRemainingNodes = true;
				return node.WithArgs(node.Args.Add(F.Braces(context.RemainingNodes)));
			}
			return null;
		}
コード例 #46
0
			// Bubbles up a call. The returned pair consists of 
			// 1. A sequence of statements to run before the call
			// 2. The call with all (outer) #runSequences removed
			Pair<VList<LNode>, LNode> BubbleUp_GeneralCall2(LNode expr)
			{
				var target = expr.Target;
				var args = expr.Args;
				var combinedSequence = LNode.List();
			
				// Bubbe up target
				target = BubbleUpBlocks(target);
				if (target.CallsMin(__numrunSequence, 1)) {
					combinedSequence = target.Args.WithoutLast(1);
					expr = expr.WithTarget(target.Args.Last);
				}
			
				// Bubble up each argument
				var isAssignment = EcsValidators.IsAssignmentOperator(expr.Name);
				if (isAssignment) {
					LNode lhs = BubbleUpBlocks(expr.Args[0]);
					LNode rhs = BubbleUpBlocks(expr.Args[1]);
					args = LNode.List(lhs, rhs);
				} else {	// most common case
					args = args.SmartSelect(arg => BubbleUpBlocks(arg));
				}
			
				int lastRunSeq = args.LastIndexWhere(a => a.CallsMin(__numrunSequence, 1));
				if (lastRunSeq >= 0) {
					// last index of #runSequence that is not marked pure
					int lastRunSeqImpure = args.First(lastRunSeq + 1).LastIndexWhere(a => 
					a.CallsMin(__numrunSequence, 1) && a.AttrNamed(_trivia_pure.Name) == null);
				
					if (lastRunSeq > 0 && 
					(args.Count == 2 && (target.IsIdNamed(S.And) || target.IsIdNamed(S.Or)) || args.Count == 3 && target.IsIdNamed(S.QuestionMark)))
					{
						Context.Sink.Error(target, 
						"#useSequenceExpressions is not designed to support sequences or variable declarations on the right-hand side of the `&&`, `||` or `?` operators. The generated code will be incorrect.");
					}
				
					var argsW = args.ToList();
					for (int i = 0; i <= lastRunSeq; i++) {
						LNode arg = argsW[i];
						if (!arg.IsLiteral) {
							if (arg.CallsMin(__numrunSequence, 1)) {
								combinedSequence.AddRange(arg.Args.WithoutLast(1));
								argsW[i] = arg = arg.Args.Last;
							}
							if (i < lastRunSeqImpure) {
								if (i == 0 && (expr.CallsMin(S.IndexBracks, 1) || expr.CallsMin(S.NullIndexBracks, 1))) {
									// Consider foo[#runSequence(f(), i)]. In case this appears in
									// an lvalue context and `foo` is a struct, we cannot store `foo` in 
									// a temporary, as this may silently change the code's behavior.
									// Better to take the risk of evaluating `foo` after `f()`.
								 } else {
									if (isAssignment || arg.Attrs.Any(a => a.IsIdNamed(S.Ref) || a.IsIdNamed(S.Out)))
										argsW[i] = MaybeCreateTemporaryForLValue(arg, ref combinedSequence);
									else {
										// Create a temporary variable to hold this argument
										LNode tmpVarName, tmpVarDecl = TempVarDecl(Context, arg, out tmpVarName);
										combinedSequence.Add(tmpVarDecl);
										argsW[i] = tmpVarName.PlusAttr(_trivia_isTmpVar);
									}
								}
							}
						}
					}
				
					expr = expr.WithArgs(LNode.List(argsW));
				}
			
				return Pair.Create(combinedSequence, expr);
			}
コード例 #47
0
ファイル: EcsParserGrammar.cs プロジェクト: BingjieGao/Loyc
		void WhereClausesOpt(ref LNode name)
		{
			TokenType la0;
			#line 1163 "EcsParserGrammar.les"
			var list = new BMultiMap<Symbol,LNode>();
			#line default
			// Line 1164: (WhereClause)*
			for (;;) {
				la0 = LA0;
				if (la0 == TT.ContextualKeyword)
					list.Add(WhereClause());
				else
					break;
			}
			#line 1165 "EcsParserGrammar.les"
			if ((list.Count != 0)) {
				if ((!name.CallsMin(S.Of, 2))) {
					Error("'{0}' is not generic and cannot use 'where' clauses.", name.ToString());
				} else {
					var tparams = name.Args.ToRWList();
					for (int i = 1; i < tparams.Count; i++) {
						var wheres = list[TParamSymbol(tparams[i])];
						tparams[i] = tparams[i].PlusAttrs(wheres);
						wheres.Clear();
					}
					name = name.WithArgs(tparams.ToRVList());
					if ((list.Count > 0)) {
						Error(list[0].Value, "There is no type parameter named '{0}'", list[0].Key);
					}
				}
			}
			#line default
		}
コード例 #48
0
ファイル: Prelude.Les.cs プロジェクト: qwertie/ecsharp
		public static LNode @case(LNode node, IMessageSink sink)
		{
			if (node.ArgCount >= 2 && node.Args.Last.Calls(S.Braces))
				return F.Call(S.Splice, new VList<LNode>(node.WithArgs(node.Args.WithoutLast(1)), node.Args.Last));
			if (node.ArgCount >= 1)
				return node.WithTarget(S.Case);
			return null;
		}