Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
 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));
     }
 }
Esempio n. 4
0
		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());
		}
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        /// <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));
        }
Esempio n. 7
0
 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);
         }
     }
 }
Esempio n. 8
0
 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);
     }
 }
Esempio n. 9
0
 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));
     }
 }
Esempio n. 10
0
 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++;
     }
 }
Esempio n. 11
0
 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);
     });
 }
Esempio n. 12
0
        /// <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);
        }
Esempio n. 13
0
        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;
            }
        }
Esempio n. 14
0
        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);
        }
Esempio n. 15
0
        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)));
        }
Esempio n. 16
0
		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);
			}
		}
Esempio n. 17
0
		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;
			}
		}
Esempio n. 18
0
		/// <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;
		}
Esempio n. 19
0
        /// <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);
        }
Esempio n. 20
0
		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));
		}
Esempio n. 21
0
		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());
		}
Esempio n. 22
0
		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;
		}
Esempio n. 23
0
        /// <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);
        }
Esempio n. 24
0
        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()));
        }
Esempio n. 25
0
		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;
		}