Example #1
0
        private static LNode ValidateOnStmt(LNode node, IMacroContext context, out LNodeList restOfStmts, out LNode firstArg)
        {
            var   a = node.Args;
            LNode on_handler;

            restOfStmts = LNode.List();
            firstArg    = null;
            if (a.Count == 2)
            {
                firstArg = a[0];
            }
            else if (a.Count != 1)
            {
                return(null);
            }
            if (!(on_handler = a.Last).Calls(S.Braces))
            {
                return(null);
            }
            if (context.RemainingNodes.Count == 0)
            {
                context.Sink.Warning(node, "{0} should not be the final statement of a block.", node.Name);
            }
            restOfStmts = new LNodeList(context.RemainingNodes);
            context.DropRemainingNodes = true;
            return(on_handler);
        }
Example #2
0
        internal static MacroMode GetMacroMode(ref LNodeList attrs, LNode pattern)
        {
            MacroMode modes = 0;

            attrs = attrs.SmartWhere(attr =>
            {
                if (attr.IsId && Enum.TryParse(attr.Name.Name, out MacroMode mode))
                {
                    modes |= mode;
                    return(false);
                }
                return(true);
            });

            if (pattern.IsLiteral)
            {
                modes |= MacroMode.MatchEveryLiteral;
            }
            else if (pattern.IsId)
            {
                modes |= MacroMode.MatchIdentifierOnly;
            }
            else if (DecodeSubstitutionExpr(pattern, out _, out _, out _) != null)
            {
                modes |= MacroMode.MatchEveryCall | MacroMode.MatchEveryIdentifier | MacroMode.MatchEveryLiteral;
            }
            else if (!pattern.Target.IsId)
            {
                modes |= MacroMode.MatchEveryCall;                 // custom matching code needed
            }
            return(modes);
        }
 public LNodeList EliminateSequenceExpressions(LNodeList stmts, bool isDeclContext)
 {
     return(stmts.SmartSelectMany(stmt => {
         /*
          * // Optimization: scan find out whether this construct has any block
          * // expressions. If not, skip it.
          * hasBlockExprs = false;
          * stmt.ReplaceRecursive(new Func<LNode, Maybe<LNode>>(n => {
          *      if (!hasBlockExprs)
          *              hasBlockExprs = n.IsCall && (
          *                      (n.Calls(S.ColonColon, 2) && n.Args[1].IsId) ||
          *                      (n.Calls(S.Var, 2) && n.AttrNamed(S.Out) != null) ||
          *                      (n.Calls(S.In, 2) && n.Args[1].Calls(S.Braces)));
          *      return hasBlockExprs ? n : null;
          * }));
          * if (!hasBlockExprs)
          *      return stmt;
          */
         LNode result = EliminateSequenceExpressions(stmt, isDeclContext);
         if (result != stmt)
         {
             if (result.Calls(sy__numrunSequence))
             {
                 return result.Args;
             }
         }
         _arrayOf1[0] = result;
         return _arrayOf1;
     }));
 }
Example #4
0
        private static void DSOCM_DistributeAttributes(LNodeList attrs, ref LNode newArg, ref LNode propOrFieldDecl)
        {
            // Some word attributes like `public` and `static` move to the field
            // or property, as well as named parameters representing an attribute
            // target `field:` or `property:`; all others belong on the argument.
            // Example: given `[A] [field: B] public params T _arg = value`, we want
            // a field `[B] public T arg` and a parameter `[A] params T arg = value`.
            LNodeList argAttrs = LNodeList.Empty, fieldAttrs = LNodeList.Empty;

            foreach (var attr in attrs)
            {
                var name = attr.Name;
                if (attr.IsId && (FieldCreationAttributes.Contains(name) || name == S.Readonly))
                {
                    fieldAttrs.Add(attr);
                }
                else if (name == S.TriviaSLComment || name == S.TriviaNewline)
                {
                    fieldAttrs.Add(attr);                     // Put doc comments and leading newline on the field/prop
                }
                else if (attr.Calls(S.NamedArg, 2) && (attr.Args[0].IsIdNamed("field") || attr.Args[0].IsIdNamed("property")))
                {
                    fieldAttrs.Add(attr.Args[1]);
                }
                else
                {
                    argAttrs.Add(attr);
                }
            }
            propOrFieldDecl = propOrFieldDecl.WithAttrs(fieldAttrs);
            newArg          = newArg.WithAttrs(argAttrs);
        }
