The CQR implementation of QilExpression.

QilExpression is the XML Query Intermediate Language invented by Michael Brundage and Chris Suver. QilExpression is an intermediate representation (IR) for all XML query and view languages. QilExpression is designed for optimization, composition with virtual XML views, translation into other forms, and direct execution. See also the QIL specification.

상속: QilNode
예제 #1
0
 /// <summary>
 /// This function is called on every recompilation to discard all previous results
 /// </summary>
 private void Reset()
 {
     _compilerErrorColl = null;
     _outputSettings = null;
     _qil = null;
     _command = null;
 }
예제 #2
0
        //-----------------------------------------------
        // Entry
        //-----------------------------------------------

        /// <summary>
        /// Visits the specified QilExpression graph and generates MSIL code.
        /// </summary>
        public void Visit(QilExpression qil, GenerateHelper helper, MethodInfo methRoot)
        {
            _qil = qil;
            _helper = helper;
            _iterNested = null;
            _indexId = 0;

            // Prepare each global parameter and global variable to be visited
            PrepareGlobalValues(qil.GlobalParameterList);
            PrepareGlobalValues(qil.GlobalVariableList);

            // Visit each global parameter and global variable
            VisitGlobalValues(qil.GlobalParameterList);
            VisitGlobalValues(qil.GlobalVariableList);

            // Build each function
            foreach (QilFunction ndFunc in qil.FunctionList)
            {
                // Visit each parameter and the function body
                Function(ndFunc);
            }

            // Build the root expression
            _helper.MethodBegin(methRoot, null, true);
            StartNestedIterator(qil.Root);
            Visit(qil.Root);
            Debug.Assert(_iterCurr.Storage.Location == ItemLocation.None, "Root expression should have been pushed to the writer.");
            EndNestedIterator(qil.Root);
            _helper.MethodEnd();
        }
예제 #3
0
 /// <summary>
 /// This function is called on every recompilation to discard all previous results
 /// </summary>
 private void Reset()
 {
     _compilerResults = null;
     _outputSettings = null;
     _qil = null;
     _command = null;
 }
예제 #4
0
 public XmlILOptimizerVisitor(QilExpression qil, bool optimize) : base(optimize ? s_patternsOpt : s_patternsNoOpt, qil.Factory)
 {
     _qil = qil;
     _elemAnalyzer = new XmlILElementAnalyzer(qil.Factory);
     _contentAnalyzer = new XmlILStateAnalyzer(qil.Factory);
     _nmspAnalyzer = new XmlILNamespaceAnalyzer();
 }
예제 #5
0
        //-----------------------------------------------
        // Convenience methods
        //-----------------------------------------------

        public QilExpression QilExpression(QilNode root, QilFactory factory)
        {
            QilExpression n = new QilExpression(QilNodeType.QilExpression, root, factory);
            n.XmlType = _typeCheck.CheckQilExpression(n);
            TraceNode(n);
            return n;
        }
예제 #6
0
        /// <summary>
        /// Scan through the external parameters, global variables, and function list for forward references.
        /// </summary>
        protected override QilNode VisitQilExpression(QilExpression qil)
        {
            IList <QilNode> fdecls = new ForwardRefFinder().Find(qil);

            if (fdecls != null && fdecls.Count > 0)
            {
                this.writer.WriteStartElement("ForwardDecls");
                foreach (QilNode n in fdecls)
                {
                    // i.e. <Function id="$a"/>
                    this.writer.WriteStartElement(Enum.GetName(typeof(QilNodeType), n.NodeType));
                    this.writer.WriteAttributeString("id", _ngen.NameOf(n));
                    WriteXmlType(n);

                    if (n.NodeType == QilNodeType.Function)
                    {
                        // Visit Arguments and SideEffects operands
                        Visit(n[0]);
                        Visit(n[2]);
                    }

                    this.writer.WriteEndElement();
                }
                this.writer.WriteEndElement();
            }

            return(VisitChildren(qil));
        }
