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
;
42 namespace Mono
.Xml
.XPath2
44 internal class XQueryASTCompiler
48 public static XQueryStaticContext
Compile (XQueryModule module
, XQueryCompileOptions options
, Evidence evidence
, XQueryCommandImpl commandImpl
)
51 options
= new XQueryCompileOptions ();
52 return new XQueryASTCompiler (module
, options
, new XQueryCompileContext (), evidence
, commandImpl
).Compile ();
57 private XQueryASTCompiler (XQueryModule module
, XQueryCompileOptions options
, XQueryCompileContext compileContext
, Evidence evidence
, XQueryCommandImpl commandImpl
)
60 this.options
= options
;
61 this.compileContext
= compileContext
;
62 this.evidence
= evidence
;
63 this.commandImpl
= commandImpl
;
65 inScopeSchemas
= new XmlSchemaSet ();
66 localVariables
= new Hashtable ();
67 localFunctions
= new XQueryFunctionTable ();
71 XQueryCompileOptions options
;
72 XQueryCompileContext compileContext
;
74 IXmlNamespaceResolver nsResolver
;
75 string defaultFunctionNamespace
;
77 // FIXME: Is it OK for an XmlSchema to be in two or more set?
78 XmlSchemaSet inScopeSchemas
;
79 ArrayList libModuleContexts
= new ArrayList ();
81 Hashtable localVariables
;
82 XQueryFunctionTable localFunctions
;
84 bool preserveWhitespace
; // Xml space policy
85 bool constructionSpace
; // construction mode
86 bool defaultOrdered
; // Ordering mode
89 XQueryCommandImpl commandImpl
;
93 private XQueryStaticContext
Compile ()
97 XQueryMainModule main
= module
as XQueryMainModule
;
98 ExprSequence expr
= (main
!= null) ?
99 CompileExprSequence (main
.QueryBody
) : null;
101 return new XQueryStaticContext (
109 module
.Prolog
.DefaultFunctionNamespace
,
118 private void CompileProlog ()
120 Prolog p
= module
.Prolog
;
122 // resolve external modules
123 // FIXME: check if external queries are allowed by default.
124 // FIXME: check recursion
125 XmlUrlResolver res
= new XmlUrlResolver ();
126 foreach (ModuleImport modimp
in p
.ModuleImports
) {
127 foreach (string uri
in modimp
.Locations
) {
128 Stream s
= res
.GetEntity (res
.ResolveUri (null, uri
), null, typeof (Stream
)) as Stream
;
129 XQueryLibraryModule ext
= XQueryParser
.Parse (new StreamReader (s
)) as XQueryLibraryModule
;
131 throw new XmlQueryCompileException (String
.Format ("External module {0} is resolved as a main module, while it should be a library module."));
132 XQueryStaticContext sctx
= new XQueryASTCompiler (ext
, options
, compileContext
, evidence
, commandImpl
).Compile ();
133 libModuleContexts
.Add (sctx
);
137 // resolve and compile in-scope schemas
138 foreach (SchemaImport xsimp
in p
.SchemaImports
) {
139 foreach (string uri
in xsimp
.Locations
) {
140 XmlSchema schema
= inScopeSchemas
.Add (xsimp
.Namespace
, uri
);
141 compileContext
.InEffectSchemas
.Add (schema
);
144 inScopeSchemas
.Compile ();
148 ResolveVariableReferences ();
150 // compile FunctionDeclaration into XQueryFunction
151 foreach (FunctionDeclaration func
in p
.Functions
.Values
) {
152 XQueryFunction cfunc
= CompileFunction (func
);
153 localFunctions
.Add (cfunc
);
157 private void CheckReferences ()
159 XQueryMainModule main
= module
as XQueryMainModule
;
161 main
.QueryBody
.CheckReference (this);
162 foreach (FunctionDeclaration func
in module
.Prolog
.Functions
.Values
) {
164 func
.FunctionBody
.CheckReference (this);
165 CheckSchemaType (func
.ReturnType
);
166 foreach (XQueryFunctionArgument param
in func
.Parameters
)
167 CheckSchemaType (param
.Type
);
171 internal void CheckSchemaType (SequenceType type
)
175 type
.ItemType
.CheckReference (this);
178 internal void CheckSchemaTypeName (XmlQualifiedName name
)
180 XmlSchemaType type
= XmlSchemaType
.GetBuiltInType (name
);
183 throw new XmlQueryCompileException (String
.Format ("Unresolved schema type name: {0}", name
));
186 internal void CheckVariableName (XmlQualifiedName name
)
188 // This should not be done, since unresolved QName
189 // may be still valid in context of XmlArgumentList
190 // which is supplied at dynamic evaluation phase.
192 if (module.Prolog.Variables [name] != null)
194 if (localVariables [name] != null)
196 foreach (XQueryStaticContext ctx in libModuleContexts)
197 if (ctx.InScopeVariables [name] != null)
199 throw new XmlQueryCompileException (String.Format ("Unresolved variable name: {0}", name));
203 internal void CheckFunctionName (XmlQualifiedName name
)
205 if (XQueryFunction
.FindKnownFunction (name
) != null)
207 if (module
.Prolog
.Functions
[name
] != null)
209 foreach (XQueryStaticContext ctx
in libModuleContexts
)
210 if (ctx
.InScopeFunctions
[name
] != null)
212 throw new XmlQueryCompileException (String
.Format ("Unresolved function name: {0}", name
));
215 private void ResolveVariableReferences ()
220 internal XmlSchemaType
ResolveSchemaType (XmlQualifiedName name
)
222 XmlSchemaType type
= XmlSchemaType
.GetBuiltInType (name
);
225 type
= inScopeSchemas
.GlobalTypes
[name
] as XmlSchemaType
;
231 private XQueryFunction
CompileFunction (FunctionDeclaration func
)
234 return XQueryFunction
.FromQName (func
.Name
);
235 return new XQueryUserFunction (func
.Name
, func
.Parameters
.ToArray (), func
.FunctionBody
.Expr
, func
.ReturnType
);
238 private ExprSequence
CompileExprSequence (ExprSequence expr
)
240 for (int i
= 0; i
< expr
.Count
; i
++)
241 expr
[i
] = expr
[i
].Compile (this);
245 internal void CheckType (ExprSingle expr
, SequenceType type
)
247 if (!expr
.StaticType
.CanConvertTo (type
))
248 throw new XmlQueryCompileException (String
.Format ("Cannot convert type from {0} to {1}", expr
.StaticType
, type
));
251 internal XQueryFunction
ResolveFunction (XmlQualifiedName name
)
253 XQueryFunction func
= XQueryFunction
.FindKnownFunction (name
);
255 func
= localFunctions
[name
];
260 throw new XmlQueryCompileException ("Could not find specified function.");