Example #5
0
        /// <summary>Searches a list of expressions/statements for one or more
        /// patterns, and performs replacements.</summary>
        /// <param name="stmts">A list of expressions/statements in which to search.</param>
        /// <param name="patterns">Each pair consists of (A) something to search
        /// for and (B) a replacement expression. Part A can use the substitution
        /// operator with an identifier inside (e.g. $Foo) to "capture" any
        /// subexpression, and part B can use the same substitution (e.g. $Foo)
        /// to insert the captured subexpression(s) into the output.</param>
        /// <param name="replacementCount">Number of replacements that occurred.</param>
        /// <returns>The result of applying the replacements.</returns>
        /// <remarks><see cref="LNodeExt.MatchesPattern"/> is used for matching.</remarks>
        public static LNodeList Replace(LNodeList stmts, Pair <LNode, LNode>[] patterns, out int replacementCount)
        {
            // This list is used to support simple token replacement in TokenTrees
            _tokenTreeRepls = InternalList <Triplet <Symbol, LNode, int> > .Empty;
            foreach (var pair in patterns)             // Look for Id => Id or Id => Literal
            {
                if (pair.A.IsId && (pair.B.IsId || pair.B.IsLiteral))
                {
                    _tokenTreeRepls.Add(new Triplet <Symbol, LNode, int>(pair.A.Name, pair.B, 0));
                }
            }

            // Scan the syntax tree for things to replace...
            int count  = 0;
            var temp   = new MMap <Symbol, LNode>();
            var output = stmts.SmartSelect(stmt => stmt.ReplaceRecursive(n => {
                LNode r = TryReplaceHere(n, patterns, temp);
                if (r != null)
                {
                    count++;
                }
                return(r);
            }));

            replacementCount = count;
            return(output);
        }
Example #6
0
 internal void AddParts(LNodeList parts)
 {
     foreach (var part in parts)
     {
         Parts.Add(new AdtParam(part, this));
     }
 }
Example #7
0
        internal static LNodeList GetArgNamesFromFormalArgList(LNode args, Action <LNode> onError)
        {
            LNodeList formalArgs = args.Args;
            LNodeList argList    = LNodeList.Empty;

            foreach (var formalArg in formalArgs)
            {
                if (!formalArg.Calls(S.Var, 2))
                {
                    onError(formalArg);
                }
                else
                {
                    LNode argName = formalArg.Args[1];
                    if (argName.Calls(S.Assign, 2))
                    {
                        argName = argName.Args[0];
                    }
                    LNode @ref = formalArg.AttrNamed(S.Ref) ?? formalArg.AttrNamed(S.Out);
                    if (@ref != null)
                    {
                        argName = argName.PlusAttr(@ref);
                    }
                    argList.Add(argName);
                }
            }
            return(argList);
        }
Example #8
0
        private static void WarnAboutMissingDollarSigns(LNodeList argList, IMacroContext context, LNode pattern, LNode replacement)
        {
            // Warn if a name appears in both pattern and replacement but uses $ in only one of the two.
            Dictionary <Symbol, LNode> pVars = ScanForVariables(pattern), rVars = ScanForVariables(replacement);
            // Also warn if it looks like all `$`s were forgotten.
            bool allIds = argList.Count > 0 && argList.All(n => !n.IsCall);

            foreach (var pair in pVars)
            {
                LNode rVar = rVars.TryGetValue(pair.Key, null);
                if (pair.Value.IsId)                 // id without `$` in pattern list
                {
                    if (rVar != null && (allIds || !rVar.IsId))
                    {
                        context.Sink.Warning(pair.Value, "`{0}` is written without `$`, so it may not match as intended.", pair.Value.Name);
                    }
                }
                else                 // $id in pattern list
                {
                    if (rVar != null && rVar.IsId)
                    {
                        context.Sink.Warning(rVar, "`{0}` appears in the output without `$` so replacement will not occur.", pair.Key);
                    }
                }
            }
        }
