Example #1
0
        private Expression BuildFunCallExpressionFromMethodInfo(AtomMetadata atom, ParseTreeNode root, CompilerState state)
        {
            // number of arguments must exactly match number of child nodes in the tree
            var paramInfo = atom.MethodInfo.GetParameters();

            var funArgs = root.RequireChild("exprList", 1, 0);

            funArgs.RequireChildren(paramInfo.Length);

            // types and order of arguments must match nodes in the tree
            var args = new Expression[paramInfo.Length];

            for (var i = 0; i < paramInfo.Length; i++)
            {
                var param   = paramInfo[i];
                var argNode = funArgs.ChildNodes[i];
                var value   = state.ParentRuntime.Analyze(argNode, state);

                Expression adjusted;
                if (!ExpressionTreeExtensions.TryAdjustReturnType(root, value, param.ParameterType, out adjusted))
                {
                    throw new CompilationException(string.Format("Could not adjust parameter number {0} to invoke function {1}",
                                                                 i, atom.Name), funArgs.ChildNodes[i]);
                }

                args[i] = adjusted;
            }

            return(BuildFunctorInvokeExpression(atom, args));
        }
Example #2
0
        private Expression BuildFunctorInvokeExpression(AtomMetadata atom, Expression adjustedContext)
        {
            if (adjustedContext == null)
            {
                return(atom.MethodTarget == null
                        ? Expression.Call(atom.MethodInfo)
                        : Expression.Call(Expression.Constant(atom.MethodTarget), atom.MethodInfo));
            }

            return(atom.MethodTarget == null
                    ? Expression.Call(atom.MethodInfo, adjustedContext)
                    : Expression.Call(Expression.Constant(atom.MethodTarget), atom.MethodInfo, adjustedContext));
        }
        /// <summary>
        /// Registers a new atom. This API is for statically known identifiers and functions.
        /// To process identifiers whose names are not known at the time of runtime init use
        /// <see cref="IExpressionEvaluatorRuntime.RegisterDynamicAtomHandler"/>.
        /// </summary>
        /// <param name="atom">An atom to register</param>
        /// <seealso cref="AtomMetadata"/>
        /// <seealso cref="IExpressionEvaluatorRuntime.RegisterDynamicAtomHandler"/>
        public void RegisterAtom(AtomMetadata atom)
        {
            if (atom == null)
            {
                throw new ArgumentNullException("atom");
            }

            if (atom.AtomType != AtomType.Function && atom.AtomType != AtomType.Identifier)
            {
                throw new ArgumentException("Atom type is invalid: " + atom.AtomType);
            }

            if (!m_atoms.TryAdd(atom.Name, atom))
            {
                throw new ArgumentException("Atom with the same name is already registered: " + atom.Name);
            }
        }
        /// <summary>
        /// Registers an atom to process identifiers whose names are not known at the time of runtime initialization.
        /// Atom will be used as a handler and must have non-null <see cref="AtomMetadata.ExpressionGenerator"/> member.
        /// This handler will be invoked from inside <see cref="IExpressionEvaluatorRuntime.Analyze"/> for identifiers which are not statically known atoms.
        /// More than one handler can be registered, they will be invoked one after another in arbitrary order
        /// until one of their expression generators returns a non-null value.
        /// </summary>
        /// <param name="atom">An atom to register. Must have non-null value of <see cref="AtomMetadata.ExpressionGenerator"/></param>
        /// <see cref="IExpressionEvaluatorRuntime.RegisterAtom"/>
        /// <see cref="AtomMetadata.ExpressionGenerator"/>
        public void RegisterDynamicAtomHandler(AtomMetadata atom)
        {
            if (atom == null)
            {
                throw new ArgumentNullException("atom");
            }

            if (atom.AtomType != AtomType.Function && atom.AtomType != AtomType.Identifier)
            {
                throw new ArgumentException("Atom type is invalid: " + atom.AtomType);
            }

            if (atom.ExpressionGenerator == null)
            {
                throw new ArgumentException("Atom handlers must have non-null ExpressionGenerator member", "atom");
            }

            m_atomHandlers.Add(atom);
        }
Example #5
0
 private Expression BuildFunctorInvokeExpression(AtomMetadata atom, Expression[] args)
 {
     return(atom.MethodTarget == null
             ? Expression.Call(atom.MethodInfo, args)
             : Expression.Call(Expression.Constant(atom.MethodTarget), atom.MethodInfo, args));
 }