예제 #7
0
        //-----------------------------------------------
        // meta
        //-----------------------------------------------
        public QilExpression QilExpression(QilNode root)
        {
            QilExpression n = new QilExpression(QilNodeType.QilExpression, root);

            n.XmlType = _typeCheck.CheckQilExpression(n);
            TraceNode(n);
            return(n);
        }
 /// <summary>
 /// Perform tail-call analysis on the functions in the specified QilExpression.
 /// </summary>
 public static void Analyze(QilExpression qil) {
     foreach (QilFunction ndFunc in qil.FunctionList) {
         // Only analyze functions which are pushed to the writer, since otherwise code
         // is generated after the call instruction in order to process cached results
         if (XmlILConstructInfo.Read(ndFunc).ConstructMethod == XmlILConstructMethod.Writer)
             AnalyzeDefinition(ndFunc.Definition);
     }
 }
예제 #9
0
        //-----------------------------------------------
        // Convenience methods
        //-----------------------------------------------

        public QilExpression QilExpression(QilNode root, QilFactory factory)
        {
            QilExpression n = new QilExpression(QilNodeType.QilExpression, root, factory);

            n.XmlType = this.typeCheck.CheckQilExpression(n);
            TraceNode(n);
            return(n);
        }
예제 #10
0
 //-----------------------------------------------
 // meta
 //-----------------------------------------------
 public XmlQueryType CheckQilExpression(QilExpression node)
 {
     Check(node[0].NodeType == QilNodeType.False || node[0].NodeType == QilNodeType.True, node, "IsDebug must either be True or False");
     CheckLiteralValue(node[1], typeof(XmlWriterSettings));
     CheckLiteralValue(node[2], typeof(IList <WhitespaceRule>));
     CheckClassAndNodeType(node[3], typeof(QilList), QilNodeType.GlobalParameterList);
     CheckClassAndNodeType(node[4], typeof(QilList), QilNodeType.GlobalVariableList);
     CheckClassAndNodeType(node[5], typeof(QilList), QilNodeType.FunctionList);
     return(XmlQueryTypeFactory.ItemS);
 }
예제 #11
0
        /// <summary>
        /// Given the logical query plan (QilExpression) generate a physical query plan (MSIL) that can be executed.
        /// </summary>
        // SxS Note: The way the trace file names are created (hardcoded) is NOT SxS safe. However the files are
        // created only for internal tracing purposes. In addition XmlILTrace class is not compiled into retail 
        // builds. As a result it is fine to suppress the FxCop SxS warning.
        public XmlILCommand Generate(QilExpression query, TypeBuilder typeBldr)
        {
            _qil = query;

            bool useLRE = (
                !_qil.IsDebug &&
                (typeBldr == null)
#if DEBUG
                && !XmlILTrace.IsEnabled // Dump assembly to disk; can't do this when using LRE
#endif
            );
            bool emitSymbols = _qil.IsDebug;

            // In debug code, ensure that input QIL is correct
            QilValidationVisitor.Validate(_qil);

#if DEBUG
            // Trace Qil before optimization
            XmlILTrace.WriteQil(this.qil, "qilbefore.xml");

            // Trace optimizations
            XmlILTrace.TraceOptimizations(this.qil, "qilopt.xml");
#endif

            // Optimize and annotate the Qil graph
            _optVisitor = new XmlILOptimizerVisitor(_qil, !_qil.IsDebug);
            _qil = _optVisitor.Optimize();

            // In debug code, ensure that output QIL is correct
            QilValidationVisitor.Validate(_qil);

#if DEBUG
            // Trace Qil after optimization
            XmlILTrace.WriteQil(this.qil, "qilafter.xml");
#endif

            // Create module in which methods will be generated
            if (typeBldr != null)
            {
                _module = new XmlILModule(typeBldr);
            }
            else
            {
                _module = new XmlILModule(useLRE, emitSymbols);
            }

            // Create a code generation helper for the module; enable optimizations if IsDebug is false
            _helper = new GenerateHelper(_module, _qil.IsDebug);

            // Create helper methods
            CreateHelperFunctions();

            // Create metadata for the Execute function, which is the entry point to the query
            // public static void Execute(XmlQueryRuntime);
            MethodInfo methExec = _module.DefineMethod("Execute", typeof(void), new Type[] { }, new string[] { }, XmlILMethodAttributes.NonUser);

            // Create metadata for the root expression
            // public void Root()
            Debug.Assert(_qil.Root != null);
            XmlILMethodAttributes methAttrs = (_qil.Root.SourceLine == null) ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None;
            MethodInfo methRoot = _module.DefineMethod("Root", typeof(void), new Type[] { }, new string[] { }, methAttrs);

            // Declare all early bound function objects
            foreach (EarlyBoundInfo info in _qil.EarlyBoundTypes)
            {
                _helper.StaticData.DeclareEarlyBound(info.NamespaceUri, info.EarlyBoundType);
            }

            // Create metadata for each QilExpression function that has at least one caller
            CreateFunctionMetadata(_qil.FunctionList);

            // Create metadata for each QilExpression global variable and parameter
            CreateGlobalValueMetadata(_qil.GlobalVariableList);
            CreateGlobalValueMetadata(_qil.GlobalParameterList);

            // Generate Execute method
            GenerateExecuteFunction(methExec, methRoot);

            // Visit the QilExpression graph
            _xmlIlVisitor = new XmlILVisitor();
            _xmlIlVisitor.Visit(_qil, _helper, methRoot);

            // Collect all static information required by the runtime
            XmlQueryStaticData staticData = new XmlQueryStaticData(
                _qil.DefaultWriterSettings,
                _qil.WhitespaceRules,
                _helper.StaticData
            );

            // Create static constructor that initializes XmlQueryStaticData instance at runtime
            if (typeBldr != null)
            {
                CreateTypeInitializer(staticData);

                // Finish up creation of the type
                _module.BakeMethods();

                return null;
            }
            else
            {
                // Finish up creation of the type
                _module.BakeMethods();

                // Create delegate over "Execute" method
                ExecuteDelegate delExec = (ExecuteDelegate)_module.CreateDelegate("Execute", typeof(ExecuteDelegate));
                return new XmlILCommand(delExec, staticData);
            }
        }