Example #9
0
        /// <summary>Given the contents of case statement like `matchCode` or
        /// `switch`, this method gets a list of the cases.</summary>
        /// <returns>The first item in each pair is a list of the cases associated
        /// with a single handler (for `default:`, the list is empty). The second
        /// item is the handler code.</returns>
        static internal VList <Pair <LNodeList, LNodeList> > GetCases(LNodeList body, IMessageSink sink)
        {
            var pairs = VList <Pair <LNodeList, LNodeList> > .Empty;

            for (int i = 0; i < body.Count; i++)
            {
                bool isDefault;
                if (body[i].Calls(S.Lambda, 2))
                {
                    var alts = body[i][0].WithoutOuterParens().AsList(S.Tuple).SmartSelect(UnwrapBraces);
                    pairs.Add(Pair.Create(alts, body[i][1].AsList(S.Braces)));
                }
                else if ((isDefault = IsDefaultLabel(body[i])) || body[i].CallsMin(S.Case, 1))
                {
                    var alts      = isDefault ? LNodeList.Empty : body[i].Args.SmartSelect(UnwrapBraces);
                    int bodyStart = ++i;
                    for (; i < body.Count && !IsDefaultLabel(body[i]) && !body[i].CallsMin(S.Case, 1); i++)
                    {
                    }
                    var handler = new LNodeList(body.Slice(bodyStart, i - bodyStart));
                    pairs.Add(Pair.Create(alts, handler));
                    i--;                        // counteract i++ when loop repeats (redo)
                }
                else
                {
                    Reject(sink, body[i], "expected 'case _:' or '_ => _'");
                    break;
                }
            }
            return(pairs);
        }
Example #10
0
            void ProcessRequiresAttribute(LNodeList conditions, Symbol mode, LNode variableName)
            {
                // Create a "Contract.Requires()" check for each provided condition.
                foreach (var condition_ in conditions)
                {
                    LNode condition = condition_;                       // make it writable so we can replace `_`
                    LNode conditionStr;

                    if (ReplaceContractUnderscore(ref condition, variableName))
                    {
                        if (variableName == null)
                        {
                            Context.Sink.Error(condition, "`{0}`: underscore has no meaning in this location.", mode);
                        }
                    }
                    if (mode == sy_assert)
                    {
                        PrependStmts.Add(LNode.Call((Symbol)"assert", LNode.List(condition)));                          // relies on assert() macro
                    }
                    else if (_haveCCRewriter)
                    {
                        PrependStmts.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id((Symbol)"Contract"), LNode.Id((Symbol)"Requires"))).SetStyle(NodeStyle.Operator), LNode.List(condition)));
                    }
                    else
                    {
                        conditionStr = ConditionToStringLit(condition, "Precondition failed: {1}");
                        PrependStmts.Add(LNode.Call(GetAssertMethodForRequires(), LNode.List(condition, conditionStr)));
                    }
                }
            }
Example #11
0
        protected void Test(string input, IParsingService inLang, string expected, IParsingService outLang, int maxExpand = 0xFFFF, IMessageSink sink = null)
        {
            MacroProcessor lemp      = NewLemp(maxExpand, inLang).With(l => l.Sink = sink);
            var            inputCode = new LNodeList(inLang.Parse(input, MessageSink.Default));

            Test(inputCode, lemp, expected, outLang);
        }
Example #12
0
        public LNodeList StmtList()
        {
            LNodeList result    = default(LNodeList);
            var       endMarker = LT0.Type() == TT.Literal && LT0.TypeMarker == null ? TT.EOF : TT.Semicolon;

            result = ExprList(ref endMarker);
            return(result);
        }
