Enhanced C#
Language of your choice: library documentation
Public fields | Properties | Public Member Functions | Static Public Member Functions | List of all members
LeMP.MacroProcessor Class Reference

Encapsulates the LeMP engine, a simple LISP-style macro processor, suitable for running LLLPG and other lexical macros. More...


Source file:

Remarks

Encapsulates the LeMP engine, a simple LISP-style macro processor, suitable for running LLLPG and other lexical macros.

MacroProcessor itself only cares about a few nodes including #importMacros and #unimportMacros, and { braces } (for scoping the #import statements). The macro processor should be configured with any needed macros like this:

var prelude = typeof(LeMP.Prelude.BuiltinMacros); // the default prelude
var MP = new MacroProcessor(prelude, sink);
MP.AddMacros(typeof(LeMP.StandardMacros).Assembly);
MP.PreOpenedNamespaces.Add((Symbol) "LeMP.Prelude"); // already done for you
MP.PreOpenedNamespaces.Add((Symbol) "LeMP");

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.

Public fields

int MaxExpansions = 255
 
MMap< object, object > DefaultScopedProperties = new MMap<object, object>()
 Default values of scoped properties. More...
 

Properties

IMessageSink Sink [get, set]
 
static MacroProcessor Current [get]
 Returns the MacroProcessor running on the current thread, or null if none. More...
 
ICollection< SymbolPreOpenedNamespaces [get]
 Macros in these namespaces will be available without an explicit import command (#importMacros). By default this list has one item: @LeMP.Prelude (i.e. (Symbol)"LeMP.Prelude") More...
 
TimeSpan AbortTimeout [get, set]
 
static int NextTempCounter [get]
 Gets the next number to use as a suffix for temporary variables (without incrementing). More...
 

Public Member Functions

 MacroProcessor (IMessageSink sink)
 Initializes MacroProcessor with default prelude. More...
 
 MacroProcessor (IMessageSink sink, Type prelude)
 Initializes MacroProcessor. More...
 
bool AddMacros (Type type)
 
bool AddMacros (Assembly assembly, bool writeToSink=true)
 
VList< LNodeProcessSynchronously (VList< LNode > stmts)
 Processes a list of nodes directly on the current thread. More...
 
void ProcessSynchronously (IReadOnlyList< InputOutput > sourceFiles, Action< InputOutput > onProcessed=null)
 Processes source files one at a time (may be easier for debugging). More...
 
void ProcessParallel (IReadOnlyList< InputOutput > sourceFiles, Action< InputOutput > onProcessed=null)
 Processes source files in parallel. All files are fully processed before the method returns. More...
 
Task< VList< LNode > >[] ProcessAsync (IReadOnlyList< InputOutput > sourceFiles, Action< InputOutput > onProcessed=null)
 Processes source files in parallel using .NET Tasks. The method returns immediately. More...
 

Static Public Member Functions

static int IncrementTempCounter ()
 Gets the next number to use as a suffix for temporary variables, then increments it. More...
 

Constructor & Destructor Documentation

LeMP.MacroProcessor.MacroProcessor ( IMessageSink  sink)
inline

Initializes MacroProcessor with default prelude.

LeMP.MacroProcessor.MacroProcessor ( IMessageSink  sink,
Type  prelude 
)
inline

Initializes MacroProcessor.

Parameters
sinkThe destination for warning and error messages. NOTE: this class can process files in parallel. Consider using a thread-safe implementation of IMessageSink.
preludeAn initial type from which to add macros. Omit this parameter to use typeof(LeMP.Prelude.BuiltinMacros).

Member Function Documentation

static int LeMP.MacroProcessor.IncrementTempCounter ( )
inlinestatic

Gets the next number to use as a suffix for temporary variables, then increments it.

MacroProcessor currently starts this counter at 10 to avoid collisions with names like tmp_2 and tmp_3 that might be names chosen by a developer; tmp_10 is much less likely to collide.

Task<VList<LNode> > [] LeMP.MacroProcessor.ProcessAsync ( IReadOnlyList< InputOutput sourceFiles,
Action< InputOutput onProcessed = null 
)
inline

Processes source files in parallel using .NET Tasks. The method returns immediately.

References Loyc.Threading.ThreadEx.PropagateVariables().

void LeMP.MacroProcessor.ProcessParallel ( IReadOnlyList< InputOutput sourceFiles,
Action< InputOutput onProcessed = null 
)
inline

Processes source files in parallel. All files are fully processed before the method returns.

Referenced by LeMP.Compiler.Run().

VList<LNode> LeMP.MacroProcessor.ProcessSynchronously ( VList< LNode stmts)
inline

Processes a list of nodes directly on the current thread.

Note: AbortTimeout doesn't work when using this overload.

Referenced by LeMP.Compiler.Run().

void LeMP.MacroProcessor.ProcessSynchronously ( IReadOnlyList< InputOutput sourceFiles,
Action< InputOutput onProcessed = null 
)
inline

Processes source files one at a time (may be easier for debugging).

Member Data Documentation

MMap<object, object> LeMP.MacroProcessor.DefaultScopedProperties = new MMap<object, object>()

Default values of scoped properties.

Code being processed can look up a scoped property named "N" with #getScopedProperty("N") in LESv2 or EC#. This map is empty by default. Scoped properties are "scoped" in the sense that setting a property with #setScopedProperty(keyLiteral, valueLiteral) takes effect only until the end of the braced block in which it appears.

The @#inputFolder and @#inputFileName properties (note: @ is EC# syntax for Symbol) are not normally stored in this collection; when you use ProcessSynchronously or ProcessParallel, @#inputFolder and @#inputFileName are set according to the folder and filename in InputOutput.FileName. However, @#inputFolder is not set if the filename has no folder component, so this collection could be used to provide a value of @#inputFolder in that case.

Referenced by LeMP.Compiler.AddStdMacros().

Property Documentation

MacroProcessor LeMP.MacroProcessor.Current
staticget

Returns the MacroProcessor running on the current thread, or null if none.

int LeMP.MacroProcessor.NextTempCounter
staticget

Gets the next number to use as a suffix for temporary variables (without incrementing).

ICollection<Symbol> LeMP.MacroProcessor.PreOpenedNamespaces
get

Macros in these namespaces will be available without an explicit import command (#importMacros). By default this list has one item: @LeMP.Prelude (i.e. (Symbol)"LeMP.Prelude")

Referenced by LeMP.Compiler.AddStdMacros().