Encapsulates the LeMP engine, a simple LISP-style macro processor, suitable for running LLLPG and other lexical macros.
MacroProcessor itself only cares about to #import/#importMacros/#unimportMacros statements, and { braces } (for scoping the #import statements). The macro processor should be configured with any needed macros like this: var MP = new MacroProcessor(prelude, sink); MP.AddMacros(typeof(LeMP.Prelude.Macros).Assembly); MP.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude")); In order for the input code to have access to macros, two steps are necessary: you have to add the macro classes with AddMacros and then you have to import the namespace that contains the class(es). Higher-level code (e.g. Compiler) can define "always-open" namespaces by adding entries to PreOpenedNamespaces, and the code being processed can open additional namespaces with a #importMacros(Namespace) statement (in LES, "import macros Namespace" can be used as a synonym if PreOpenedNamespaces contains LeMP.Prelude). MacroProcessor is not aware of any distinction between "statements" and "expressions"; it will run macros no matter where they are located, whether as standalone statements, attributes, or arguments to functions. MacroProcessor's main responsibilities are to keep track of a table of registered macros (call AddMacros to register more), to keep track of which namespaces are open (namespaces can be imported by #import, or by import which is defined in the LES prelude); to scan the input for macros to call; and to control the printout of messages. This class processes a batch of files at once. Call either ProcessSynchronously or ProcessParallel. Parallelizing on a file-by-file basis is easy; each source file is completely independent, since no semantic analysis is being done. TODO: add method for processing an LNode instead of a list of source files.
Example #1
0
 public TestCompiler(IMessageSink sink, ICharSource text, string fileName = "")
     : base(sink, typeof(LeMP.Prelude.BuiltinMacros), new[] { new InputOutput(text, fileName) })
 {
     Parallel = false;
     MacroProcessor.AddMacros(typeof(LeMP.Prelude.Les.Macros));
     MacroProcessor.AddMacros(typeof(LeMP.Test.TestMacros));
     MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude"));
     MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude.Les"));
 }
Example #2
0
 public MacroProcessorTask(MacroProcessor parent)
 {
     _parent = parent;
     _macros = parent.Macros.Clone();
     foreach (var mi in MacroProcessor.GetMacros(this.GetType(), null, _sink, this))
     {
         MacroProcessor.AddMacro(_macros, mi);
     }
     _macroNamespaces = new MSet <Symbol>(_macros.SelectMany(ms => ms.Value).Select(mi => mi.NamespaceSym).Where(ns => ns != null));
 }
Example #3
0
        public Compiler(IMessageSink sink, Type prelude = null, bool registerEcsAndLes = true)
        {
            MacroProcessor = new MacroProcessor(prelude, sink);

            if (registerEcsAndLes)
            {
                ParsingService.Register(Loyc.Syntax.Les.LesLanguageService.Value);
                ParsingService.Register(Loyc.Ecs.EcsLanguageService.WithPlainCSharpPrinter, new[] { "cs" });
                ParsingService.Register(Loyc.Ecs.EcsLanguageService.Value);
            }
        }
Example #4
0
        MacroProcessor NewLemp(int maxExpand)
        {
            var lemp = new MacroProcessor(typeof(LeMP.Prelude.Macros), _sink);

            lemp.AddMacros(typeof(LeMP.Prelude.Les.Macros));
            lemp.AddMacros(typeof(LeMP.StandardMacros));
            lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP"));
            lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude"));
            lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude.Les"));
            lemp.MaxExpansions = maxExpand;
            return(lemp);
        }