Example #13
0
 protected void AppendInitializersInside(Token group, ref LNodeList list)
 {
     if (Down(group.Children))
     {
         InitializerList(ref list);
         Up();
     }
 }
Example #14
0
            protected override void WriteOutput(InputOutput io)
            {
                LNodeList results = io.Output;

                Output.AppendFormat("// Generated from {1} by LeMP {2}.{0}", io.OutOptions.NewlineString,
                                    io.FileName, typeof(Compiler).Assembly.GetName().Version.ToString());
                io.OutPrinter.Print(results, Output, Sink, ParsingMode.File, io.OutOptions);
            }
Example #15
0
 public override LNode WithAttrs(LNodeList attrs)
 {
     if (attrs.Count == 0)
     {
         return(this);
     }
     return(new StdLiteralNodeWithAttrs <TValue>(attrs, _value, this));
 }
Example #16
0
 protected LNodeList AppendExprsInside(Token group, LNodeList list, bool allowTrailingComma = false, bool allowUnassignedVarDecl = false)
 {
     if (Down(group.Children))
     {
         ExprList(ref list, allowTrailingComma, allowUnassignedVarDecl);
         return(Up(list));
     }
     return(list);
 }
 public static LNodeList MaybeRemoveNoOpFromRunSeq(LNodeList runSeq)
 {
     // Delete final no-op in case of e.g. Foo()::id; => #runSequence(var id = Foo(); id)
     if (runSeq.Count > 1 && runSeq.Last.IsId)
     {
         return(runSeq.WithoutLast(1));
     }
     return(runSeq);
 }
Example #18
0
        protected override void Stmt(string text, LNode expected, Action <EcsPrinterOptions> configure = null, Mode mode = Mode.Both)
        {
            bool exprMode = (mode & Mode.Expression) != 0;

            if ((mode & (Mode.ParserTest | Mode.ExpectAndDropParserError)) == 0)
            {
                return;
            }
            var sink = (mode & Mode.ExpectAndDropParserError) != 0 ? new MessageHolder() : (IMessageSink)ConsoleMessageSink.Value;

            using (Token.SetToStringStrategy(TokenExt.ToString))             // debugging aid
            {
                // This is the easy way:
                //   LNode result = EcsLanguageService.Value.ParseSingle(text, sink, exprMode ? ParsingMode.Expressions : ParsingMode.Statements, preserveComments: true);
                // But to make debugging easier, I'll do it the long way:
                ILexer <Token> lexer        = EcsLanguageService.Value.Tokenize(new UString(text), "", sink);
                var            preprocessed = new EcsPreprocessor(lexer, true);
                var            treeified    = new TokensToTree(preprocessed, false);
                var            parser       = new EcsParser(treeified.Buffered(), lexer.SourceFile, sink, null);
                LNodeList      results      = exprMode ? LNode.List(parser.ExprStart(false)) : LNode.List(parser.ParseStmtsGreedy());

                // Inject comments
                var injector = new EcsTriviaInjector(preprocessed.TriviaList, preprocessed.SourceFile, (int)TokenType.Newline, "/*", "*/", "//", (mode & Mode.Expression) == 0);
                results = LNode.List(injector.Run(results.GetEnumerator()).ToList());

                LNode result = results.AsLNode(S.Splice);
                AreEqual(TokenType.EOF, parser.LT0.Type(), string.Format("Parser stopped before EOF at [{0}] in {1}", parser.LT0.StartIndex, text));

                if ((mode & Mode.IgnoreTrivia) != 0)
                {
                    result = result.ReplaceRecursive(n => n.IsTrivia ? Maybe <LNode> .NoValue : n, LNode.ReplaceOpt.ProcessAttrs).Value;
                }
                if (sink is MessageHolder)
                {
                    ((MessageHolder)sink).WriteListTo(TraceMessageSink.Value);
                    GreaterOrEqual(((MessageHolder)sink).List.Count(m => m.Severity >= Severity.Error), 1,
                                   "Expected an error but got none for " + text);
                    if (expected == null)
                    {
                        return;
                    }
                }
                if (!expected.Equals(result, LNode.CompareMode.TypeMarkers))
                {
                    if ((mode & Mode.CompareAsLes) != 0)
                    {
                        using (LNode.SetPrinter(Syntax.Les.Les3LanguageService.Value))
                            AreEqual(expected.ToString(), result.ToString());
                    }
                    else
                    {
                        AreEqual(expected, result);
                    }
                    Fail("{0} has a different type marker than {1}", expected, result);
                }
            }
        }
