2 // XQueryASTCompiler.cs - XQuery static context compiler
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System
.Collections
;
33 using System
.Collections
.Specialized
;
35 using System
.Security
.Policy
;
37 using System
.Xml
.Query
;
38 using System
.Xml
.Schema
;
39 using Mono
.Xml
.XQuery
;
40 using Mono
.Xml
.XQuery
.Parser
;
43 namespace Mono
.Xml
.XPath2
45 internal class XQueryASTCompiler
49 public static XQueryStaticContext
Compile (XQueryModule module
, XQueryCompileOptions options
, Evidence evidence
, XQueryCommandImpl commandImpl
)
52 options
= new XQueryCompileOptions ();
53 return new XQueryASTCompiler (module
, options
, new XQueryCompileContext (), evidence
, commandImpl
).Compile ();
58 private XQueryASTCompiler (XQueryModule module
, XQueryCompileOptions options
, XQueryCompileContext compileContext
, Evidence evidence
, XQueryCommandImpl commandImpl
)
61 this.options
= options
;
62 this.compileContext
= compileContext
;
63 this.evidence
= evidence
;
64 this.commandImpl
= commandImpl
;
66 inScopeSchemas
= new XmlSchemaSet ();
67 localVariables
= new Hashtable ();
68 localFunctions
= new XQueryFunctionTable ();
72 XQueryCompileOptions options
;
73 XQueryCompileContext compileContext
;
75 IXmlNamespaceResolver nsResolver
;
76 string defaultFunctionNamespace
;
78 // FIXME: Is it OK for an XmlSchema to be in two or more set?
79 XmlSchemaSet inScopeSchemas
;
80 ArrayList libModuleContexts
= new ArrayList ();
82 Hashtable localVariables
;
83 XQueryFunctionTable localFunctions
;
85 bool preserveWhitespace
; // Xml space policy
86 bool constructionSpace
; // construction mode
87 bool defaultOrdered
; // Ordering mode
90 XQueryCommandImpl commandImpl
;
94 private XQueryStaticContext
Compile ()
98 XQueryMainModule main
= module
as XQueryMainModule
;
99 ExprSequence expr
= (main
!= null) ?
100 CompileExprSequence (main
.QueryBody
) : null;
102 return new XQueryStaticContext (
110 module
.Prolog
.DefaultFunctionNamespace
,
119 private void CompileProlog ()
121 Prolog p
= module
.Prolog
;
123 // resolve external modules
124 // FIXME: check if external queries are allowed by default.
125 // FIXME: check recursion
126 XmlUrlResolver res
= new XmlUrlResolver ();
127 foreach (ModuleImport modimp
in p
.ModuleImports
) {
128 foreach (string uri
in modimp
.Locations
) {
129 Stream s
= res
.GetEntity (res
.ResolveUri (null, uri
), null, typeof (Stream
)) as Stream
;
130 XQueryLibraryModule ext
= XQueryParser
.Parse (new StreamReader (s
)) as XQueryLibraryModule
;
132 throw new XmlQueryCompileException (String
.Format ("External module {0} is resolved as a main module, while it should be a library module."));
133 XQueryStaticContext sctx
= new XQueryASTCompiler (ext
, options
, compileContext
, evidence
, commandImpl
).Compile ();
134 libModuleContexts
.Add (sctx
);
138 // resolve and compile in-scope schemas
139 foreach (SchemaImport xsimp
in p
.SchemaImports
) {
140 foreach (string uri
in xsimp
.Locations
) {
141 XmlSchema schema
= inScopeSchemas
.Add (xsimp
.Namespace
, uri
);
142 compileContext
.InEffectSchemas
.Add (schema
);
145 inScopeSchemas
.Compile ();
149 ResolveVariableReferences ();
151 // compile FunctionDeclaration into XQueryFunction
152 foreach (FunctionDeclaration func
in p
.Functions
.Values
) {
153 XQueryFunction cfunc
= CompileFunction (func
);
154 localFunctions
.Add (cfunc
);
158 private void CheckReferences ()
160 XQueryMainModule main
= module
as XQueryMainModule
;
162 main
.QueryBody
.CheckReference (this);
163 foreach (FunctionDeclaration func
in module
.Prolog
.Functions
.Values
) {
165 func
.FunctionBody
.CheckReference (this);
166 CheckSchemaType (func
.ReturnType
);
167 foreach (XQueryFunctionArgument param
in func
.Parameters
)
168 CheckSchemaType (param
.Type
);
172 internal void CheckSchemaType (SequenceType type
)
176 type
.ItemType
.CheckReference (this);
179 internal void CheckSchemaTypeName (XmlQualifiedName name
)
181 XmlSchemaType type
= InternalPool
.GetBuiltInType (name
);
184 throw new XmlQueryCompileException (String
.Format ("Unresolved schema type name: {0}", name
));
187 internal void CheckVariableName (XmlQualifiedName name
)
189 // This should not be done, since unresolved QName
190 // may be still valid in context of XmlArgumentList
191 // which is supplied at dynamic evaluation phase.
193 if (module.Prolog.Variables [name] != null)
195 if (localVariables [name] != null)
197 foreach (XQueryStaticContext ctx in libModuleContexts)
198 if (ctx.InScopeVariables [name] != null)
200 throw new XmlQueryCompileException (String.Format ("Unresolved variable name: {0}", name));
204 internal void CheckFunctionName (XmlQualifiedName name
)
206 if (XQueryFunction
.FindKnownFunction (name
) != null)
208 if (module
.Prolog
.Functions
[name
] != null)
210 foreach (XQueryStaticContext ctx
in libModuleContexts
)
211 if (ctx
.InScopeFunctions
[name
] != null)
213 throw new XmlQueryCompileException (String
.Format ("Unresolved function name: {0}", name
));
216 private void ResolveVariableReferences ()
221 internal XmlSchemaType
ResolveSchemaType (XmlQualifiedName name
)
223 XmlSchemaType type
= InternalPool
.GetBuiltInType (name
);
226 type
= inScopeSchemas
.GlobalTypes
[name
] as XmlSchemaType
;
232 private XQueryFunction
CompileFunction (FunctionDeclaration func
)
235 return XQueryFunction
.FromQName (func
.Name
);
236 return new XQueryUserFunction (func
.Name
, func
.Parameters
.ToArray (), func
.FunctionBody
.Expr
, func
.ReturnType
);
239 private ExprSequence
CompileExprSequence (ExprSequence expr
)
241 for (int i
= 0; i
< expr
.Count
; i
++)
242 expr
[i
] = expr
[i
].Compile (this);
246 internal void CheckType (ExprSingle expr
, SequenceType type
)
248 if (!expr
.StaticType
.CanConvertTo (type
))
249 throw new XmlQueryCompileException (String
.Format ("Cannot convert type from {0} to {1}", expr
.StaticType
, type
));
252 internal XQueryFunction
ResolveFunction (XmlQualifiedName name
)
254 XQueryFunction func
= XQueryFunction
.FindKnownFunction (name
);
256 func
= localFunctions
[name
];
261 throw new XmlQueryCompileException ("Could not find specified function.");