예제 #12
0
 // Do not edit this region
 #region AUTOGENERATED
 #region meta
 protected override QilNode VisitQilExpression(QilExpression n) { return NoReplace(n); }
예제 #13
0
 //-----------------------------------------------
 // meta
 //-----------------------------------------------
 public QilExpression QilExpression(QilNode root) {
     QilExpression n = new QilExpression(QilNodeType.QilExpression, root);
     n.XmlType = this.typeCheck.CheckQilExpression(n);
     TraceNode(n);
     return n;
 }
예제 #14
0
 protected virtual QilNode VisitQilExpression(QilExpression n) { return VisitChildren(n); }
예제 #15
0
 /// <summary>
 /// Serialize rewritten Qil tree to writer "w".
 /// </summary>
 private static void WriteQilRewrite(QilExpression qil, XmlWriter w, string rewriteName) {
     w.WriteStartElement("Diff");
     if (rewriteName != null)
         w.WriteAttributeString("rewrite", rewriteName);
     WriteQil(qil, w);
     w.WriteEndElement();
 }
 public XmlILOptimizerVisitor(QilExpression qil, bool optimize) : base(optimize ? PatternsOpt : PatternsNoOpt, qil.Factory) {
     this.qil = qil;
     this.elemAnalyzer = new XmlILElementAnalyzer(qil.Factory);
     this.contentAnalyzer = new XmlILStateAnalyzer(qil.Factory);
     this.nmspAnalyzer = new XmlILNamespaceAnalyzer();
 }
        // Do not edit this region
        // It is auto-generated
        #region AUTOGENERATED

        #region meta
        protected override QilNode VisitQilExpression(QilExpression local0) {
            QilNode local1 = local0[0];
            if (this[XmlILOptimization.EliminateUnusedFunctions]) {
                if (AllowReplace(XmlILOptimization.EliminateUnusedFunctions, local0)) {
                    
    IList<QilNode> funcList = local0.FunctionList;
    for (int i = funcList.Count - 1; i >= 0; i--) {
        if (XmlILConstructInfo.Write(funcList[i]).CallersInfo.Count == 0)
            funcList.RemoveAt(i);
    }
}
            }
            if (this[XmlILOptimization.AnnotateConstruction]) {
                if (AllowReplace(XmlILOptimization.AnnotateConstruction, local0)) {
                    
    foreach (QilFunction ndFunc in local0.FunctionList) {
        // Functions that construct Xml trees should stream output to writer; otherwise, results should
        // be cached and returned.
        if (IsConstructedExpression(ndFunc.Definition)) {
            // Perform state analysis on function's content
            ndFunc.Definition = this.contentAnalyzer.Analyze(ndFunc, ndFunc.Definition);
        }
    }

    // Perform state analysis on the root expression
    local0.Root = this.contentAnalyzer.Analyze(null, local0.Root);

    // Make sure that root expression is pushed to writer
    XmlILConstructInfo.Write(local0.Root).PushToWriterLast = true;
}
            }
            return NoReplace(local0);
        }
        /// <summary>
        /// Given the logical query plan (QilExpression) generate a physical query plan (MSIL) that can be executed.
        /// </summary>
        public XmlCommand Generate(QilExpression query, AssemblyName asmName) {
            MethodInfo methRoot, methExec;
            bool useLRE, emitSymbols;
            ExecuteDelegate delExec;
            XmlILMethodAttributes methAttrs;

            this.qil = query;

            useLRE = !this.qil.IsDebug && (asmName == null);
            emitSymbols = this.qil.IsDebug;

            // In debug code, ensure that input QIL is correct
            QilValidationVisitor.Validate(this.qil);

            // Trace Qil before optimization
            XmlILTrace.WriteQil(this.qil, "qilbefore.xml");

            // Trace optimizations
            XmlILTrace.TraceOptimizations(this.qil, "qilopt.xml");

            if (XmlILTrace.IsEnabled) {
                // Dump assembly to disk; can't do this when using LRE
                useLRE = false;
            }

            // Optimize and annotate the Qil graph
            this.optVisitor = new XmlILOptimizerVisitor(this.qil, !this.qil.IsDebug);
            this.qil = this.optVisitor.Optimize();

            // In debug code, ensure that output QIL is correct
            QilValidationVisitor.Validate(this.qil);

            // Trace Qil after optimization
            XmlILTrace.WriteQil(this.qil, "qilafter.xml");

            // Create module in which methods will be generated
            this.module = new XmlILModule(useLRE, emitSymbols, asmName);

            // Create a code generation helper for the module; enable optimizations if IsDebug is false
            this.helper = new GenerateHelper(this.module, this.qil.IsDebug);

            // Create helper methods
            CreateHelperFunctions();

            // Create metadata for the root expression
            // public void Root()
            Debug.Assert(this.qil.Root != null);
            methAttrs = (this.qil.Root.SourceLine == null) ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None;
            methRoot = this.module.DefineMethod("Root", typeof(void), new Type[] {}, new string[] {}, methAttrs);

            // Create metadata for each QilExpression function that has at least one caller
            CreateFunctionMetadata(this.qil.FunctionList);

            // Create metadata for each QilExpression global variable and parameter
            CreateGlobalValueMetadata(this.qil.GlobalVariableList);
            CreateGlobalValueMetadata(this.qil.GlobalParameterList);

            // Create Execute method
            methExec = CreateExecuteFunction(methRoot);

            // Visit the QilExpression graph
            this.xmlIlVisitor = new XmlILVisitor();
            this.xmlIlVisitor.Visit(this.qil, this.helper, methRoot);

            this.module.BakeMethods();

            // Create delegate over "Execute" method
            delExec = (ExecuteDelegate) this.module.CreateDelegate("Execute", typeof(ExecuteDelegate));

            return new XmlILCommand(delExec, this.qil, this.helper.StaticData);
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 public XmlILCommand(ExecuteDelegate delExec, QilExpression qil, StaticDataManager staticData) {
     Debug.Assert(qil != null);
     this.delExec = delExec;
     this.defaultWriterSettings = qil.DefaultWriterSettings;
     this.wsRules = qil.WhitespaceRules;
     this.names = staticData.Names;
     this.prefixMappingsList = staticData.PrefixMappingsList;
     this.filters = staticData.NameFilters;
     this.types = staticData.XmlTypes;
     this.collations = staticData.Collations;
     this.globalNames = staticData.GlobalNames;
     this.earlyInfo = staticData.EarlyBound;
 }
 private void CompileIlFromQil(XsltSettings settings) {
     command = new XmlILGenerator().Generate(qil, settings.AssemblyName);
     // Set outputSettings only if compilation was successful
     outputSettings = qil.DefaultWriterSettings;
     qil = null;
 }
예제 #21
0
        public static void TraceOptimizations(QilExpression qil, string fileName) {
            if (!IsEnabled)
                return;

            XmlWriter w = XmlWriter.Create(dirName + "\\" + fileName);

            w.WriteStartDocument();
            w.WriteProcessingInstruction("xml-stylesheet", "href='qilo.xslt' type='text/xsl'");
            w.WriteStartElement("QilOptimizer");
            w.WriteAttributeString("timestamp", DateTime.Now.ToString(CultureInfo.InvariantCulture));
            WriteQilRewrite(qil, w, null);

            try {
                // Then, rewrite the graph until "done" or some max value is reached.
                for (int i = 1; i < MAX_REWRITES; i++) {
                    QilExpression qilTemp = (QilExpression) (new QilCloneVisitor(qil.Factory).Clone(qil));

                    XmlILOptimizerVisitor visitor = new XmlILOptimizerVisitor(qilTemp, !qilTemp.IsDebug);
                    visitor.Threshold = i;
                    qilTemp = visitor.Optimize();

                    // In debug code, ensure that QIL after N steps is correct
                    QilValidationVisitor.Validate(qilTemp);

                    // Trace the rewrite
                    WriteQilRewrite(qilTemp, w, OptimizationToString(visitor.LastReplacement));

                    if (visitor.ReplacementCount < i)
                        break;
                }
            }
            catch (Exception e) {
                if (!XmlException.IsCatchableException(e)) {
                    throw;
                }
                w.WriteElementString("Exception", null, e.ToString());
                throw;
            }
            finally {
                w.WriteEndElement();
                w.WriteEndDocument();
                w.Flush();
                w.Close();
            }
        }
예제 #22
0
 public IList <QilNode> Find(QilExpression qil)
 {
     Visit(qil);
     return(_fwdrefs);
 }
예제 #23
0
 /// <summary>
 /// Serialize Qil tree to writer "w".
 /// </summary>
 private static void WriteQil(QilExpression qil, XmlWriter w) {
     QilXmlWriter qw = new QilXmlWriter(w);
     qw.ToXml(qil);
 }
예제 #24
0
        // Do not edit this region
        // It is auto-generated
        #region AUTOGENERATED

        #region meta
        protected override QilNode VisitQilExpression(QilExpression local0)
        {
            QilNode local1 = local0[0];
            if (this[XmlILOptimization.EliminateUnusedGlobals])
            {
                // PATTERN: [EliminateUnusedGlobals] $qil:(QilExpression *) => { ... }
                if (AllowReplace(XmlILOptimization.EliminateUnusedGlobals, local0))
                {
                    EliminateUnusedGlobals(local0.GlobalVariableList);
                    EliminateUnusedGlobals(local0.GlobalParameterList);
                    EliminateUnusedGlobals(local0.FunctionList);
                }
            }
            if (this[XmlILOptimization.AnnotateConstruction])
            {
                // PATTERN: [AnnotateConstruction] $qil:(QilExpression *) => { ... }
                if (AllowReplace(XmlILOptimization.AnnotateConstruction, local0))
                {
                    foreach (QilFunction ndFunc in local0.FunctionList)
                    {
                        // Functions that construct Xml trees should stream output to writer; otherwise, results should
                        // be cached and returned.
                        if (IsConstructedExpression(ndFunc.Definition))
                        {
                            // Perform state analysis on function's content
                            ndFunc.Definition = _contentAnalyzer.Analyze(ndFunc, ndFunc.Definition);
                        }
                    }

                    // Perform state analysis on the root expression
                    local0.Root = _contentAnalyzer.Analyze(null, local0.Root);

                    // Make sure that root expression is pushed to writer
                    XmlILConstructInfo.Write(local0.Root).PushToWriterLast = true;
                }
            }
            return NoReplace(local0);
        }
예제 #25
0
        public static void WriteQil(QilExpression qil, string fileName) {
            if (!IsEnabled)
                return;

            XmlWriter w = XmlWriter.Create(dirName + "\\" + fileName);
            try {
                WriteQil(qil, w);
            }
            finally {
                w.Close();
            }
        }
 /// <summary>
 /// This function is called on every recompilation to discard all previous results
 /// </summary>
 private void Reset() {
     this.compilerResults = null;
     this.outputSettings  = null;
     this.qil             = null;
     this.command         = null;
 }
예제 #27
0
 //-----------------------------------------------
 // meta
 //-----------------------------------------------
 public XmlQueryType CheckQilExpression(QilExpression node) {
     Check(node[0].NodeType == QilNodeType.False || node[0].NodeType == QilNodeType.True, node, "IsDebug must either be True or False");
     CheckLiteralValue(node[1], typeof(XmlWriterSettings));
     CheckLiteralValue(node[2], typeof(IList<WhitespaceRule>));
     CheckClassAndNodeType(node[3], typeof(QilList), QilNodeType.GlobalParameterList);
     CheckClassAndNodeType(node[4], typeof(QilList), QilNodeType.GlobalVariableList);
     CheckLiteralValue(node[5], typeof(IList<EarlyBoundInfo>));
     CheckClassAndNodeType(node[6], typeof(QilList), QilNodeType.FunctionList);
     return XmlQueryTypeFactory.ItemS;
 }
예제 #28
0
 protected override QilNode VisitQilExpression(QilExpression n)
 {
     return(NoReplace(n));
 }
        private void EndElement()
        {
            MethodInfo facMethod = null;

            object[]         facArgs;
            QilList          list;
            QilNode          nd;
            ReaderAnnotation ann;

            list = this.stk.Pop();
            ann  = (ReaderAnnotation)list.Annotation;

            // Special case certain element names
            string s = r.LocalName;

            switch (r.LocalName)
            {
            case "QilExpression": {
                Debug.Assert(list.Count > 0, "QilExpression node requires a Root expression");
                QilExpression qil = f.QilExpression(list[list.Count - 1]);

                // Be flexible on order and presence of QilExpression children
                for (int i = 0; i < list.Count - 1; i++)
                {
                    switch (list[i].NodeType)
                    {
                    case QilNodeType.True:
                    case QilNodeType.False:
                        qil.IsDebug = list[i].NodeType == QilNodeType.True;
                        break;

                    case QilNodeType.FunctionList:
                        qil.FunctionList = (QilList)list[i];
                        break;

                    case QilNodeType.GlobalVariableList:
                        qil.GlobalVariableList = (QilList)list[i];
                        break;

                    case QilNodeType.GlobalParameterList:
                        qil.GlobalParameterList = (QilList)list[i];
                        break;
                    }
                }
                nd = qil;
                break;
            }

            case "ForwardDecls":
                this.inFwdDecls = false;
                return;

            case "Parameter":
            case "Let":
            case "For":
            case "Function": {
                string  id   = ann.Id;
                QilName name = ann.Name;
                Debug.Assert(id != null, r.LocalName + " must have an id attribute");
                Debug.Assert(!this.inFwdDecls || ann.XmlType != null, "Forward decl for " + r.LocalName + " '" + id + "' must have an xmlType attribute");

                // Create node (may be discarded later if it was already declared in forward declarations section)
                switch (r.LocalName)
                {
                case "Parameter":
                    Debug.Assert(list.Count <= (this.inFwdDecls ? 0 : 1), "Parameter '" + id + "' must have 0 or 1 arguments");
                    Debug.Assert(ann.XmlType != null, "Parameter '" + id + "' must have an xmlType attribute");
                    if (this.inFwdDecls || list.Count == 0)
                    {
                        nd = f.Parameter(null, name, ann.XmlType);
                    }
                    else
                    {
                        nd = f.Parameter(list[0], name, ann.XmlType);
                    }
                    break;

                case "Let":
                    Debug.Assert(list.Count == (this.inFwdDecls ? 0 : 1), "Let '" + id + "' must have 0 or 1 arguments");
                    if (this.inFwdDecls)
                    {
                        nd = f.Let(f.Unknown(ann.XmlType));
                    }
                    else
                    {
                        nd = f.Let(list[0]);
                    }
                    break;

                case "For":
                    Debug.Assert(list.Count == 1, "For '" + id + "' must have 1 argument");
                    nd = f.For(list[0]);
                    break;

                default:
                    Debug.Assert(list.Count == (this.inFwdDecls ? 2 : 3), "Function '" + id + "' must have 2 or 3 arguments");
                    if (this.inFwdDecls)
                    {
                        nd = f.Function(list[0], list[1], ann.XmlType);
                    }
                    else
                    {
                        nd = f.Function(list[0], list[1], list[2], ann.XmlType != null ? ann.XmlType : list[1].XmlType);
                    }
                    break;
                }

                // Set DebugName
                if (name != null)
                {
                    ((QilReference)nd).DebugName = name.ToString();
                }

                if (this.inFwdDecls)
                {
                    Debug.Assert(!this.scope.ContainsKey(id), "Multiple nodes have id '" + id + "'");
                    this.fwdDecls[id] = nd;
                    this.scope[id]    = nd;
                }
                else
                {
                    if (this.fwdDecls.ContainsKey(id))
                    {
                        // Replace forward declaration
                        Debug.Assert(r.LocalName == Enum.GetName(typeof(QilNodeType), nd.NodeType), "Id '" + id + "' is not not bound to a " + r.LocalName + " forward decl");
                        nd = this.fwdDecls[id];
                        this.fwdDecls.Remove(id);

                        if (list.Count > 0)
                        {
                            nd[0] = list[0];
                        }
                        if (list.Count > 1)
                        {
                            nd[1] = list[1];
                        }
                    }
                    else
                    {
                        // Put reference in scope
                        Debug.Assert(!this.scope.ContainsKey(id), "Id '" + id + "' is already in scope");
                        this.scope[id] = nd;
                    }
                }
                nd.Annotation = ann;
                break;
            }

            case "RefTo": {
                // Lookup reference
                string id = ann.Id;
                Debug.Assert(id != null, r.LocalName + " must have an id attribute");

                Debug.Assert(this.scope.ContainsKey(id), "Id '" + id + "' is not in scope");
                this.stk.Peek().Add(this.scope[id]);
                return;
            }

            case "Sequence":
                nd = f.Sequence(list);
                break;

            case "FunctionList":
                nd = f.FunctionList(list);
                break;

            case "GlobalVariableList":
                nd = f.GlobalVariableList(list);
                break;

            case "GlobalParameterList":
                nd = f.GlobalParameterList(list);
                break;

            case "ActualParameterList":
                nd = f.ActualParameterList(list);
                break;

            case "FormalParameterList":
                nd = f.FormalParameterList(list);
                break;

            case "SortKeyList":
                nd = f.SortKeyList(list);
                break;

            case "BranchList":
                nd = f.BranchList(list);
                break;

            case "XsltInvokeEarlyBound": {
                Debug.Assert(ann.ClrNamespace != null, "XsltInvokeEarlyBound must have a clrNamespace attribute");
                Debug.Assert(list.Count == 2, "XsltInvokeEarlyBound must have exactly 2 arguments");
                Debug.Assert(list.XmlType != null, "XsltInvokeEarlyBound must have an xmlType attribute");
                MethodInfo mi   = null;
                QilName    name = (QilName)list[0];

                foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
                {
                    Type t = asm.GetType(ann.ClrNamespace);
                    if (t != null)
                    {
                        mi = t.GetMethod(name.LocalName);
                        break;
                    }
                }

                Debug.Assert(mi != null, "Cannot find method " + ann.ClrNamespace + "." + name.ToString());

                nd = f.XsltInvokeEarlyBound(name, f.LiteralObject(mi), list[1], ann.XmlType);
                break;
            }

            default: {
                // Find factory method which will be used to construct the Qil node
                Debug.Assert(nameToFactoryMethod.ContainsKey(r.LocalName), "Method " + r.LocalName + " could not be found on QilFactory");
                facMethod = nameToFactoryMethod[r.LocalName];
                Debug.Assert(facMethod.GetParameters().Length == list.Count, "NodeType " + r.LocalName + " does not allow " + list.Count + " parameters");

                // Create factory method arguments
                facArgs = new object[list.Count];
                for (int i = 0; i < facArgs.Length; i++)
                {
                    facArgs[i] = list[i];
                }

                // Create node and set its properties
                nd = (QilNode)facMethod.Invoke(f, facArgs);
                break;
            }
            }

            nd.SourceLine = list.SourceLine;

            // Add node to its parent's list
            this.stk.Peek().Add(nd);
        }
 /// <summary>
 /// This function is called on every recompilation to discard all previous results
 /// </summary>
 private void Reset() {
     compilerResults = null;
     outputSettings  = null;
     qil             = null;
     command         = null;
 }
예제 #31
0
 protected virtual QilNode VisitQilExpression(QilExpression n)
 {
     return(VisitChildren(n));
 }
 private void CompileQilToMsil(XsltSettings settings) {
     this.command = new XmlILGenerator().Generate(this.qil, /*typeBuilder:*/null);
     this.outputSettings = this.command.StaticData.DefaultWriterSettings;
     this.qil = null;
 }