Example #19
0
        private static LNode RegisterSimpleMacro(LNodeList attrs, LNode pattern, LNode body, IMacroContext context)
        {
            if (DecodeSubstitutionExpr(pattern, out _, out _, out _) != null)
            {
                return(Reject(context, pattern, "Defining a macro that could match everything is not allowed."));
            }

            MacroMode modes = GetMacroMode(ref attrs, pattern);

            LNode macroName   = pattern.Target ?? pattern;
            LNode replacement = body.AsList(S.Braces).AsLNode(S.Splice);

            if (pattern.IsCall)
            {
                WarnAboutMissingDollarSigns(pattern.Args, context, pattern, replacement);
            }

            // Note: we could fill out the macro's Syntax and Description with the
            // pattern and replacement converted to strings, but it's generally a
            // waste of CPU time as those strings are usually not requested.
            // Compromise: provide syntax pattern only
            var syntax = pattern.ToString();
            var lma    = new LexicalMacroAttribute(syntax, "User-defined macro at {0}".Localized(pattern.Range.Start), macroName.Name.Name)
            {
                Mode = modes
            };

            if ((modes & (MacroMode.MatchEveryLiteral | MacroMode.MatchEveryCall | MacroMode.MatchEveryIdentifier)) != 0)
            {
                lma = new LexicalMacroAttribute(syntax, lma.Description)
                {
                    Mode = modes
                }
            }
            ;

            var macroInfo = new MacroInfo(null, lma, UserDefinedMacro);

            macroInfo.Mode |= MacroMode.UseLogicalNameInErrorMessages;

            context.RegisterMacro(macroInfo);

            return(F.Splice());            // delete the `define` node from the output

            LNode UserDefinedMacro(LNode candidate, IMacroContext context2)
            {
                MMap <Symbol, LNode> captures = new MMap <Symbol, LNode>();

                if (candidate.MatchesPattern(pattern, ref captures, out LNodeList unmatchedAttrs))
                {
                    LNode replacement2 = WithUniqueIdentifiers(replacement, context.IncrementTempCounter, out _);
                    return(ReplaceCaptures(replacement2, captures).PlusAttrsBefore(unmatchedAttrs));
                }
                return(null);
            }
        }
Example #20
0
        // 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);
        }
Example #21
0
 private static bool AreValidLinqClauses(LNodeList parts, int i, Pedantics p)
 {
     for (; i < parts.Count; i++)
     {
         if (LinqClauseKind(parts[i], p) == null)
         {
             return(false);
         }
     }
     return(true);
 }
Example #22
0
        private LNodeList StmtListInside(Token t)
        {
            var list = new LNodeList();

            if (Down(t.Children))
            {
                StmtList(ref list);
                return(Up(list));
            }
            return(list);
        }
        private void PrintArgList(LNodeList args, ParenFor kind, bool allowUnassignedVarDecl, bool omitMissingArguments, char separator = ',')
        {
            var keepFlags = _flags & (Ambiguity.InPattern | Ambiguity.IsPattern);

            using (WithFlags(keepFlags | (allowUnassignedVarDecl ? Ambiguity.AllowUnassignedVarDecl : 0))) {
                WriteOpenParen(kind);
                _out.Indent(PrinterIndentHint.Brackets);
                PrintArgs(args, _flags, omitMissingArguments, separator);
                _out.Dedent(PrinterIndentHint.Brackets);
                WriteCloseParen(kind);
            }
        }
