private double?ParseNumericOption(BMultiMap <string, string> options, string key, IMessageSink sink, double?min = null, double?max = null) { string value; if (!options.TryGetValue(key, out value)) { return(null); } double num; if (double.TryParse(value ?? "", out num)) { if ((min == null || num >= min.Value) && (max == null || num <= max.Value)) { return(num); } } if (sink != null) { if (min != null && max != null) { sink.Error("--" + key, "Expected numeric value between {0} and {1}", min.Value, max.Value); } else { sink.Error("--" + key, "Expected numeric value"); } } return(null); }
private void MaybeCreateVariableFor(Pred pred, Symbol varName, LNode primType) { if (pred.ResultSaver != null) { return; } if (primType == null) { primType = F.Object; _sink.Error(pred, Localize.Localized("The type of this expression is unknown (did you set LLLPG's 'terminalType' option?)")); } LNode type = primType, oldType; if (pred.VarIsList) { type = _codeGen.GetListType(primType); } if (!_newVarInitializers.ContainsKey(varName)) { _newVarInitializers[varName] = Pair.Create(type, _codeGen.MakeInitializedVarDecl(primType, pred.VarIsList, varName)); } else if (!(oldType = _newVarInitializers[varName].A).Equals(type)) { _sink.Error(pred, Localize.Localized( "Type mismatch: Variable '{0}' was generated earlier with type {1}, but this predicate expects {2}.", varName, oldType, type)); } pred.ResultSaver = Pred.GetStandardResultSaver(F.Id(varName), pred.VarIsList ? S.AddAssign : S.Assign); }
Pred NodeToPred(LNode expr, Context ctx = Context.Rule) { try { return(NodeToPredCore(expr, ctx)); } catch (Exception ex) { _sink.Error(expr, ex.ExceptionMessageAndType()); return(new TerminalPred(expr, _helper.EmptySet)); } }
public static LNode unroll(LNode var, VList<LNode> cases, LNode body, IMessageSink sink) { // Maps identifiers => replacements. The integer counts how many times replacement occurred. var replacements = InternalList<Triplet<Symbol, LNode, int>>.Empty; if (var.IsId && !var.HasPAttrs()) { replacements.Add(Pair.Create(var.Name, (LNode)LNode.Missing, 0)); } else { var vars = var.Args; if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs())) { replacements = new Triplet<Symbol, LNode, int>[vars.Count].AsInternalList(); for (int i = 0; i < vars.Count; i++) { replacements.InternalArray[i].A = vars[i].Name; // Check for duplicate names for (int j = 0; j < i; j++) if (replacements[i].A == replacements[j].A && replacements[i].A.Name != "_") sink.Error(vars[i], "Duplicate name in the left-hand tuple"); // non-fatal } } else return Reject(sink, var, "The left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers."); } UnrollCtx ctx = new UnrollCtx { Replacements = replacements }; WList<LNode> output = new WList<LNode>(); int iteration = 0; foreach (LNode replacement in cases) { iteration++; bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces); int count = tuple ? replacement.ArgCount : 1; if (replacements.Count != count) { sink.Error(replacement, "iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Count, count); if (count < replacements.Count) continue; // too few } for (int i = 0; i < replacements.Count; i++) replacements.InternalArray[i].B = tuple ? replacement.Args[i] : replacement; if (body.Calls(S.Braces)) { foreach (LNode stmt in body.Args) output.Add(ctx.Replace(stmt).Value); } else output.Add(ctx.Replace(body).Value); } foreach (var r in replacements) if (r.C == 0 && !r.A.Name.StartsWith("_")) sink.Write(Severity.Warning, var, "Replacement variable '{0}' was never used", r.A); return body.With(S.Splice, output.ToVList()); }
private bool?ParseBoolOption(BMultiMap <string, string> options, string key, IMessageSink sink) { string value; if (!options.TryGetValue(key, out value)) { return(null); } if (value == null) { return(true); } if (value.Equals("true", StringComparison.InvariantCultureIgnoreCase) || value == "1") { return(true); } if (value.Equals("false", StringComparison.InvariantCultureIgnoreCase) || value == "0") { return(false); } if (sink != null) { sink.Error("--" + key, "Expected boolean `true` or `false`"); } return(null); }
/// <summary> /// Tries to send the message; throws if not logged on. /// </summary> /// <param name="m"></param> public bool Send(QuickFix.Message m) { if (Initiator.IsLoggedOn == false) { _messageSink.Error(() => "Can't send a message. We're not logged on."); return(false); } if (ActiveSessionID == null) { _messageSink.Error( () => "Can't send a message. ActiveSessionID is null (not logged on?)."); return(false); } return(QuickFix.Session.SendToTarget(m, ActiveSessionID)); }
static void ApplyLanguageOption(IMessageSink sink, string option, string value, ref IParsingService lang) { if (string.IsNullOrEmpty(value)) { sink.Error(option, "Missing value"); } else { if (!value.StartsWith(".")) { value = "." + value; } if ((lang = ParsingService.GetServiceForFileName(value)) == null) { sink.Error(option, "No language was found for extension «{0}»", value); } } }
static bool TryCatch(object context, IMessageSink sink, Action action) { try { action(); return(true); } catch (Exception ex) { sink.Error(context, "{0} ({1})", ex.Message, ex.GetType().Name); return(false); } }
private static void SetOption <T>(IMessageSink errorSink, LNode optionName, object value, Action <T> setter) { if (value is T) { setter((T)value); } else { errorSink.Error(optionName, "{0}: expected literal of type «{1}».", optionName.Name, typeof(T)); } }
private void InsertSingle(ref int atIndex, Pred b, BranchMode bMode, IMessageSink warnings) { if (bMode == BranchMode.ErrorExit || bMode == BranchMode.ErrorContinue) { if (ErrorBranch != null) { warnings.Error(b, "There is already an error branch."); } else { ErrorBranch = b; ExitOnError = bMode == BranchMode.ErrorExit; if (atIndex < Arms.Count) { Warning_ErrorBranchNotLast(ErrorBranch, warnings); } } } else { if (atIndex == Arms.Count && ErrorBranch != null) { Warning_ErrorBranchNotLast(ErrorBranch, warnings); } Arms.Insert(atIndex, b); if (bMode == BranchMode.Default) { if (DefaultArm != null) { int a = DefaultArm.Value; warnings.Error(b, "There is already a default branch"); } else { DefaultArm = atIndex; } } atIndex++; } }
private void OrderRejected(OrderRecord order) { _messageSink.Error(() => { var reason = order.RejectReason; if (string.IsNullOrWhiteSpace(reason)) { // TODO There is a lack of ability to send free-text error messages via FIX // Therefore if the reason is not filled in here we guess at the likely cause reason = "Unkown. Possibly order would have led to a crossed market"; } return("Unable to add order: " + reason); }); }
/// <summary>Opens a set of source files by file name, and creates an <see cref="InputOutput"/> object for each.</summary> /// <param name="sink">Any I/O errors that occur will be logged to this object.</param> /// <param name="fileNames">List of file names</param> /// <returns>a list of files that were opened, together with their settings. /// This method does not run the macro processor on these files.</returns> public static List <InputOutput> OpenSourceFiles(IMessageSink sink, IEnumerable <string> fileNames) { var openFiles = new List <InputOutput>(); foreach (var filename in fileNames) { try { var stream = File.OpenRead(filename); var io = new InputOutput(new StreamCharSource(stream), Path.GetFullPath(filename)); openFiles.Add(io); } catch (Exception ex) { sink.Error(filename, ex.GetType().Name + ": " + ex.Message); } } return(openFiles); }
private static void MaybeStartRoslynSession(LNode codeBlock, IMessageSink sink) { if (_roslynSessionLogFileName == null) { try { _roslynSessionLogFileName = Path.GetTempFileName(); FileInfo fileInfo = new FileInfo(_roslynSessionLogFileName); fileInfo.Attributes |= FileAttributes.Temporary; _roslynSessionLog = File.AppendText(_roslynSessionLogFileName); _roslynSessionLog.WriteLine("Roslyn code execution log - {0}".Localized(DateTime.Now.ToString())); } catch (IOException e) { sink.Error(codeBlock, "Error opening Roslyn session log {0}: {1}".Localized( _roslynSessionLogFileName, e.Message)); } } if (_roslynScriptState == null) { var scriptOptions = ScriptOptions.Default.WithReferences( typeof(IIsEmpty).Assembly, // Loyc.Interfaces.dll typeof(MessageHolder).Assembly, // Loyc.Essentials.dll typeof(VList <>).Assembly, // Loyc.Collections.dll typeof(LNode).Assembly, // Loyc.Syntax.dll typeof(EcsLanguageService).Assembly, // Loyc.Ecs.dll typeof(StandardMacros).Assembly // LeMP.StdMacros.dll ) .WithImports("Loyc", "Loyc.Syntax", "LeMP", "System") .WithLanguageVersion(LanguageVersion.CSharp8) .WithEmitDebugInformation(true) .WithCheckOverflow(false); _roslynScriptState = CSharpScript.RunAsync( $"dynamic {__result_of_precompute};\n" + // Using dynamic for this variable type gave me an error when calling .RegisterMacro on it: // Error CS0656 Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' $"global::LeMP.IMacroContext {__macro_context_sanitized};", scriptOptions).Result; } }
private static LNode ParseRuleBody(LNode ruleBody, IMessageSink sink) { TokenTree ruleTokens; // Expecting @{...} or {...} if ((ruleTokens = ruleBody.Value as TokenTree) == null && !ruleBody.Calls(S.Braces)) { sink.Error(ruleBody, "Expected token tree or braced block"); return(null); } if (ruleTokens != null) { return(StageOneParser.ParseTokenTree(ruleTokens, sink)); } else { if (ruleBody.Args.Any(stmt => stmt.Value is TokenTree)) { ruleBody = ruleBody.With(S.Tuple, ruleBody.Args.SmartSelect(stmt => ParseStmtInRule(stmt, sink))); } } return(ruleBody); }
public static LNode BackingField(LNode prop, IMessageSink sink) { LNode propType, propName, propArgs, body; if (prop.ArgCount != 4 || !(body = prop.Args[3]).Calls(S.Braces)) { return(null); } // Look for an attribute of the form [field], [field name] or [field Type name] LNode fieldAttr = null, fieldName; bool autoType = false; int i; for (i = 0; i < prop.Attrs.Count; i++) { LNode attr = prop.Attrs[i]; if (attr.IsIdNamed(_field)) { fieldAttr = attr; break; } else if (attr.Calls(S.Var, 2)) { LNode fieldVarAttr = null; attr = attr.WithoutAttrNamed(__field, out fieldVarAttr); if (fieldVarAttr != null && fieldVarAttr.IsId || (autoType = attr.Args[0].IsIdNamed(_field))) { fieldAttr = attr; break; } } } if (fieldAttr == null) { return(null); } // Extract the type and name of the backing field, if specified LNode field = fieldAttr; propType = prop.Args[0]; propName = prop.Args[1]; propArgs = prop.Args[2]; if (field.IsId) { fieldName = F.Id(ChooseFieldName(Loyc.Ecs.EcsNodePrinter.KeyNameComponentOf(propName))); field = F.Call(S.Var, propType, fieldName).WithAttrs(fieldAttr.Attrs); } else { fieldName = field.Args[1]; if (fieldName.Calls(S.Assign, 2)) { fieldName = fieldName.Args[0]; } } if (autoType) { field = field.WithArgChanged(0, propType); } // Construct the new backing field, fill in the property getter and/or setter if (body.ArgCount == 0) { body = body.WithArgs(LNode.Id(S.get)); } LNode newBody = body.WithArgs(body.Args.SmartSelect(stmt => { var fieldAccessExpr = fieldName; if (propArgs.ArgCount > 0) { // Special case: the property has arguments, // e.g. [field List<T> L] T this[int x] { get; set; } // ==> List<T> L; T this[int x] { get { return L[x]; } set { L[x] = value; } } var argList = GetArgNamesFromFormalArgList(propArgs, formalArg => sink.Error(formalArg, "'field' macro expected a variable declaration here")); fieldAccessExpr = F.Call(S.IndexBracks, argList.Insert(0, fieldName)); } var attrs = stmt.Attrs; if (stmt.IsIdNamed(S.get)) { stmt = F.Call(stmt.WithoutAttrs(), F.Braces(F.Call(S.Return, fieldAccessExpr))).WithAttrs(attrs); stmt.BaseStyle = NodeStyle.Special; } if (stmt.IsIdNamed(S.set)) { stmt = F.Call(stmt.WithoutAttrs(), F.Braces(F.Call(S.Assign, fieldAccessExpr, F.Id(S.value)))).WithAttrs(attrs); stmt.BaseStyle = NodeStyle.Special; } return(stmt); })); if (newBody == body) { sink.Warning(fieldAttr, "The body of the property does not contain a 'get;' or 'set;' statement without a body, so no code was generated to get or set the backing field."); } prop = prop.WithAttrs(prop.Attrs.RemoveAt(i)).WithArgChanged(3, newBody); prop.Style &= ~NodeStyle.OneLiner; // avoid collapsing output to one line return(F.Call(S.Splice, new VList <LNode>(field, prop))); }
static void ApplyLanguageOption(IMessageSink sink, string option, string value, ref IParsingService lang) { if (string.IsNullOrEmpty(value)) sink.Error(option, "Missing value"); else { if (!value.StartsWith(".")) value = "." + value; if ((lang = ParsingService.GetServiceForFileName(value)) == null) sink.Error(option, "No language was found for extension «{0}»", value); } }
static bool TryCatch(object context, IMessageSink sink, Action action) { try { action(); return true; } catch (Exception ex) { sink.Error(context, "{0} ({1})", ex.Message, ex.GetType().Name); return false; } }
/// <summary>Opens a set of source files by file name, and creates a text file for each.</summary> /// <param name="sink"></param> /// <param name="fileNames"></param> /// <returns></returns> public static List<InputOutput> OpenSourceFiles(IMessageSink sink, IEnumerable<string> fileNames) { var openFiles = new List<InputOutput>(); foreach (var filename in fileNames) { try { var stream = File.OpenRead(filename); var text = File.ReadAllText(filename, Encoding.UTF8); var io = new InputOutput(new StreamCharSource(stream), filename); openFiles.Add(io); } catch (Exception ex) { sink.Error(filename, ex.GetType().Name + ": " + ex.Message); } } return openFiles; }
/// <summary>Processes all standard command-line arguments from /// <see cref="KnownOptions"/>, except --help.</summary> /// <param name="options">A set of options, presumably derived from command- /// line options using <see cref="UG.ProcessCommandLineArguments"/></param> /// <param name="warnAboutUnknownOptions">Whether to warn (to <see cref="Sink"/>) /// about options not listed in <see cref="KnownOptions"/>.</param> /// <param name="inputFiles">Files to open with <see cref="OpenSourceFiles"/></param> /// <returns>true, unless inputFiles != null and all input files failed to open.</returns> /// <remarks> /// This method calls AddStdMacros() unless options includes "nostdmacros". /// </remarks> public bool ProcessArguments(BMultiMap <string, string> options, bool warnAboutUnknownOptions, IList <string> inputFiles = null) { Compiler c = this; string value; bool? flag; double? num; var filter = c.Sink as SeverityMessageFilter ?? new SeverityMessageFilter(c.Sink, Severity.NoteDetail); if (warnAboutUnknownOptions) { WarnAboutUnknownOptions(options, Sink, KnownOptions); } if (options.TryGetValue("verbose", out value)) { if (value != "false") { try { // Enum.TryParse() does not exist before .NET 4 so use Enum.Parse filter.MinSeverity = (Severity)Enum.Parse(typeof(Severity), value); } catch (Exception) { // Docs say OverflowException, but that just sounds wrong filter.MinSeverity = Severity.Verbose; } } } IMessageSink sink = c.Sink = filter; if ((num = ParseNumericOption(options, "max-expand", sink, 0, 99999)) != null) { c.MaxExpansions = (int)num.Value; } foreach (var macroDll in options["macros"]) { Assembly assembly; TryCatch("While opening " + macroDll, sink, () => { // When running standalone, Assembly.Load works properly, // but not when running in Visual Studio. I'm speculating it's // because Visual Studio loads the Custom Tool in the "LoadFrom" // context and Assembly.Load ignores assemblies loaded in the // LoadFrom context (maybe not VS's fault as it loads us via COM) // See https://blogs.msdn.microsoft.com/suzcook/2003/05/29/choosing-a-binding-context/ // Workaround for idiotic MS design: reprogram Load to find // assemblies that are already loaded. AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => { return(AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(a => a.FullName == e.Name)); }; string path = Path.Combine(Environment.CurrentDirectory, macroDll); byte[] bytes = File.ReadAllBytes(path); assembly = Assembly.Load(bytes); c.AddMacros(assembly); }); } foreach (string macroDll in options["macros-longname"]) { Assembly assembly; TryCatch("While opening " + macroDll, sink, () => { assembly = Assembly.Load(macroDll); c.AddMacros(assembly); }); } if ((flag = ParseBoolOption(options, "noparallel", sink)) != null) { c.Parallel = flag.Value; } if (options.TryGetValue("outext", out c.OutExt)) { if (c.OutExt != null && !c.OutExt.StartsWith(".")) { c.OutExt = "." + c.OutExt; } } if (options.TryGetValue("inlang", out value)) { ApplyLanguageOption(sink, "--inlang", value, ref c.InLang); } if (options.TryGetValue("outlang", out value)) { IParsingService lang = null; ApplyLanguageOption(sink, "--outlang", value, ref lang); c.OutLang = (lang as ILNodePrinter) ?? c.OutLang; } if ((flag = ParseBoolOption(options, "forcelang", sink)) != null) { c.ForceInLang = flag.Value; } if (!options.ContainsKey("outlang") && c.OutExt != null && ParsingService.GetServiceForFileName(c.OutExt) == null) { sink.Error("--outext", "No language was found for extension «{0}»", c.OutExt); } if ((num = ParseNumericOption(options, "timeout", sink)) != null) { c.AbortTimeout = TimeSpan.FromSeconds(num.Value); } foreach (string exprStr in options["set"]) { SetPropertyHelper(exprStr, quote: false); } foreach (string exprStr in options["snippet"]) { SetPropertyHelper(exprStr, quote: true); } if (!options.TryGetValue("nostdmacros", out value) && !options.TryGetValue("no-std-macros", out value)) { AddStdMacros(); } if (options.TryGetValue("preserve-comments", out value)) { PreserveComments = value == null || !value.ToString().ToLowerInvariant().IsOneOf("false", "0"); } // Printing options if ((num = ParseNumericOption(options, "o-indent-spaces", sink, 0, 20)) != null) { OutOptions.IndentString = num.Value <= 0 ? "\t" : new string(' ', (int)num.Value); } if ((flag = ParseBoolOption(options, "o-allow-change-parens", sink)) != null) { OutOptions.AllowChangeParentheses = flag.Value; } if ((flag = ParseBoolOption(options, "o-omit-comments", sink)) != null) { OutOptions.OmitComments = flag.Value; } if ((flag = ParseBoolOption(options, "o-omit-unknown-trivia", sink)) != null) { OutOptions.OmitUnknownTrivia = flag.Value; } if ((flag = ParseBoolOption(options, "o-explicit-trivia", sink)) != null) { OutOptions.PrintTriviaExplicitly = flag.Value; } if ((flag = ParseBoolOption(options, "o-compatibility-mode", sink)) != null) { OutOptions.CompatibilityMode = flag.Value; } if ((flag = ParseBoolOption(options, "o-compact-mode", sink)) != null) { OutOptions.CompactMode = flag.Value; } if (inputFiles != null) { this.Files = new List <InputOutput>(OpenSourceFiles(Sink, inputFiles)); if (inputFiles.Count != 0 && Files.Count == 0) { return(false); } } return(true); }
public static LNode BackingField(LNode prop, IMessageSink sink) { LNode propType, propName, propArgs, body; if (prop.ArgCount != 4 || !(body = prop.Args[3]).Calls(S.Braces)) return null; // Look for an attribute of the form [field], [field name] or [field Type name] LNode fieldAttr = null, fieldName; bool autoType = false; int i; for (i = 0; i < prop.Attrs.Count; i++) { LNode attr = prop.Attrs[i]; if (attr.IsIdNamed(_field)) { fieldAttr = attr; break; } else if (attr.Calls(S.Var, 2)) { LNode fieldVarAttr = null; attr = attr.WithoutAttrNamed(__field, out fieldVarAttr); if (fieldVarAttr != null && fieldVarAttr.IsId || (autoType = attr.Args[0].IsIdNamed(_field))) { fieldAttr = attr; break; } } } if (fieldAttr == null) return null; // Extract the type and name of the backing field, if specified LNode field = fieldAttr; propType = prop.Args[0]; propName = prop.Args[1]; propArgs = prop.Args[2]; if (field.IsId) { fieldName = F.Id(ChooseFieldName(Loyc.Ecs.EcsNodePrinter.KeyNameComponentOf(propName))); field = F.Call(S.Var, propType, fieldName).WithAttrs(fieldAttr.Attrs); } else { fieldName = field.Args[1]; if (fieldName.Calls(S.Assign, 2)) fieldName = fieldName.Args[0]; } if (autoType) field = field.WithArgChanged(0, propType); // Construct the new backing field, fill in the property getter and/or setter if (body.ArgCount == 0) body = body.WithArgs(LNode.Id(S.get)); LNode newBody = body.WithArgs(body.Args.SmartSelect(stmt => { var fieldAccessExpr = fieldName; if (propArgs.ArgCount > 0) { // Special case: the property has arguments, // e.g. [field List<T> L] T this[int x] { get; set; } // ==> List<T> L; T this[int x] { get { return L[x]; } set { L[x] = value; } } var argList = GetArgNamesFromFormalArgList(propArgs, formalArg => sink.Error(formalArg, "'field' macro expected a variable declaration here")); fieldAccessExpr = F.Call(S.IndexBracks, argList.Insert(0, fieldName)); } var attrs = stmt.Attrs; if (stmt.IsIdNamed(S.get)) { stmt = F.Call(stmt.WithoutAttrs(), F.Braces(F.Call(S.Return, fieldAccessExpr))).WithAttrs(attrs); stmt.BaseStyle = NodeStyle.Special; } if (stmt.IsIdNamed(S.set)) { stmt = F.Call(stmt.WithoutAttrs(), F.Braces(F.Call(S.Assign, fieldAccessExpr, F.Id(S.value)))).WithAttrs(attrs); stmt.BaseStyle = NodeStyle.Special; } return stmt; })); if (newBody == body) sink.Warning(fieldAttr, "The body of the property does not contain a 'get;' or 'set;' statement without a body, so no code was generated to get or set the backing field."); prop = prop.WithAttrs(prop.Attrs.RemoveAt(i)).WithArgChanged(3, newBody); prop.Style &= ~NodeStyle.OneLiner; // avoid collapsing output to one line return F.Call(S.Splice, new VList<LNode>(field, prop)); }
public static LNode @try(LNode node, IMessageSink sink) { if (!node.IsCall) return null; // try(code, catch, Exception::e, handler, catch, ..., finally, handler) // ...becomes... // #try(#{ stmt1; stmt2; ... }, #catch(#var(Exception, e), handler), #finally(handler)) LNode finallyCode = null; WList<LNode> clauses = new WList<LNode>(); var parts = node.Args; for (int i = parts.Count-2; i >= 1; i -= 2) { var p = parts[i]; if (p.IsIdNamed(_finally)) { if (clauses.Count != 0 || finallyCode != null) sink.Error(p, "The «finally» clause must come last, there can only be one of them."); finallyCode = parts[i+1]; } else if (p.Name == _catch) { if (p.ArgCount > 0) { if (p.ArgCount > 1) sink.Error(p, "Expected catch() to take one argument."); // This is a normal catch clause clauses.Insert(0, F.Call(S.Catch, p.Args[0], F.Missing, parts[i + 1])); } else { // This is a catch-all clause (the type argument is missing) if (clauses.Count != 0) sink.Error(p, "The catch-all clause must be the last «catch» clause."); clauses.Add(F.Call(S.Catch, F.Missing, F.Missing, parts[i + 1])); } } else if (i > 1 && parts[i-1].IsIdNamed(_catch)) { // This is a normal catch clause clauses.Insert(0, F.Call(S.Catch, AutoRemoveParens(p), F.Missing, parts[i+1])); i--; } else { return Reject(sink, p, "Expected «catch» or «finally» clause here. Clause is missing or malformed."); } if (i == 2) return Reject(sink, parts[1], "Expected «catch» or «finally» clause here. Clause is missing or malformed."); } if (clauses.Count == 0 && finallyCode == null) { Debug.Assert(node.ArgCount <= 1); return Reject(sink, node, "Missing «catch, Type, Code» or «finally, Code» clause"); } if (finallyCode != null) clauses.Add(F.Call(S.Finally, finallyCode)); clauses.Insert(0, node.Args[0]); return node.With(S.Try, clauses.ToVList()); }
private bool? ParseBoolOption(BMultiMap<string, string> options, string key, IMessageSink sink) { string value; if (!options.TryGetValue(key, out value)) return null; if (value == null) return true; if (value.Equals("true", StringComparison.InvariantCultureIgnoreCase) || value == "1") return true; if (value.Equals("false", StringComparison.InvariantCultureIgnoreCase) || value == "0") return false; if (sink != null) sink.Error("--" + key, "Expected boolean `true` or `false`"); return null; }
/// <summary>Processes all standard command-line arguments from /// <see cref="KnownOptions"/>, except --help.</summary> /// <param name="options">A set of options, presumably derived from command- /// line options using <see cref="UG.ProcessCommandLineArguments"/></param> /// <param name="warnAboutUnknownOptions">Whether to warn (to <see cref="Sink"/>) /// about options not listed in <see cref="KnownOptions"/>.</param> /// <param name="inputFiles">Files to open with <see cref="OpenSourceFiles"/></param> /// <returns>true, unless inputFiles != null and all input files failed to open.</returns> /// <remarks> /// This method calls AddStdMacros() unless options includes "nostdmacros". /// </remarks> public bool ProcessArguments(BMultiMap <string, string> options, bool warnAboutUnknownOptions, IList <string> inputFiles = null) { Compiler c = this; string value; bool? flag; double? num; var filter = c.Sink as SeverityMessageFilter ?? new SeverityMessageFilter(c.Sink, Severity.NoteDetail); if (warnAboutUnknownOptions) { WarnAboutUnknownOptions(options, Sink, KnownOptions); } if (options.TryGetValue("verbose", out value)) { if (value != "false") { try { // Enum.TryParse() does not exist before .NET 4 so use Enum.Parse filter.MinSeverity = (Severity)Enum.Parse(typeof(Severity), value); } catch (Exception) { // Docs say OverflowException, but that just sounds wrong filter.MinSeverity = Severity.Verbose; } } } IMessageSink sink = c.Sink = filter; if ((num = ParseNumericOption(options, "max-expand", sink, 0, 99999)) != null) { c.MaxExpansions = (int)num.Value; } foreach (var macroDll in options["macros"]) { Assembly assembly; TryCatch("While opening " + macroDll, sink, () => { if (macroDll.Contains('\\') || macroDll.Contains('/')) { // Avoid "Absolute path information is required" exception string fullPath = Path.Combine(Environment.CurrentDirectory, macroDll); assembly = Assembly.LoadFile(fullPath); } else { assembly = Assembly.LoadFrom(macroDll); } c.AddMacros(assembly); }); } foreach (string macroDll in options["macros-longname"]) { Assembly assembly; TryCatch("While opening " + macroDll, sink, () => { assembly = Assembly.Load(macroDll); c.AddMacros(assembly); }); } if ((flag = ParseBoolOption(options, "noparallel", sink)) != null) { c.Parallel = flag.Value; } if (options.TryGetValue("outext", out c.OutExt)) { if (c.OutExt != null && !c.OutExt.StartsWith(".")) { c.OutExt = "." + c.OutExt; } } if (options.TryGetValue("inlang", out value)) { ApplyLanguageOption(sink, "--inlang", value, ref c.InLang); } if (options.TryGetValue("outlang", out value)) { IParsingService lang = null; ApplyLanguageOption(sink, "--outlang", value, ref lang); c.OutLang = (lang as ILNodePrinter) ?? c.OutLang; } if ((flag = ParseBoolOption(options, "forcelang", sink)) != null) { c.ForceInLang = flag.Value; } if (!options.ContainsKey("outlang") && c.OutExt != null && ParsingService.GetServiceForFileName(c.OutExt) == null) { sink.Error("--outext", "No language was found for extension «{0}»", c.OutExt); } if ((num = ParseNumericOption(options, "timeout", sink)) != null) { c.AbortTimeout = TimeSpan.FromSeconds(num.Value); } foreach (string exprStr in options["set"]) { SetPropertyHelper(exprStr, quote: false); } foreach (string exprStr in options["snippet"]) { SetPropertyHelper(exprStr, quote: true); } if (!options.TryGetValue("nostdmacros", out value) && !options.TryGetValue("no-std-macros", out value)) { AddStdMacros(); } if (options.TryGetValue("preserve-comments", out value)) { PreserveComments = value == null || !value.ToString().ToLowerInvariant().IsOneOf("false", "0"); } // Printing options if ((num = ParseNumericOption(options, "o-indent-spaces", sink, 0, 20)) != null) { OutOptions.IndentString = num.Value <= 0 ? "\t" : new string(' ', (int)num.Value); } if ((flag = ParseBoolOption(options, "o-allow-change-parens", sink)) != null) { OutOptions.AllowChangeParentheses = flag.Value; } if ((flag = ParseBoolOption(options, "o-omit-comments", sink)) != null) { OutOptions.OmitComments = flag.Value; } if ((flag = ParseBoolOption(options, "o-omit-unknown-trivia", sink)) != null) { OutOptions.OmitUnknownTrivia = flag.Value; } if ((flag = ParseBoolOption(options, "o-explicit-trivia", sink)) != null) { OutOptions.PrintTriviaExplicitly = flag.Value; } if ((flag = ParseBoolOption(options, "o-compatibility-mode", sink)) != null) { OutOptions.CompatibilityMode = flag.Value; } if ((flag = ParseBoolOption(options, "o-compact-mode", sink)) != null) { OutOptions.CompactMode = flag.Value; } if (inputFiles != null) { this.Files = new List <InputOutput>(OpenSourceFiles(Sink, inputFiles)); if (inputFiles.Count != 0 && Files.Count == 0) { return(false); } } return(true); }
public static LNode unroll(LNode var, VList <LNode> cases, LNode body, IMessageSink sink) { // Maps identifiers => replacements. The integer counts how many times replacement occurred. var replacements = InternalList <Triplet <Symbol, LNode, int> > .Empty; if (var.IsId && !var.HasPAttrs()) { replacements.Add(Pair.Create(var.Name, (LNode)LNode.Missing, 0)); } else { var vars = var.Args; if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs())) { replacements = new Triplet <Symbol, LNode, int> [vars.Count].AsInternalList(); for (int i = 0; i < vars.Count; i++) { replacements.InternalArray[i].A = vars[i].Name; // Check for duplicate names for (int j = 0; j < i; j++) { if (replacements[i].A == replacements[j].A && replacements[i].A.Name != "_") { sink.Error(vars[i], "Duplicate name in the left-hand tuple"); // non-fatal } } } } else { return(Reject(sink, var, "The left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers.")); } } UnrollCtx ctx = new UnrollCtx { Replacements = replacements }; WList <LNode> output = new WList <LNode>(); int iteration = 0; foreach (LNode replacement in cases) { iteration++; bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces); int count = tuple ? replacement.ArgCount : 1; if (replacements.Count != count) { sink.Error(replacement, "iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Count, count); if (count < replacements.Count) { continue; // too few } } for (int i = 0; i < replacements.Count; i++) { replacements.InternalArray[i].B = tuple ? replacement.Args[i] : replacement; } if (body.Calls(S.Braces)) { foreach (LNode stmt in body.Args) { output.Add(ctx.Replace(stmt).Value); } } else { output.Add(ctx.Replace(body).Value); } } foreach (var r in replacements) { if (r.C == 0 && !r.A.Name.StartsWith("_")) { sink.Write(Severity.Warning, var, "Replacement variable '{0}' was never used", r.A); } } return(body.With(S.Splice, output.ToVList())); }
private double? ParseNumericOption(BMultiMap<string, string> options, string key, IMessageSink sink, double? min = null, double? max = null) { string value; if (!options.TryGetValue(key, out value)) return null; double num; if (double.TryParse(value ?? "", out num)) { if ((min == null || num >= min.Value) && (max == null || num <= max.Value)) return num; } if (sink != null) { if (min != null && max != null) sink.Error("--" + key, "Expected numeric value between {0} and {1}", min.Value, max.Value); else sink.Error("--" + key, "Expected numeric value"); } return null; }