Example #5
0
 public MacroProcessorTask(MacroProcessor parent)
 {
     _macros = parent._macros.Clone();
     // Braces must be handled specially by ApplyMacros itself, but we need
     // a macro method in order to get the special treatment, because as an
     // optimization, we ignore all symbols that are not in the macro table.
     MacroProcessor.AddMacro(_macros, new MacroInfo(null, S.Braces, OnBraces, MacroMode.Normal | MacroMode.Passive));
     MacroProcessor.AddMacro(_macros, new MacroInfo(null, S.Import, OnImport, MacroMode.Normal | MacroMode.Passive));
     MacroProcessor.AddMacro(_macros, new MacroInfo(null, _importMacros, OnImportMacros, MacroMode.Normal));
     MacroProcessor.AddMacro(_macros, new MacroInfo(null, _unimportMacros, OnUnimportMacros, MacroMode.Normal | MacroMode.Passive));
     MacroProcessor.AddMacro(_macros, new MacroInfo(null, _noLexicalMacros, NoLexicalMacros, MacroMode.NoReprocessing));
     _parent = parent;
 }
Example #6
0
 public TestCompiler(IMessageSink sink, ICharSource text, params string[] preOpenedNamespaces)
     : base(sink, typeof(LeMP.Prelude.BuiltinMacros), new[] { new InputOutput(text, "TEST") })
 {
     Parallel = false;
     MacroProcessor.AddMacros(typeof(LeMP.les2.to.ecs.Macros));
     MacroProcessor.AddMacros(typeof(LeMP.les3.to.ecs.Macros));
     MacroProcessor.AddMacros(typeof(LeMP.Tests.TestMacros));
     MacroProcessor.AddMacros(typeof(LeMP.Tests.A.AliasTest));
     MacroProcessor.AddMacros(typeof(LeMP.Tests.B.AliasTest));
     // Register all the old names, as we would in production
     MacroProcessor.AddMacros(typeof(LeMP.Prelude.Les.Macros));
     MacroProcessor.AddMacros(typeof(LeMP.Prelude.Les3.Macros));
     MacroProcessor.AddMacros(typeof(LeMP.Les3.To.CSharp.Macros));
     MacroProcessor.PreOpenedNamespaces.Add((Symbol)"LeMP.Prelude");
     foreach (var ns in preOpenedNamespaces)
     {
         MacroProcessor.PreOpenedNamespaces.Add((Symbol)ns);
     }
 }
Example #7
0
		MacroProcessor NewLemp(int maxExpand)
		{
			var lemp = new MacroProcessor(typeof(LeMP.Prelude.Macros), _sink);
			lemp.AddMacros(typeof(LeMP.Prelude.Les.Macros));
			lemp.AddMacros(typeof(LeMP.StandardMacros));
			lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP"));
			lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude"));
			lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude.Les"));
			lemp.MaxExpansions = maxExpand;
			return lemp;
		}
Example #8
0
		public Compiler(IMessageSink sink, Type prelude = null)
		{
			MacroProcessor = new MacroProcessor(prelude, sink);
		}
Example #9
0
 public Compiler(IMessageSink sink, Type prelude = null)
 {
     MacroProcessor = new MacroProcessor(prelude, sink);
 }
 public static Task<IFunctionalNamespace[]> ParseCompilationUnitsAsync(List<IProjectSourceItem> SourceItems, CompilationParameters Parameters, IBinder Binder, IAssembly DeclaringAssembly, MacroProcessor Processor, IMessageSink Sink)
 {
     var units = new Task<IFunctionalNamespace>[SourceItems.Count];
     for (int i = 0; i < units.Length; i++)
     {
         var item = SourceItems[i];
         units[i] = ParseCompilationUnitAsync(item, Parameters, Binder, DeclaringAssembly, Processor, Sink);
     }
     return Task.WhenAll(units);
 }
Example #11
0
 public int IncrementTempCounter()
 {
     return(MacroProcessor.IncrementTempCounter());
 }