Example #24
0
            internal CodeGeneratorForMatchCase(IMacroContext context, LNode input, LNodeList handler)
            {
                _context = context;
                _input   = input;
                _handler = handler;
                var @break = LNode.Call(CodeSymbols.Break);

                if (_handler.IsEmpty || !_handler.Last.Equals(@break))
                {
                    _handler.Add(@break);
                }
            }
Example #25
0
 // Looks for contract attributes in a list and creates statements that
 // should be inserted at the beginning of the method that those attributes
 // are a part of. `variableName` is the name of the associated method
 // argument, or null if the attributes are attached to the return value or
 // the entire method. Returns the attribute list with contract attributes
 // removed.
 internal LNodeList Process(LNodeList attributes, LNode variableName, bool isPropSetter = false)
 {
     return(attributes.SmartWhere(attr => {
         LNode exceptionType = null;
         var mode = GetContractAttrMode(attr, out exceptionType);
         if (mode != null)
         {
             ProcessAttribute(attr, mode, exceptionType, variableName, isPropSetter);
             return false;                   // Remove contract attribute from method signature
         }
         return true;                        // No change
     }));
 }
Example #26
0
        public static LNode AddCsLineDirectives(LNode node, IMacroContext context)
        {
            if (node.ArgCount != 0)
            {
                return(null);
            }
            int sourceLine = -1;
            var list0      = new LNodeList(context.RemainingNodes);
            var list1      = context.PreProcess(list0);
            var list2      = AddLineDirectives(list1, true, ref sourceLine);

            context.DropRemainingNodes = true;
            return(F.Call(S.Splice, list2));
        }
Example #27
0
            // Generates a class declaration for the current alt and its subtypes
            internal void GenerateOutput(ref LNodeList list)
            {
                bool isAbstract = _classAttrs.Any(a => a.IsIdNamed(S.Abstract));

                var baseParts = new List <AdtParam>();

                for (var type = ParentType; type != null; type = type.ParentType)
                {
                    baseParts.InsertRange(0, type.Parts);
                }
                var allParts = baseParts.Concat(Parts);

                var initialization = Parts.Select(p => LNode.Call(CodeSymbols.Assign, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id(CodeSymbols.This), p.NameId)).SetStyle(NodeStyle.Operator), p.NameId)).SetStyle(NodeStyle.Operator)).ToList();

                if (baseParts.Count > 0)
                {
                    initialization.Insert(0, F.Call(S.Base, baseParts.Select(p => p.NameId)));
                }

                var args = new LNodeList(allParts.Select(p => p.OriginalDecl));

                if (!_constructorAttrs.Any(a => a.IsIdNamed(S.Public)))
                {
                    _constructorAttrs.Add(F.Id(S.Public));
                }
                LNode constructor = LNode.Call(LNode.List(_constructorAttrs), CodeSymbols.Constructor, LNode.List(LNode.Missing, _typeNameStem, LNode.Call(CodeSymbols.AltList, LNode.List(args)), LNode.Call(CodeSymbols.Braces, LNode.List().AddRange(initialization).AddRange(_extraConstrLogic)).SetStyle(NodeStyle.StatementBlock)));

                var outBody = new LNodeList();

                outBody.Add(constructor);
                outBody.AddRange(Parts.Select(p => p.GetFieldDecl()));
                outBody.AddRange(baseParts.Select(p => GetWithFn(p, isAbstract, S.Override, allParts)));
                outBody.AddRange(Parts.Select(p => GetWithFn(p, isAbstract, _children.Count > 0 ? S.Virtual : null, allParts)));
                outBody.AddRange(Parts.WithIndexes()
                                 .Where(kvp => kvp.Value.NameId.Name.Name != "Item" + (baseParts.Count + kvp.Key + 1))
                                 .Select(kvp => kvp.Value.GetItemDecl(baseParts.Count + kvp.Key + 1)));
                outBody.AddRange(_classBody);

                list.Add(LNode.Call(LNode.List(_classAttrs), CodeSymbols.Class, LNode.List(TypeName, LNode.Call(CodeSymbols.AltList, LNode.List(BaseTypes)), LNode.Call(CodeSymbols.Braces, LNode.List(outBody)).SetStyle(NodeStyle.StatementBlock))));
                if (_genericArgs.Count > 0 && Parts.Count > 0)
                {
                    var argNames = allParts.Select(p => p.NameId);
                    list.Add(LNode.Call(LNode.List().AddRange(_classAttrs).Add(LNode.Id(CodeSymbols.Static)).Add(LNode.Id(CodeSymbols.Partial)), CodeSymbols.Class, LNode.List(_typeNameStem, LNode.Call(CodeSymbols.AltList), LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(LNode.List(LNode.Id(CodeSymbols.Public), LNode.Id(CodeSymbols.Static)), CodeSymbols.Fn, LNode.List(TypeNameWithoutAttrs, LNode.Call(CodeSymbols.Of, LNode.List().Add(LNode.Id((Symbol)"New")).AddRange(_genericArgs)).SetStyle(NodeStyle.Operator), LNode.Call(CodeSymbols.AltList, LNode.List(args)), LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(LNode.Call(CodeSymbols.New, LNode.List(LNode.Call(TypeNameWithoutAttrs, LNode.List(argNames)))))))).SetStyle(NodeStyle.StatementBlock))))).SetStyle(NodeStyle.StatementBlock))));
                }
                foreach (var child in _children)
                {
                    child.GenerateOutput(ref list);
                }
            }
