[LexicalMacro("([notnull] (x => ...)); ([notnull] x) => ...; ([requires(expr)] x) => ...; " + "([ensures(expr)] (x => ...)); ([ensuresOnThrow(expr)] (x => ...)); ", "Generates Contract checks in a lambda function. See the documentation of " + "ContractsOnMethod for more information about the contract attributes.", "=>", Mode = MacroMode.Passive | MacroMode.PriorityInternalFallback)] public static LNode ContractsOnLambda(LNode fn, IMacroContext context) { LNode oldFn = fn; if (fn.ArgCount == 2) { var rw = new CodeContractRewriter(LNode.Missing, Id_lambda_function, context); fn = ProcessArgContractAttributes(fn, 0, rw, isLambda: true); if (fn.HasAttrs) { fn = fn.WithAttrs(rw.Process(fn.Attrs, null)); } if (rw.PrependStmts.IsEmpty) { return(null); } else { var body = fn.Args[1]; 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, rw.PrependStmts)); fn = fn.WithArgChanged(1, body); return(fn); } } return(null); }
protected LNode GenerateSetDecl(PGIntSet set, Symbol setName) { var ranges = set.InternalRangeList(); IEnumerable <object> args; Symbol method; if (ranges.Count * 2 < set.SizeIgnoringInversion) // use ranges { method = _NewSetOfRanges; args = ranges.SelectMany(r => { if (r.Lo >= 32 && r.Hi < 0xFFFC) { return new object[] { (char)r.Lo, (char)r.Hi } } ; else { return new object[] { r.Lo, r.Hi } }; }); } else { method = _NewSet; args = set.IntegerSequence(false).Select(n => set.IsCharSet && n >= 32 && n < 0xFFFC ? (object)(char)n : (object)(int)n); } return (F.Attr(F.Id(S.Static), F.Id(S.Readonly), F.Var(SetType, setName, ApiCall(method, LNode.List(args.Select(a => F.Literal(a))), true)))); }
[LexicalMacro("notnull T method(notnull T arg) {...}; T method([requires(expr)] T arg) {...}; " + "[requires(expr)] T method(...) {...}; [ensures(expr)] T method(...) {...}; " + "[ensuresOnThrow(expr)] T method(...) {...}; [ensuresOnThrow<Exception>(expr)] T method(...) {...}", "Generates Contract checks in a method.\n\n" + "- [requires(expr)] and [assert(expr)] specify an expression that must be true at the beginning of the method; assert conditions are checked in debug builds only, while \"requires\" conditions are checked in all builds. The condition can include an underscore `_` that refers to the argument that the attribute is attached to, if any.\n" + "- [ensures(expr)] and [ensuresAssert(expr)] specify an expression that must be true if-and-when the method returns normally. assert conditions are checked in debug builds only. The condition can include an underscore `_` that refers to the return value of the method.\n" + "- [ensuresFinally(expr)] specifies an expression that must be true when the method exits, whether by exception or by a normal return. This is implemented by wrapping the method in a try-finally block.\n" + "- [ensuresOnThrow(expr)] and [ensuresOnThrow<ExceptionType>(expr)] specify a condition that must be true if the method throws an exception. When #haveContractRewriter is false, underscore `_` refers to the thrown exception object; this is not available in the MS Code Contracts Rewriter.\n" + "- notnull is equivalent to [requires(_ != null)] if applied to an argument, and [ensures(_ != null)] if applied to the method as a whole.\n" + "\nAll contract attributes (except notnull) can specify multiple expressions separated by commas, to produce multiple checks, each with its own error message.", "#fn", "#cons", Mode = MacroMode.Passive | MacroMode.PriorityInternalFallback)] public static LNode ContractsOnMethod(LNode fn, IMacroContext context) { LNode fnArgs, oldFn = fn; if (fn.ArgCount >= 4) { var rw = new CodeContractRewriter(fn.Args[0], fn.Args[1], context); fn = ProcessArgContractAttributes(fn, 2, rw); if (fn.Args[0].HasAttrs) { fn = fn.WithArgChanged(0, fn.Args[0].WithAttrs(rw.Process(fn.Args[0].Attrs, null))); } if (fn.HasAttrs) { fn = fn.WithAttrs(rw.Process(fn.Attrs, null)); } if (rw.PrependStmts.IsEmpty) { return(null); } else { var body = fn.Args[3]; 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, rw.PrependStmts)); fn = fn.WithArgChanged(3, body); return(fn); } } return(null); }
public static LNode match(LNode node, IMacroContext context) { { LNode input; VList <LNode> contents; if (node.Args.Count == 2 && (input = node.Args[0]) != null && node.Args[1].Calls(CodeSymbols.Braces)) { contents = node.Args[1].Args; var outputs = new WList <LNode>(); input = MaybeAddTempVarDecl(context, input, outputs); int next_i = 0; for (int case_i = 0; case_i < contents.Count; case_i = next_i) { var @case = contents[case_i]; if (!IsCaseLabel(@case)) { return(Reject(context, contents[0], "In 'match': expected 'case' statement")); } for (next_i = case_i + 1; next_i < contents.Count; next_i++) { var stmt = contents[next_i]; if (IsCaseLabel(stmt)) { break; } if (stmt.Calls(S.Break, 0)) { next_i++; break; } } var handler = new VList <LNode>(contents.Slice(case_i + 1, next_i - (case_i + 1))); if (@case.Calls(S.Case) && @case.Args.Count > 0) { var codeGen = new CodeGeneratorForMatchCase(context, input, handler); foreach (var pattern in @case.Args) { outputs.Add(codeGen.GenCodeForPattern(pattern)); } } else // default: // Note: the extra {braces} around the handler are rarely // needed. They are added just in case the handler declares a // variable and a different handler declares another variable // by the same name, which is illegal unless we add braces. { outputs.Add(LNode.Call(CodeSymbols.Braces, LNode.List(handler)).SetStyle(NodeStyle.Statement)); if (next_i < contents.Count) { context.Sink.Error(contents[next_i], "The default branch must be the final branch in a 'match' statement."); } } } return(LNode.Call(CodeSymbols.DoWhile, LNode.List(outputs.ToVList().AsLNode(S.Braces), LNode.Literal(false)))); } } return(null); }
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))); } } }
public static LNode @case(LNode node, IMacroContext context) { LNode expr, braces = null; if (node.ArgCount == 2 && (braces = node.Args.Last).Calls(S.Braces) || node.ArgCount == 1 && (node[0].Calls(S.Colon, 2) || node[0].Calls("'or", 2))) { expr = node[0]; var results = LNode.List(); while (expr.Calls("'or", 2)) { results.Add(LNode.Call(S.Case, LNode.List(expr[0]), expr[0])); expr = expr[1]; } if (braces != null) { results.Add(LNode.Call(S.Case, LNode.List(expr), expr)); return(F.Call(S.Splice, results.Add(braces))); } else if (expr.Calls(S.Colon, 2)) { results.Add(LNode.Call(S.Case, LNode.List(expr[0]), expr[0])); return(F.Call(S.Splice, results.Add(expr[1]))); } else { return(Les2.Reject(context, node, "Unrecognized syntax in case statement")); } } return(null); }
protected override void Stmt(string text, LNode expected, Action <EcsNodePrinter> configure = null, Mode mode = Mode.Both) { bool exprMode = (mode & Mode.Expression) != 0; if ((mode & Mode.ParserTest) == 0) { return; } // This is the easy way: //LNode result = EcsLanguageService.Value.ParseSingle(text, MessageSink.Console, exprMode ? ParsingService.Exprs : ParsingService.Stmts); // But to make debugging easier, I'll do it the long way: ILexer <Token> lexer = EcsLanguageService.Value.Tokenize(new UString(text), "", MessageSink.Console); var preprocessed = new EcsPreprocessor(lexer); var treeified = new TokensToTree(preprocessed, false); var sink = (mode & Mode.ExpectAndDropParserError) != 0 ? new MessageHolder() : (IMessageSink)MessageSink.Console; var parser = new EcsParser(treeified.Buffered(), lexer.SourceFile, sink); LNode result = exprMode ? parser.ExprStart(false) : LNode.List(parser.ParseStmtsGreedy()).AsLNode(S.Splice); AreEqual(TokenType.EOF, parser.LT0.Type(), string.Format("Parser stopped before EOF at [{0}] in {1}", parser.LT0.StartIndex, text)); AreEqual(expected, result); if (sink is MessageHolder) { GreaterOrEqual(((MessageHolder)sink).List.Count, 1, "Expected an error but got none for " + text); } }
// Step 3 void Process(Rule rule) { // Create $result variable if it was used bool usingResult = _data.OtherReferences.ContainsKey(_resultId) || _data.ProperLabels.TryGetValue(_result, false); if (usingResult && rule.ReturnType != null) { _data.ProperLabels[_result] = true; var type = rule.ReturnType; _newVarInitializers[_result] = Pair.Create(type, _codeGen.MakeInitializedVarDecl(type, false, _result)); } Visit(rule.Pred); if (_newVarInitializers.Count != 0) { var decls = _newVarInitializers.OrderBy(p => p.Key.Name).Select(p => p.Value.B); var seq = new Seq(new ActionPred(rule.Basis, LNode.List(decls)), rule.Pred); if (usingResult) { seq = new Seq(seq, new ActionPred(rule.Basis, LNode.List(F.Call(S.Return, _resultId)))); } rule.Pred = seq; } }
public static LNode RangeIncl(LNode node, IMacroContext context) { LNode lo = null; { LNode hi; if (node.Args.Count == 2 && (lo = node.Args[0]) != null && (hi = node.Args[1]) != null || node.Args.Count == 1 && (hi = node.Args[0]) != null) { if (lo == null || lo.IsIdNamed(__)) { if (hi.IsIdNamed(__)) { return(Range_Everything); } else { return(LNode.Call(Range_UntilInclusive, LNode.List(hi))); } } else if (hi.IsIdNamed(__)) { return(LNode.Call(Range_StartingAt, LNode.List(lo))); } else { return(LNode.Call(Range_Inclusive, LNode.List(lo, hi))); } } } return(null); }
public static LNode saveAndRestore(LNode node, IMacroContext context) { var tmp_10 = context.GetArgsAndBody(true); var args = tmp_10.Item1; var body = tmp_10.Item2; if (args.Count == 1) { LNode newValue = null; { var tmp_11 = args[0]; LNode property; if (tmp_11.Calls(CodeSymbols.Assign, 2) && (property = tmp_11.Args[0]) != null && (newValue = tmp_11.Args[1]) != null || (property = tmp_11) != null) { string mainProp = KeyNameComponentOf(property).Name; string varPrefix = "old" + mainProp + "_"; LNode varName, varDecl = TempVarDecl(context, property, out varName, varPrefix); LNode tryFinally = LNode.Call(CodeSymbols.Try, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(body)).SetStyle(NodeStyle.StatementBlock), LNode.Call(CodeSymbols.Finally, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Assign, LNode.List(property, varName)).SetStyle(NodeStyle.Operator))).SetStyle(NodeStyle.StatementBlock))))); if (newValue != null) { return(LNode.Call(CodeSymbols.Splice, LNode.List(varDecl, LNode.Call(CodeSymbols.Assign, LNode.List(property, newValue)).SetStyle(NodeStyle.Operator), tryFinally)).IncludingTriviaFrom(node)); } else { return(LNode.Call(CodeSymbols.Splice, LNode.List(varDecl, tryFinally)).IncludingTriviaFrom(node)); } } } } return(null); }
static LNode MergeIdentifiers(LNode left, LNode right) { if (left == null) { return(right); } if (right.IsIdNamed(S.Missing)) { return(left); } { LNode right1, right2; if (right.Calls(CodeSymbols.Dot, 1) && (right2 = right.Args[0]) != null) { return(LNode.Call(CodeSymbols.Dot, LNode.List(left, right2))); } else if (right.Calls(CodeSymbols.Dot, 2) && (right1 = right.Args[0]) != null && (right2 = right.Args[1]) != null) { return(LNode.Call(CodeSymbols.Dot, LNode.List(MergeIdentifiers(left, right1), right2))); } else { throw new LogException(Severity.Note, right, "Multi-using statement seems malformed. Correct example: `using System(.Text, .Linq));`"); } } }
void ProcessRequiresAttribute(VList <LNode> 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))); } } }
public LNode GetItemDecl(int itemNum) { LNode ItemN = F.Id("Item" + itemNum); // ItemN properties are used by the code generated for pattern matching return(LNode.Call(LNode.List(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id((Symbol)"System"), LNode.Id((Symbol)"ComponentModel"))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"EditorBrowsable"))).SetStyle(NodeStyle.Operator), LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id((Symbol)"System"), LNode.Id((Symbol)"ComponentModel"))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"EditorBrowsableState"))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"Never"))).SetStyle(NodeStyle.Operator))), LNode.Id(CodeSymbols.Public)), CodeSymbols.Property, LNode.List(Type, ItemN, LNode.Missing, LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.get, LNode.List(LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(NameId)))).SetStyle(NodeStyle.Statement))).SetStyle(NodeStyle.Special))).SetStyle(NodeStyle.Statement)))); }
void ProcessRequiresAttribute(VList <LNode> conditions, Symbol mode, LNode variableName) { foreach (var condition_ in conditions) { LNode condition = condition_; LNode conditionStr; if (ReplaceContractUnderscore(ref condition, variableName)) { if (variableName == null) { Context.Write(Severity.Error, condition, "`{0}`: underscore has no meaning in this location.", mode); } } if (mode == sy_assert) { PrependStmts.Add(LNode.Call((Symbol)"assert", LNode.List(condition))); } else if (_haveCCRewriter) { PrependStmts.Add(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id((Symbol)"Contract"), LNode.Id((Symbol)"Requires"))), LNode.List(condition))); } else { conditionStr = ConditionToStringLit(condition, "Precondition failed: {1}"); PrependStmts.Add(LNode.Call(GetAssertMethodForRequires(), LNode.List(condition, conditionStr))); } } }
LNode GetOutputAsLNode() { WList <LNode> finalOutput = _handler.ToWList(); for (int end = _output.Count - 1; end >= 0; end--) { var tmp_10 = _output[end]; Mode mode = tmp_10.Item1; LNode code = tmp_10.Item2; if (mode == Mode.Condition) { // Merge adjacent conditions into the same if-statement int start = end; for (; start > 0 && _output[start - 1].A == mode; start--) { } LNode cond = _output[start].B; for (int i = start + 1; i <= end; i++) { cond = LNode.Call(CodeSymbols.And, LNode.List(cond, _output[i].B)).SetStyle(NodeStyle.Operator); } end = start; finalOutput = new WList <LNode> { LNode.Call(CodeSymbols.If, LNode.List(cond, finalOutput.ToVList().AsLNode(S.Braces))) }; } else { finalOutput.Insert(0, code); } } return(finalOutput.ToVList().AsLNode(S.Braces)); }
public static LNode ContractsOnLambda(LNode fn, IMacroContext context) { LNode oldFn = fn; if (fn.ArgCount == 2) { var rw = new CodeContractRewriter(LNode.Missing, Id_lambda_function, context); fn = ProcessArgContractAttributes(fn, 0, rw, isLambda: true); if (fn.HasAttrs) { fn = fn.WithAttrs(rw.Process(fn.Attrs, null)); } if (rw.PrependStmts.IsEmpty) { return(null); } else { var body = fn.Args[1]; 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, rw.PrependStmts)); fn = fn.WithArgChanged(1, body); return(fn); } } return(null); }
[LexicalMacro("lo..hi; ..hi; lo.._", "Given `lo..hi, produces `Range.Excl(lo, hi)", "..")] public static LNode RangeExcl(LNode node, IMacroContext context) { LNode lo = null; { LNode hi; if (node.Args.Count == 2 && (lo = node.Args[0]) != null && (hi = node.Args[1]) != null || node.Args.Count == 1 && (hi = node.Args[0]) != null) { if (lo == null || lo.IsIdNamed(__)) { if (hi.IsIdNamed(__)) { return(Range_Everything); } else { return(LNode.Call(Range_UntilExclusive, LNode.List(hi))); } } else if (hi.IsIdNamed(__)) { return(LNode.Call(Range_StartingAt, LNode.List(lo))); } else { return(LNode.Call(Range_ExcludeHi, LNode.List(lo, hi))); } } } return(null); }
public static LNode ContractsOnMethod(LNode fn, IMacroContext context) { LNode oldFn = fn; if (fn.ArgCount >= 4) { var rw = new CodeContractRewriter(fn.Args[0], fn.Args[1], context); fn = ProcessArgContractAttributes(fn, 2, rw); if (fn.Args[0].HasAttrs) { fn = fn.WithArgChanged(0, fn.Args[0].WithAttrs(rw.Process(fn.Args[0].Attrs, null))); } if (fn.HasAttrs) { fn = fn.WithAttrs(rw.Process(fn.Attrs, null)); } if (rw.PrependStmts.IsEmpty) { return(null); } else { var body = fn.Args[3]; 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, rw.PrependStmts)); fn = fn.WithArgChanged(3, body); return(fn); } } return(null); }
LNodeList UnwrapRunSequence(ref LNode runSeq) { var result = LNode.List(); if (runSeq.Calls(sy__numrunSequence)) { if (runSeq.ArgCount == 1 && runSeq[0].Calls(S.Braces)) { result = runSeq[0].Args; } else { result = runSeq.Args; } if (result.Count == 0) { Context.Sink.Error(runSeq, "#runSequence() has no arguments, which is not supported."); } else if (result.Count == 1) { runSeq = result[0].PlusAttrs(runSeq.Attrs); return(LNode.List()); } } return(result); }
public virtual LNode VisitInput(LNode stmt, IMessageSink sink) { LNode aliasSet; if ((stmt.Calls(_alias, 1) || stmt.CallsMin(S.Alias, 1)) && (aliasSet = stmt.Args[0]).Calls(S.Assign, 2)) { IEnumerable <KeyValuePair <LNode, LNode> > q; LNode alias = aliasSet.Args[0], replacement = aliasSet.Args[1], old; if (_definedAliases.TryGetValue(alias, out old)) { if (stmt.AttrNamed(S.Partial) == null || !old.Equals(replacement)) { sink.Warning(alias, "Redefinition of alias '{0}'", alias); } } else if ((q = _definedAliases.Where(pair => replacement.Equals(pair.Value))).Any()) { sink.Warning(replacement, "Aliases '{0}' and '{1}' have the same replacement value", q.First().Key, alias); } _definedAliases[alias] = replacement; return(LNode.Call(S.Splice, LNode.List())); // erase alias from output } return(null); }
private static LNode ValidateOnStmt(LNode node, IMacroContext context, out VList <LNode> 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.Write(Severity.Warning, node, "{0} should not be the final statement of a block.", node.Name); } restOfStmts = new VList <LNode>(context.RemainingNodes); context.DropRemainingNodes = true; return(on_handler); }
private void MatchAttributes(LNode pattern, LNode candidate) { LNode condition; bool isParams, refExistingVar; Symbol listVar; var pAttrs = pattern.PAttrs(); if (pAttrs.Count == 1 && (listVar = DecodeSubstitutionExpr(pAttrs[0], out condition, out isParams, out refExistingVar)) != null && isParams) { if (listVar != __ || condition != null) { if (!refExistingVar) { AddVar(listVar, true, errAt: pattern); } Tests.Add(LNode.Call(CodeSymbols.OrBits, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Call(LNode.List(LNode.InParensTrivia), CodeSymbols.Assign, LNode.List(F.Id(listVar), LNode.Call(CodeSymbols.Dot, LNode.List(candidate, LNode.Id((Symbol)"Attrs"))).SetStyle(NodeStyle.Operator))).SetStyle(NodeStyle.Operator), LNode.Id((Symbol)"IsEmpty"))).SetStyle(NodeStyle.Operator), LNode.Literal(true))).SetStyle(NodeStyle.Operator)); if (condition != null) { Tests.Add(condition); } } } else if (pAttrs.Count != 0) { Context.Sink.Error(pAttrs[0], "Currently, Attribute matching is very limited; you can only use `[$(...varName)]`"); } }
public static LNode ArrayLiteral(LNode node, IMacroContext context) { var value = node.Value; if (value is Array array) { Type elementType = value.GetType().GetElementType(); string elementTypeName = elementType.NameWithGenericArgs(); LNode elementTypeN = LNode.Call(S.CsRawText, LNode.List(LNode.Literal(elementTypeName))); Func <object, LNode, LNode> newLiteral = (el, pnode) => LNode.Literal(el, pnode); // Reduce output text size by preventing the printer from using casts // e.g. print `23` instead of `(byte) 23` or `(short) 23`. Also, unbox // ints to save memory (ideally we'd do this for all Value Types) if (elementType == typeof(byte)) { newLiteral = (el, pnode) => LNode.Literal((int)(byte)el, pnode); } if (elementType == typeof(sbyte)) { newLiteral = (el, pnode) => LNode.Literal((int)(sbyte)el, pnode); } if (elementType == typeof(short)) { newLiteral = (el, pnode) => LNode.Literal((int)(short)el, pnode); } if (elementType == typeof(ushort)) { newLiteral = (el, pnode) => LNode.Literal((int)(ushort)el, pnode); } if (elementType == typeof(int)) { newLiteral = (el, pnode) => LNode.Literal((int)(int)el, pnode); } if (array.Rank == 1) { var initializers = new List <LNode>(); int count = 0; foreach (object element in array) { LNode elemNode = newLiteral(element, node); if ((count++ & 7) == 0 && array.Length > 8) { elemNode = elemNode.PlusAttr(LNode.Id(S.TriviaNewline)); } initializers.Add(elemNode); } return(LNode.Call(CodeSymbols.New, LNode.List().Add(LNode.Call(LNode.Call(CodeSymbols.Of, LNode.List(LNode.Id(CodeSymbols.Array), elementTypeN)))).AddRange(initializers))); } else { return(null); // TODO //Stmt("int[,] Foo = new[,] { {\n 0 }, {\n 1,\n 2, }, };", F.Call(S.Var, F.Of(S.TwoDimensionalArray, S.Int32), // F.Call(S.Assign, Foo, F.Call(S.New, F.Call(S.TwoDimensionalArray), F.Braces(zero), F.Braces(one, two))))); } } return(null); }
public IListSource <LNode> ParseExprs(bool allowTrailingComma = false, bool allowUnassignedVarDecl = false) { var list = LNode.List(); try { ExprList(ref list, allowTrailingComma, allowUnassignedVarDecl); } catch (Exception ex) { UnhandledException(ex); } return(list); }
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); } } }
public static LNode In(LNode node, IMacroContext context) { { LNode range, x; if (node.Calls(CodeSymbols.In, 2) && (x = node.Args[0]) != null && (range = node.Args[1]) != null) { LNode parens; range = range.WithoutAttrNamed(S.TriviaInParens, out parens); if (parens == null) { { LNode hi, lo; if (range.Calls(CodeSymbols.DotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null) { if (lo.IsIdNamed(__)) { return(LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator)); } else if (hi.IsIdNamed(__)) { return(LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator)); } else { return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol)"IsInRangeExcludeHi"))), LNode.List(lo, hi))); } } else if (range.Calls(CodeSymbols.DotDot, 1) && (hi = range.Args[0]) != null) { return(LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator)); } else if (range.Calls(CodeSymbols.DotDotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null) { if (lo.IsIdNamed(__)) { return(LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator)); } else if (hi.IsIdNamed(__)) { return(LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator)); } else { return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol)"IsInRange"))), LNode.List(lo, hi))); } } else if (range.Calls(CodeSymbols.DotDotDot, 1) && (hi = range.Args[0]) != null) { return(LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator)); } } } return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(range, LNode.Id((Symbol)"Contains"))), LNode.List(x))); } } return(null); }
[LexicalMacro("x in lo..hi; x in lo...hi; x in ..hi; x in lo..._; x in range", "Converts an 'in' expression to a normal C# expression using the following rules " + "(keeping in mind that the EC# parser treats `..<` as an alias for `..`):\n" + "1. `x in _..hi` and `x in ..hi` become `x.IsInRangeExcl(hi)`\n" + "2. `x in _...hi` and `x in ...hi` become `x.IsInRangeIncl(hi)`\n" + "3. `x in lo.._` and `x in lo..._` become simply `x >= lo`\n" + "4. `x in lo..hi` becomes `x.IsInRangeExcludeHi(lo, hi)`\n" + "5. `x in lo...hi` becomes `x.IsInRange(lo, hi)`\n" + "6. `x in range` becomes `range.Contains(x)`\n" + "The first applicable rule is used.", "#in")] public static LNode In(LNode node, IMacroContext context) { { LNode range, x; if (node.Calls(CodeSymbols.In, 2) && (x = node.Args[0]) != null && (range = node.Args[1]) != null) { LNode parens; range = range.WithoutAttrNamed(S.TriviaInParens, out parens); if (parens == null) { { LNode hi, lo; if (range.Calls(CodeSymbols.DotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null) { if (lo.IsIdNamed(__)) { return(LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator)); } else if (hi.IsIdNamed(__)) { return(LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator)); } else { return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol)"IsInRangeExcludeHi"))), LNode.List(lo, hi))); } } else if (range.Calls(CodeSymbols.DotDot, 1) && (hi = range.Args[0]) != null) { return(LNode.Call(CodeSymbols.LT, LNode.List(x, hi)).SetStyle(NodeStyle.Operator)); } else if (range.Calls(CodeSymbols.DotDotDot, 2) && (lo = range.Args[0]) != null && (hi = range.Args[1]) != null) { if (lo.IsIdNamed(__)) { return(LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator)); } else if (hi.IsIdNamed(__)) { return(LNode.Call(CodeSymbols.GE, LNode.List(x, lo)).SetStyle(NodeStyle.Operator)); } else { return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(x, LNode.Id((Symbol)"IsInRange"))), LNode.List(lo, hi))); } } else if (range.Calls(CodeSymbols.DotDotDot, 1) && (hi = range.Args[0]) != null) { return(LNode.Call(CodeSymbols.LE, LNode.List(x, hi)).SetStyle(NodeStyle.Operator)); } } } return(LNode.Call(LNode.Call(CodeSymbols.Dot, LNode.List(range, LNode.Id((Symbol)"Contains"))), LNode.List(x))); } } return(null); }
public IListSource <LNode> ParseStmtsGreedy() { var list = LNode.List(); try { StmtList(ref list); } catch (Exception ex) { UnhandledException(ex); } ExpectEOF(); return(list); }
private List <LogMessage> RunLeMPAndCaptureErrors(UString inputText) { MessageHolder messages = new MessageHolder(); MacroProcessor lemp = NewLemp(0xFFFF, EcsLanguageService.Value).With(mp => mp.Sink = messages); IListSource <LNode> inputCode = EcsLanguageService.Value.Parse(inputText, MessageSink.Default); lemp.ProcessSynchronously(LNode.List(inputCode)); return(messages.List.Where(m => m.Severity == Severity.Error).ToList()); }
/// <summary>A method called to create a virtual node to apply trivia to an empty source file.</summary> /// <remarks>Default implementation attaches all trivia to a "missing" node /// (zero-length identifier). If this method returns null then the result is discarded.</remarks> protected virtual LNode GetEmptyResultSet() { if (SortedTrivia.Count == 0) { return(null); } var dummy = LNode.Id(LNode.List(LNode.Id(CodeSymbols.TriviaDummyNode)), GSymbol.Empty, GetRange(SortedTrivia[0])); return(AttachTriviaTo(dummy, SortedTrivia, TriviaLocation.TrailingExtra, null, -1) ?? dummy); }