Added some files for the compiler's parsing phase (antlr generad files, and the gramm...
[mono.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / driver.cs
1 //
2 // driver.cs: Walks the AST from a JScript program, and generates CIL opcodes.
3 //
4 // Author: Cesar Octavio Lopez Nataren <cesar@ciencias.unam.mx>
5 //
6
7 namespace Microsoft.JScript
8 {
9         using System;
10         using System.IO;
11         using System.Collections;
12         using System.Reflection.Emit;
13         using System.Reflection;
14         using System.Runtime.CompilerServices;
15
16         public class Context
17         {
18                 public Hashtable variables = new Hashtable ();
19                 public ILGenerator ig;
20                 public TypeBuilder type;
21
22                 public Context ()
23                 {}
24         }
25         
26
27         public class Jsc 
28         {
29                 AssemblyName assemblyName;
30                 AssemblyBuilder assemblyBuilder;
31                 ModuleBuilder moduleBuilder;
32                 MethodBuilder methodBuilder;
33                 
34                 Context context;
35                 string basename;
36                 
37                 Program mainProgram;
38                 string JSCRIPT_MODULE = "Jscript Module";
39
40                 public Jsc (string output)
41                 {
42                         basename = output;
43                         
44                         assemblyName = new AssemblyName ();
45
46                         assemblyName.Name = basename;
47
48                         assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (assemblyName,
49                                                                                          AssemblyBuilderAccess.RunAndSave, ".");
50                         // FIXME: hard coded ".exe" extension
51                         moduleBuilder = assemblyBuilder.DefineDynamicModule (JSCRIPT_MODULE, basename + ".exe", false);
52                 
53                         context = new Context ();
54                 }
55
56
57                 public void  GetAST (string filename)
58                 {
59                         StreamReader reader = new StreamReader (filename);
60                         JScriptLexer lexer = new JScriptLexer (reader);
61                         JScriptParser parser = new JScriptParser (lexer);
62                         
63                         mainProgram = new Program ();
64                         parser.program (mainProgram);
65                 }
66
67
68                 private void EmitJScript0Type ()
69                 {
70                         context.type = moduleBuilder.DefineType ("JScript 0", TypeAttributes.Public | TypeAttributes.Class);
71                         context.type.SetParent (typeof (GlobalScope));
72                         context.type.SetCustomAttribute (new CustomAttributeBuilder
73                                                          (typeof (CompilerGlobalScopeAttribute).GetConstructor (new Type [] {}), new object [] {}));
74                 }
75
76                 private void EmitJScript0Cons ()
77                 {
78                         ConstructorBuilder constructor;
79                         constructor = context.type.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard,
80                                                                       new Type [] {typeof (GlobalScope)});
81                         
82                         context.ig = constructor.GetILGenerator ();
83                         
84                         context.ig.Emit (OpCodes.Ldarg_0);
85                         context.ig.Emit (OpCodes.Ldarg_1);
86                         context.ig.Emit (OpCodes.Dup);
87                         context.ig.Emit (OpCodes.Ldfld,
88                                          typeof (ScriptObject).GetField ("engine"));
89                         context.ig.Emit (OpCodes.Call, 
90                                          typeof (GlobalScope).GetConstructor (new Type [] {typeof (GlobalScope), typeof (Microsoft.JScript.Vsa.VsaEngine)}));
91                         context.ig.Emit (OpCodes.Ret);                          
92                 }
93
94
95                 private void EmitGlobalCode ()
96                 {
97                         methodBuilder = context.type.DefineMethod ("Global Code",
98                                                                    MethodAttributes.Public, 
99                                                                    typeof (object), 
100                                                                    null);
101                         
102                         context.ig = methodBuilder.GetILGenerator ();
103                         
104                         context.ig.Emit (OpCodes.Ldarg_0);
105                         
106                         context.ig.Emit (OpCodes.Ldfld,
107                                          typeof (ScriptObject).GetField ("engine"));
108                 
109                         context.ig.Emit (OpCodes.Ldarg_0);
110
111                         context.ig.Emit (OpCodes.Call, 
112                                          typeof (Microsoft.JScript.Vsa.VsaEngine).GetMethod ("PushScriptObject", new Type [] {typeof (Microsoft.JScript.ScriptObject)}));
113
114
115                         int size = mainProgram.SourceElements.Size;                     
116                         
117                         // Emit the statements from the program.
118                         for (int i = 0; i < size; i++) {                                
119                                 mainProgram.SourceElements.MoveNext ();
120                                 ((Statement) mainProgram.SourceElements.Current).Emit (context);
121                         }                       
122
123                         context.ig.Emit (OpCodes.Ldsfld, 
124                                          typeof (Microsoft.JScript.Empty).GetField ("Value"));
125
126                         context.ig.Emit (OpCodes.Ldarg_0);
127
128                         context.ig.Emit (OpCodes.Ldfld, 
129                                          typeof (ScriptObject).GetField ("engine"));
130
131                         context.ig.Emit (OpCodes.Call,
132                                          typeof (Microsoft.JScript.Vsa.VsaEngine).GetMethod ("PopScriptObject"));
133
134                         context.ig.Emit (OpCodes.Pop);
135
136                         context.ig.Emit (OpCodes.Ret);                 
137                 }
138
139
140                 private void EmitJScript0 ()
141                 {
142                         EmitJScript0Type ();
143                         EmitJScript0Cons ();
144                         EmitGlobalCode ();
145
146                         Type t = context.type.CreateType ();
147                 }
148
149
150
151                 private void EmitJScriptMainType ()
152                 {
153                         context.type = moduleBuilder.DefineType ("JScript Main", TypeAttributes.Public);
154                         context.type.SetParent (typeof (System.Object));
155                 }
156
157                 private void EmitJScriptMainCons ()
158                 {
159                         // constructor for JScript Main
160                         ConstructorBuilder constructor;
161                         constructor = context.type.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard,
162                                                                       new Type [] {});
163                         context.ig = constructor.GetILGenerator ();
164                         context.ig.Emit (OpCodes.Ldarg_0);
165                         context.ig.Emit (OpCodes.Call, 
166                                          typeof (Object).GetConstructor (new Type [] {}));
167                         context.ig.Emit (OpCodes.Ret);
168                 }
169                         
170
171                 private void EmitJScriptMainFunction ()
172                 {
173                         // define Main for JScript Main 
174                         MethodBuilder methodBuilder;
175                         methodBuilder = context.type.DefineMethod ("Main",
176                                                            MethodAttributes.Public | MethodAttributes.Static,
177                                                            typeof (void),
178                                                            new Type [] {typeof (String [])});
179                         
180                         methodBuilder.SetCustomAttribute (new CustomAttributeBuilder 
181                                                           (typeof (STAThreadAttribute).GetConstructor (new Type [] {}),
182                                                            new object [] {}));
183
184
185                         context.ig = methodBuilder.GetILGenerator ();
186
187                         // declare local vars
188                         context.ig.DeclareLocal (typeof (Microsoft.JScript.GlobalScope));
189
190                         context.ig.Emit (OpCodes.Ldc_I4_1);
191                         context.ig.Emit (OpCodes.Ldc_I4_1);
192                         context.ig.Emit (OpCodes.Newarr, typeof (string));
193                         context.ig.Emit (OpCodes.Dup);
194                         context.ig.Emit (OpCodes.Ldc_I4_0);
195                         context.ig.Emit (OpCodes.Ldstr,
196                                          "mscorlib, Version=1.0.3300.0, Culture=neutral, Pub" + "licKeyToken=b77a5c561934e089");
197                         context.ig.Emit (OpCodes.Stelem_Ref);
198                         context.ig.Emit (OpCodes.Call,
199                                          typeof (Microsoft.JScript.Vsa.VsaEngine).GetMethod  ("CreateEngineAndGetGlobalScope", new Type [] {typeof (bool), typeof (string [])}));
200                         
201                         context.ig.Emit (OpCodes.Stloc_0);
202                         context.ig.Emit (OpCodes.Ldloc_0);
203                         
204
205                         context.ig.Emit (OpCodes.Newobj,
206                                          assemblyBuilder.GetType ("JScript 0").GetConstructor (new Type [] {typeof (Microsoft.JScript.GlobalScope)})); 
207
208                         context.ig.Emit (OpCodes.Call, assemblyBuilder.GetType ("JScript 0").GetMethod ("Global Code", new Type [] {}));
209
210                         context.ig.Emit (OpCodes.Pop);
211                         context.ig.Emit (OpCodes.Ret);
212
213                         assemblyBuilder.SetEntryPoint (methodBuilder);
214
215                 }                       
216
217                 private void EmitJScriptMain ()
218                 {                       
219                         EmitJScriptMainType ();
220                         EmitJScriptMainCons ();
221                         EmitJScriptMainFunction ();
222
223                         Type t2 = context.type.CreateType ();
224                 }
225
226
227                 public void Emit (string outputFile)
228                 {
229                         EmitJScript0 ();
230                         EmitJScriptMain ();                                             
231                         assemblyBuilder.Save (outputFile);                      
232                 }
233
234                 public static void Main (string [] args)
235                 {
236                         try {                   
237                                 string basename = Path.GetFileNameWithoutExtension (args [0]);
238                                 Jsc compiler = new Jsc (basename);
239                                 compiler.GetAST (args [0]);                             
240                                 // compiler.Emit (compiler.basename + ".exe");
241                         
242                         } catch (IndexOutOfRangeException) {
243                                 Console.WriteLine ("Usage: [mono] mjsc.exe filename.js");
244                         }
245                 }
246         }
247 }