forgotten ifdefs
[mono.git] / mcs / class / System.Web / System.Web.Compilation / BaseCompiler.cs
1 //
2 // System.Web.Compilation.BaseCompiler
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (c) Copyright 2002,2003 Ximian, Inc (http://www.ximian.com)
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.CodeDom;
33 using System.CodeDom.Compiler;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.Reflection;
37 using System.Text;
38 using System.Web.UI;
39 using System.Web.Configuration;
40 using System.IO;
41
42 namespace System.Web.Compilation
43 {
44         abstract class BaseCompiler
45         {
46 #if NET_2_0
47                 static BindingFlags replaceableFlags = BindingFlags.Public | BindingFlags.NonPublic |
48                                                   BindingFlags.Instance;
49 #endif
50
51                 TemplateParser parser;
52                 CodeDomProvider provider;
53                 ICodeCompiler compiler;
54                 CodeCompileUnit unit;
55                 CodeNamespace mainNS;
56                 CompilerParameters compilerParameters;
57 #if NET_2_0
58                 bool isRebuilding = false;
59                 protected Hashtable partialNameOverride = new Hashtable();
60                 protected CodeTypeDeclaration partialClass;
61                 protected CodeTypeReferenceExpression partialClassExpr;
62 #endif
63                 protected CodeTypeDeclaration mainClass;
64                 protected CodeTypeReferenceExpression mainClassExpr;
65                 protected static CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression ();
66
67                 protected BaseCompiler (TemplateParser parser)
68                 {
69                         compilerParameters = new CompilerParameters ();
70                         this.parser = parser;
71                 }
72
73                 void Init ()
74                 {
75                         unit = new CodeCompileUnit ();
76 #if NET_2_0
77                         if (parser.IsPartial) {
78                                 string partialns = null;
79                                 string partialclasstype = parser.PartialClassName;
80
81                                 int partialdot = partialclasstype.LastIndexOf ('.');
82                                 if (partialdot != -1) {
83                                         partialns = partialclasstype.Substring (0, partialdot);
84                                         partialclasstype = partialclasstype.Substring (partialdot + 1);
85                                 }
86                                 
87                                 CodeNamespace partialNS = new CodeNamespace (partialns);
88                                 partialClass = new CodeTypeDeclaration (partialclasstype);
89                                 partialClass.IsPartial = true;
90                                 partialClassExpr = new CodeTypeReferenceExpression (parser.PartialClassName);
91                                 
92                                 unit.Namespaces.Add (partialNS);
93                                 partialClass.TypeAttributes = TypeAttributes.Public;
94                                 partialNS.Types.Add (partialClass);
95                         }
96 #endif
97
98                         string mainclasstype = parser.ClassName;
99                         string mainns = "ASP";
100
101 #if NET_2_0
102                         int maindot = mainclasstype.LastIndexOf ('.');
103                         if (maindot != -1) {
104                                 mainns = mainclasstype.Substring (0, maindot);
105                                 mainclasstype = mainclasstype.Substring (maindot + 1);
106                         }
107 #endif
108
109                         mainNS = new CodeNamespace (mainns);
110                         mainClass = new CodeTypeDeclaration (mainclasstype);
111                         CodeTypeReference baseTypeRef;
112 #if NET_2_0
113                         if (partialClass != null) {
114                                 baseTypeRef = new CodeTypeReference (parser.PartialClassName);
115                                 baseTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
116                         } else {
117                                 baseTypeRef = new CodeTypeReference (parser.BaseType.FullName);
118                                 if (parser.BaseTypeIsGlobal)
119                                         baseTypeRef.Options |= CodeTypeReferenceOptions.GlobalReference;
120                         }
121 #else
122                         baseTypeRef = new CodeTypeReference (parser.BaseType.FullName);
123 #endif
124                         mainClass.BaseTypes.Add (baseTypeRef);
125
126                         mainClassExpr = new CodeTypeReferenceExpression (mainns + "." + mainclasstype);
127
128                         unit.Namespaces.Add (mainNS);
129                         mainClass.TypeAttributes = TypeAttributes.Public;
130                         mainNS.Types.Add (mainClass);
131
132                         foreach (object o in parser.Imports) {
133                                 if (o is string)
134                                         mainNS.Imports.Add (new CodeNamespaceImport ((string) o));
135                         }
136
137                         // StringCollection.Contains has O(n) complexity, but
138                         // considering the number of comparisons we make on
139                         // average and the fact that using an intermediate array
140                         // would be even more costly, this is fine here.
141                         StringCollection refAsm = unit.ReferencedAssemblies;
142                         string asmName;
143                         if (parser.Assemblies != null) {
144                                 foreach (object o in parser.Assemblies) {
145                                         asmName = o as string;
146                                         if (asmName != null && !refAsm.Contains (asmName))
147                                                 refAsm.Add (asmName);
148                                 }
149                         }
150
151 #if NET_2_0
152                         ArrayList al = WebConfigurationManager.ExtraAssemblies;
153                         if (al != null && al.Count > 0) {
154                                 foreach (object o in al) {
155                                         asmName = o as string;
156                                         if (asmName != null && !refAsm.Contains (asmName))
157                                                 refAsm.Add (asmName);
158                                 }
159                         }
160
161                         IList list = BuildManager.CodeAssemblies;
162                         if (list != null && list.Count > 0) {
163                                 Assembly asm;
164                                 foreach (object o in list) {
165                                         asm = o as Assembly;
166                                         if (o == null)
167                                                 continue;
168                                         asmName = asm.Location;
169                                         if (asmName != null && !refAsm.Contains (asmName))
170                                                 refAsm.Add (asmName);
171                                 }
172                         }
173 #endif
174                         // Late-bound generators specifics (as for MonoBASIC/VB.NET)
175                         unit.UserData["RequireVariableDeclaration"] = parser.ExplicitOn;
176                         unit.UserData["AllowLateBound"] = !parser.StrictOn;
177                         
178                         AddInterfaces ();
179                         AddClassAttributes ();
180                         CreateStaticFields ();
181                         AddApplicationAndSessionObjects ();
182                         AddScripts ();
183                         CreateMethods ();
184                         CreateConstructor (null, null);
185                 }
186
187 #if NET_2_0
188                 internal CodeDomProvider Provider {
189                         get { return provider; }
190                 }
191
192                 internal CodeCompileUnit CompileUnit {
193                         get { return unit; }
194                 }
195 #endif
196                 protected virtual void CreateStaticFields ()
197                 {
198                         CodeMemberField fld = new CodeMemberField (typeof (bool), "__initialized");
199                         fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
200                         fld.InitExpression = new CodePrimitiveExpression (false);
201                         mainClass.Members.Add (fld);
202                 }
203
204 #if NET_2_0
205                 void AssignAppRelativeVirtualPath (CodeConstructor ctor)
206                 {
207                         Type baseType = parser.CodeFileBaseClassType;
208
209                         if (baseType == null)
210                                 baseType = parser.BaseType;
211                         if (baseType == null)
212                                 return;
213                         if (!baseType.IsSubclassOf (typeof (System.Web.UI.TemplateControl)))
214                                 return;
215                         
216                         string arvp = Path.Combine (parser.BaseVirtualDir, Path.GetFileName (parser.InputFile));
217                         if (VirtualPathUtility.IsAbsolute (arvp))
218                                 arvp = "~" + arvp;
219                         
220                         CodeExpression cast = new CodeCastExpression (baseType, new CodeThisReferenceExpression ());
221                         CodePropertyReferenceExpression arvpProp = new CodePropertyReferenceExpression (cast, "AppRelativeVirtualPath");
222                         CodeAssignStatement arvpAssign = new CodeAssignStatement ();
223                         arvpAssign.Left = arvpProp;
224                         arvpAssign.Right = new CodePrimitiveExpression (arvp);
225                         ctor.Statements.Add (arvpAssign);
226                 }
227 #endif
228                 
229                 protected virtual void CreateConstructor (CodeStatementCollection localVars,
230                                                           CodeStatementCollection trueStmt)
231                 {
232                         CodeConstructor ctor = new CodeConstructor ();
233                         ctor.Attributes = MemberAttributes.Public;
234                         mainClass.Members.Add (ctor);
235
236 #if NET_2_0
237                         AssignAppRelativeVirtualPath (ctor);
238 #endif
239                         if (localVars != null)
240                                 ctor.Statements.AddRange (localVars);
241
242                         CodeTypeReferenceExpression r;
243 #if NET_2_0
244                         if (parser.IsPartial)
245                                 r = new CodeTypeReferenceExpression (mainClass.Name);
246                         else
247 #endif
248                         r = new CodeTypeReferenceExpression (mainNS.Name + "." + mainClass.Name);
249                         CodeFieldReferenceExpression initialized;
250                         initialized = new CodeFieldReferenceExpression (r, "__initialized");
251                         
252                         CodeBinaryOperatorExpression bin;
253                         bin = new CodeBinaryOperatorExpression (initialized,
254                                                                 CodeBinaryOperatorType.ValueEquality,
255                                                                 new CodePrimitiveExpression (false));
256
257                         CodeAssignStatement assign = new CodeAssignStatement (initialized,
258                                                                               new CodePrimitiveExpression (true));
259
260                         CodeConditionStatement cond = new CodeConditionStatement (bin, assign);
261                         if (trueStmt != null)
262                                 cond.TrueStatements.AddRange (trueStmt);
263                         
264                         ctor.Statements.Add (cond);
265                 }
266                 
267                 void AddScripts ()
268                 {
269                         if (parser.Scripts == null || parser.Scripts.Count == 0)
270                                 return;
271
272                         foreach (object o in parser.Scripts) {
273                                 if (o is string)
274                                         mainClass.Members.Add (new CodeSnippetTypeMember ((string) o));
275                         }
276                 }
277                 
278                 protected internal virtual void CreateMethods ()
279                 {
280                 }
281
282 #if NET_2_0
283                 void InternalCreatePageProperty (string retType, string name, string contextProperty)
284                 {
285                         CodeMemberProperty property = new CodeMemberProperty ();
286                         property.Name = name;
287                         property.Type = new CodeTypeReference (retType);
288                         property.Attributes = MemberAttributes.Family | MemberAttributes.Final;
289
290                         CodeMethodReturnStatement ret = new CodeMethodReturnStatement ();
291                         CodeCastExpression cast = new CodeCastExpression ();
292                         ret.Expression = cast;
293                         
294                         CodePropertyReferenceExpression refexp = new CodePropertyReferenceExpression ();
295                         refexp.TargetObject = new CodePropertyReferenceExpression (new CodeThisReferenceExpression (), "Context");
296                         refexp.PropertyName = contextProperty;
297                         
298                         cast.TargetType = new CodeTypeReference (retType);
299                         cast.Expression = refexp;
300                         
301                         property.GetStatements.Add (ret);
302                         if (partialClass == null)
303                                 mainClass.Members.Add (property);
304                         else
305                                 partialClass.Members.Add (property);
306                 }
307                 
308                 protected void CreateProfileProperty ()
309                 {
310                         string retType;
311                         if (AppCodeCompiler.HaveCustomProfile (WebConfigurationManager.GetSection ("system.web/profile") as ProfileSection))
312                                 retType = "ProfileCommon";
313                         else
314                                 retType = "System.Web.Profile.DefaultProfile";
315                         InternalCreatePageProperty (retType, "Profile", "Profile");
316                 }
317 #endif
318                 
319                 protected virtual void AddInterfaces ()
320                 {
321                         if (parser.Interfaces == null)
322                                 return;
323
324                         foreach (object o in parser.Interfaces) {
325                                 if (o is string)
326                                         mainClass.BaseTypes.Add (new CodeTypeReference ((string) o));
327                         }
328                 }
329
330                 protected virtual void AddClassAttributes ()
331                 {
332                 }
333                 
334                 protected virtual void AddApplicationAndSessionObjects ()
335                 {
336                 }
337
338                 /* Utility methods for <object> stuff */
339                 protected void CreateApplicationOrSessionPropertyForObject (Type type,
340                                                                             string propName,
341                                                                             bool isApplication,
342                                                                             bool isPublic)
343                 {
344                         /* if isApplication this generates (the 'cachedapp' field is created earlier):
345                         private MyNS.MyClass app {
346                                 get {
347                                         if ((this.cachedapp == null)) {
348                                                 this.cachedapp = ((MyNS.MyClass)
349                                                         (this.Application.StaticObjects.GetObject("app")));
350                                         }
351                                         return this.cachedapp;
352                                 }
353                         }
354
355                         else, this is for Session:
356                         private MyNS.MyClass ses {
357                                 get {
358                                         return ((MyNS.MyClass) (this.Session.StaticObjects.GetObject("ses")));
359                                 }
360                         }
361
362                         */
363
364                         CodeExpression result = null;
365
366                         CodeMemberProperty prop = new CodeMemberProperty ();
367                         prop.Type = new CodeTypeReference (type);
368                         prop.Name = propName;
369                         if (isPublic)
370                                 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
371                         else
372                                 prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
373
374                         CodePropertyReferenceExpression p1;
375                         if (isApplication)
376                                 p1 = new CodePropertyReferenceExpression (thisRef, "Application");
377                         else
378                                 p1 = new CodePropertyReferenceExpression (thisRef, "Session");
379
380                         CodePropertyReferenceExpression p2;
381                         p2 = new CodePropertyReferenceExpression (p1, "StaticObjects");
382
383                         CodeMethodReferenceExpression getobject;
384                         getobject = new CodeMethodReferenceExpression (p2, "GetObject");
385
386                         CodeMethodInvokeExpression invoker;
387                         invoker = new CodeMethodInvokeExpression (getobject,
388                                                 new CodePrimitiveExpression (propName));
389
390                         CodeCastExpression cast = new CodeCastExpression (prop.Type, invoker);
391
392                         if (isApplication) {
393                                 CodeFieldReferenceExpression field;
394                                 field = new CodeFieldReferenceExpression (thisRef, "cached" + propName);
395
396                                 CodeConditionStatement stmt = new CodeConditionStatement();
397                                 stmt.Condition = new CodeBinaryOperatorExpression (field,
398                                                         CodeBinaryOperatorType.IdentityEquality,
399                                                         new CodePrimitiveExpression (null));
400
401                                 CodeAssignStatement assign = new CodeAssignStatement ();
402                                 assign.Left = field;
403                                 assign.Right = cast;
404                                 stmt.TrueStatements.Add (assign);
405                                 prop.GetStatements.Add (stmt);
406                                 result = field;
407                         } else {
408                                 result = cast;
409                         }
410                                                 
411                         prop.GetStatements.Add (new CodeMethodReturnStatement (result));
412                         mainClass.Members.Add (prop);
413                 }
414
415                 protected string CreateFieldForObject (Type type, string name)
416                 {
417                         string fieldName = "cached" + name;
418                         CodeMemberField f = new CodeMemberField (type, fieldName);
419                         f.Attributes = MemberAttributes.Private;
420                         mainClass.Members.Add (f);
421                         return fieldName;
422                 }
423
424                 protected void CreatePropertyForObject (Type type, string propName, string fieldName, bool isPublic)
425                 {
426                         CodeFieldReferenceExpression field = new CodeFieldReferenceExpression (thisRef, fieldName);
427                         CodeMemberProperty prop = new CodeMemberProperty ();
428                         prop.Type = new CodeTypeReference (type);
429                         prop.Name = propName;
430                         if (isPublic)
431                                 prop.Attributes = MemberAttributes.Public | MemberAttributes.Final;
432                         else
433                                 prop.Attributes = MemberAttributes.Private | MemberAttributes.Final;
434
435                         CodeConditionStatement stmt = new CodeConditionStatement();
436                         stmt.Condition = new CodeBinaryOperatorExpression (field,
437                                                 CodeBinaryOperatorType.IdentityEquality,
438                                                 new CodePrimitiveExpression (null));
439
440                         CodeObjectCreateExpression create = new CodeObjectCreateExpression (prop.Type); 
441                         stmt.TrueStatements.Add (new CodeAssignStatement (field, create));
442                         prop.GetStatements.Add (stmt);
443                         prop.GetStatements.Add (new CodeMethodReturnStatement (field));
444
445                         mainClass.Members.Add (prop);
446                 }
447                 /******/
448
449                 void CheckCompilerErrors (CompilerResults results)
450                 {
451                         if (results.NativeCompilerReturnValue == 0)
452                                 return;
453
454                         string fileText = null;
455                         CompilerErrorCollection errors = results.Errors;
456                         CompilerError ce = (errors != null && errors.Count > 0) ? errors [0] : null;
457                         string inFile = (ce != null) ? ce.FileName : null;
458                         
459                         if (inFile != null && File.Exists (inFile)) {
460                                 using (StreamReader sr = File.OpenText (inFile)) {
461                                         fileText = sr.ReadToEnd ();
462                                 }
463                         } else {
464                                 StringWriter writer = new StringWriter();
465                                 provider.CreateGenerator().GenerateCodeFromCompileUnit (unit, writer, null);
466                                 fileText = writer.ToString ();
467                         }
468                         throw new CompilationException (parser.InputFile, errors, fileText);
469                 }
470
471                 protected string DynamicDir ()
472                 {
473                         return AppDomain.CurrentDomain.SetupInformation.DynamicBase;
474                 }
475
476                 [MonoTODO ("find out how to extract the warningLevel and compilerOptions in the <system.codedom> case")]
477                 public virtual Type GetCompiledType () 
478                 {
479                         Type type = CachingCompiler.GetTypeFromCache (parser.InputFile);
480                         if (type != null)
481                                 return type;
482
483                         Init ();
484                         string lang = parser.Language;
485 #if NET_2_0
486                         CompilationSection config = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
487                         Compiler comp = config.Compilers[lang];
488
489                         string compilerOptions = "";
490                         int warningLevel = 0;
491
492                         if (comp == null) {
493                                 CompilerInfo info = CodeDomProvider.GetCompilerInfo (lang);
494                                 if (info != null && info.IsCodeDomProviderTypeValid)
495                                         provider = info.CreateProvider ();
496
497                                 // XXX there's no way to get
498                                 // warningLevel or compilerOptions out
499                                 // of the provider.. they're in the
500                                 // configuration section, though.
501                         }
502                         else {
503                                 Type t = Type.GetType (comp.Type, true);
504                                 provider = Activator.CreateInstance (t) as CodeDomProvider;
505
506                                 compilerOptions = comp.CompilerOptions;
507                                 warningLevel = comp.WarningLevel;
508                         }
509
510 #else
511                         CompilationConfiguration config;
512
513                         config = CompilationConfiguration.GetInstance (parser.Context);
514                         provider = config.GetProvider (lang);
515
516                         string compilerOptions = config.GetCompilerOptions (lang);
517                         int warningLevel = config.GetWarningLevel (lang);
518 #endif
519                         if (provider == null)
520                                 throw new HttpException ("Configuration error. Language not supported: " +
521                                                           lang, 500);
522
523                         compiler = provider.CreateCompiler ();
524
525                         compilerParameters.IncludeDebugInformation = parser.Debug;
526                         compilerParameters.CompilerOptions = compilerOptions + " " + parser.CompilerOptions;
527
528                         compilerParameters.WarningLevel = warningLevel;
529                         bool keepFiles = (Environment.GetEnvironmentVariable ("MONO_ASPNET_NODELETE") != null);
530
531                         string tempdir = config.TempDirectory;
532                         if (tempdir == null || tempdir == "")
533                                 tempdir = DynamicDir ();
534                                 
535                         TempFileCollection tempcoll = new TempFileCollection (tempdir, keepFiles);
536                         compilerParameters.TempFiles = tempcoll;
537                         string dllfilename = Path.GetFileName (tempcoll.AddExtension ("dll", true));
538                         compilerParameters.OutputAssembly = Path.Combine (DynamicDir (), dllfilename);
539
540                         CompilerResults results = CachingCompiler.Compile (this);
541                         CheckCompilerErrors (results);
542                         Assembly assembly = results.CompiledAssembly;
543                         if (assembly == null) {
544                                 if (!File.Exists (compilerParameters.OutputAssembly)) {
545                                         results.TempFiles.Delete ();
546                                         throw new CompilationException (parser.InputFile, results.Errors,
547                                                 "No assembly returned after compilation!?");
548                                 }
549
550                                 assembly = Assembly.LoadFrom (compilerParameters.OutputAssembly);
551                         }
552
553                         results.TempFiles.Delete ();
554                         Type mainClassType = assembly.GetType (mainClassExpr.Type.BaseType, true);
555
556 #if NET_2_0
557                         if (parser.IsPartial) {
558                                 // With the partial classes, we need to make sure we
559                                 // don't have any methods that should have not been
560                                 // created (because they are accessible from the base
561                                 // types). We cannot do this normally because the
562                                 // codebehind file is actually a partial class and we
563                                 // have no way of identifying the partial class' base
564                                 // type until now.
565                                 if (!isRebuilding && CheckPartialBaseType (mainClassType)) {
566                                         isRebuilding = true;
567                                         parser.RootBuilder.ResetState ();
568                                         return GetCompiledType ();
569                                 }
570                         }
571 #endif
572
573                         return mainClassType;
574                 }
575
576 #if NET_2_0
577                 internal bool IsRebuildingPartial
578                 {
579                         get { return isRebuilding; }
580                 }
581
582                 internal bool CheckPartialBaseType (Type type)
583                 {
584                         // Get the base type. If we don't have any (bad thing), we
585                         // don't need to replace ourselves. Also check for the
586                         // core file, since that won't have any either.
587                         Type baseType = type.BaseType;
588                         if (baseType == null || baseType == typeof(System.Web.UI.Page))
589                                 return false;
590
591                         bool rebuild = false;
592
593                         if (CheckPartialBaseFields (type, baseType))
594                                 rebuild = true;
595
596                         if (CheckPartialBaseProperties (type, baseType))
597                                 rebuild = true;
598
599                         return rebuild;
600                 }
601
602                 internal bool CheckPartialBaseFields (Type type, Type baseType)
603                 {
604                         bool rebuild = false;
605
606                         foreach (FieldInfo baseInfo in baseType.GetFields (replaceableFlags)) {
607                                 if (baseInfo.IsPrivate)
608                                         continue;
609
610                                 FieldInfo typeInfo = type.GetField (baseInfo.Name, replaceableFlags);
611
612                                 if (typeInfo != null && typeInfo.DeclaringType == type) {
613                                         partialNameOverride [typeInfo.Name] = true;
614                                         rebuild = true;
615                                 }
616                         }
617
618                         return rebuild;
619                 }
620
621                 internal bool CheckPartialBaseProperties (Type type, Type baseType)
622                 {
623                         bool rebuild = false;
624
625                         foreach (PropertyInfo baseInfo in baseType.GetProperties ()) {
626                                 PropertyInfo typeInfo = type.GetProperty (baseInfo.Name);
627
628                                 if (typeInfo != null && typeInfo.DeclaringType == type) {
629                                         partialNameOverride [typeInfo.Name] = true;
630                                         rebuild = true;
631                                 }
632                         }
633
634                         return rebuild;
635                 }
636 #endif
637
638                 internal CompilerParameters CompilerParameters {
639                         get { return compilerParameters; }
640                 }
641
642                 internal CodeCompileUnit Unit {
643                         get { return unit; }
644                 }
645
646                 internal virtual ICodeCompiler Compiler {
647                         get { return compiler; }
648                 }
649
650                 internal TemplateParser Parser {
651                         get { return parser; }
652                 }
653         }
654 }
655