private Expression BuildIdentifierRootExpression(ParseTreeNode root, CompilerState state) { AtomMetadata atom; var name = root.ChildNodes[0].Token.ValueString; // first, look for an argument with this name var argument = state.TryGetArgumentByName(name); if (argument != null) { return(argument); } var context = state.Context; // next, see if we have a field or property on the context (if any context present) var contextBoundExpression = TryGetFieldOrPropertyInfoFromContext(name, context); if (contextBoundExpression != null) { return(contextBoundExpression); } // and only then look through available IDENTIFIER atoms if (m_atoms.TryGetValue(name, out atom) && atom.AtomType == AtomType.Identifier) { if (atom.ExpressionGenerator != null) { return(atom.ExpressionGenerator(root, state)); } if (atom.MethodInfo == null) { // internal error, somebody screwed up with configuration of runtime throw new Exception("ExpressionGenerator and MethodInfo are both null on atom: " + atom.Name); } // no arguments? great var paramInfo = atom.MethodInfo.GetParameters(); if (paramInfo.Length == 0) { return(BuildFunctorInvokeExpression(atom, (Expression[])null)); } // any arguments? must have exactly one argument, context must be registered, and context type must be adjustable to this method's arg type if (context == null) { throw new CompilationException("Atom's MethodInfo cannot be used for an Id expression, because context is not available: " + atom.Name, root); } Expression adjustedContext; if (paramInfo.Length > 1 || !ExpressionTreeExtensions.TryAdjustReturnType(root, context, paramInfo[0].ParameterType, out adjustedContext)) { throw new CompilationException("Atom's MethodInfo may only have either zero arguments or one argument of the same type as expression context: " + atom.Name, root); } return(BuildFunctorInvokeExpression(atom, adjustedContext)); } // still nothing found? ask IDENTIFIER atom handlers foreach (var handler in m_atomHandlers) { if (handler.AtomType != AtomType.Identifier) { continue; } if (handler.ExpressionGenerator == null) { // internal error, somebody screwed up with configuration of runtime throw new Exception("ExpressionGenerator is null on atom handler: " + handler.Name); } // only pass the first portion of dot-notation identifier to handler var result = handler.ExpressionGenerator(root.ChildNodes[0], state); if (result != null) { return(result); } } throw new CompilationException("Unknown atom: " + name, root); }