Example #28
0
        private static LNode CompileTimeMacro(string macroName, LNode node, IMacroContext context, bool alsoRuntime, bool wantPreprocess = true)
        {
            if (node.ArgCount != 1 || !node[0].Calls(S.Braces))
            {
                context.Error(node.Target, "{0} should have a single argument: a braced block.", macroName);
                return(null);
            }

            LNodeList code = node[0].Args;

            if (wantPreprocess)
            {
                if (context.Ancestors.Take(context.Ancestors.Count - 1).Any(
                        n => n.Name.IsOneOf(S.Class, S.Struct, S.Enum, S.Namespace) ||
                        n.Name.IsOneOf(S.Constructor, S.Fn, S.Property, S.Var)))
                {
                    context.Error(node.Target, "{0} is designed for use only at the top level of the file. It will be executed as though it is at the top level: any outer scopes will be ignored.", macroName);
                }

                code = context.PreProcess(code);
            }

            WriteHeaderCommentInSessionLog(node, context.Sink);

            // Remove namespace blocks (not supported by Roslyn scripting)
            LNode namespaceBlock     = null;
            var   codeSansNamespaces = code.RecursiveReplace(RemoveNamespaces);

            LNodeList?RemoveNamespaces(LNode n)
            {
                if (EcsValidators.SpaceDefinitionKind(n, out _, out _, out LNode body) == S.Namespace)
                {
                    namespaceBlock = n;
                    return(body.Args.RecursiveReplace(RemoveNamespaces));
                }
                return(null);
            }

            if (namespaceBlock != null && wantPreprocess)
            {
                context.Warning(namespaceBlock, "The C# scripting engine does not support namespaces. They will be ignored when running at compile time.");
            }

            RunCSharpCodeWithRoslyn(node, codeSansNamespaces, context);

            _roslynSessionLog?.Flush();
            return(alsoRuntime ? F.Splice(code) : F.Splice());
        }
 private void PrintArgs(LNodeList args, Ambiguity flags, bool omitMissingArguments, char separator = ',')
 {
     for (int i = 0; i < args.Count; i++)
     {
         var  arg     = args[i];
         bool missing = omitMissingArguments && IsSimpleSymbolWPA(arg, S.Missing) && args.Count > 1;
         if (i != 0)
         {
             WriteThenSpace(separator, missing ? SpaceOpt.MissingAfterComma : SpaceOpt.AfterComma);
         }
         if (!missing)
         {
             PrintExpr(arg, StartExpr, flags);
         }
     }
 }
Example #30
0
        /// <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()));
        }