Example #12
0
		MacroProcessor NewLemp(int maxExpand)
		{
			var lemp = new MacroProcessor(typeof(LeMP.Prelude.BuiltinMacros), MessageSink.Current);
			lemp.AddMacros(typeof(LeMP.Prelude.Les.Macros));
			lemp.AddMacros(typeof(LeMP.StandardMacros).Assembly);
			lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP"));
			lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude"));
			lemp.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude.Les"));
			lemp.MaxExpansions = maxExpand;
			return lemp;
		}
        public static IEnumerable<LNode> ParseNodes(string Text, string Identifier, IParsingService Service, MacroProcessor Processor, IMessageSink Sink)
        {
            var lexer = Service.Tokenize(new UString(Text), Identifier, Sink);

            var nodes = Service.Parse(lexer, Sink);

            return Processor.ProcessSynchronously(new VList<LNode>(nodes));
        }
        public static Task<IFunctionalNamespace> ParseCompilationUnitAsync(IProjectSourceItem SourceItem, CompilationParameters Parameters, IBinder Binder, IAssembly DeclaringAssembly, MacroProcessor Processor, IMessageSink Sink)
        {
            Parameters.Log.LogEvent(new LogEntry("Status", "Parsing " + SourceItem.SourceIdentifier));
            return Task.Run(() =>
            {
                var code = ProjectHandlerHelpers.GetSourceSafe(SourceItem, Parameters);
                if (code == null)
                {
                    return null;
                }
                var namer = ECSharpTypeNamer.Instance;
                var convRules = DefaultConversionRules.Create(namer.Convert);
                var globalScope = new GlobalScope(new FunctionalBinder(Binder), convRules, Parameters.Log, namer, new Flame.Syntax.MemberProvider(Binder).GetMembers, GetParameters);
                bool isLes = Enumerable.Last(SourceItem.SourceIdentifier.Split('.')).Equals("les", StringComparison.OrdinalIgnoreCase);
                var service = isLes ? (IParsingService)LesLanguageService.Value : EcsLanguageService.Value;
                var nodes = ParseNodes(code.Source, SourceItem.SourceIdentifier, service, Processor, Sink);

                if (Parameters.Log.Options.GetOption<bool>("E", false))
                {
                    var outputService = GetParsingService(Parameters.Log.Options, "syntax-format", service);
                    string newFile = outputService.Print(nodes, Sink, indentString: new string(' ', 4));
                    Parameters.Log.LogMessage(new LogEntry("'" + SourceItem.SourceIdentifier + "' after macro expansion", Environment.NewLine + newFile));
                }

                var unit = ParseCompilationUnit(nodes, globalScope, DeclaringAssembly);
                Parameters.Log.LogEvent(new LogEntry("Status", "Parsed " + SourceItem.SourceIdentifier));
                return unit;
            });
        }
Example #15
0
		public Compiler(IMessageSink sink, Type prelude = null, bool registerEcsAndLes = true)
		{
			MacroProcessor = new MacroProcessor(prelude, sink);

			if (registerEcsAndLes) {
				ParsingService.Register(Loyc.Syntax.Les.LesLanguageService.Value);
				ParsingService.Register(Loyc.Ecs.EcsLanguageService.WithPlainCSharpPrinter, new[] { "cs" });
				ParsingService.Register(Loyc.Ecs.EcsLanguageService.Value);
			}
		}
Example #16
0
 /// <summary>Adds standard macros from LeMP.StdMacros.dll, and adds the
 /// namespaces LeMP and LeMP.Prelude to the pre-opened namespace list.</summary>
 /// <remarks>Note: prelude macros were already added by the constructor.</remarks>
 public void AddStdMacros()
 {
     MacroProcessor.AddMacros(typeof(global::LeMP.StandardMacros).Assembly);
     MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP"));
     MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude"));
 }
        public static Task<IFunctionalNamespace[]> ParseCompilationUnitsAsync(List<IProjectSourceItem> SourceItems, CompilationParameters Parameters, IBinder Binder, IAssembly DeclaringAssembly)
        {
            var sink = new CompilerLogMessageSink(Parameters.Log);
            var processor = new MacroProcessor(typeof(LeMP.Prelude.BuiltinMacros), sink);

            processor.AddMacros(typeof(global::LeMP.StandardMacros).Assembly, false);

            return ParseCompilationUnitsAsync(SourceItems, Parameters, Binder, DeclaringAssembly, processor, sink);
        }