2 // driver.cs: Walks the AST from a JScript program, and generates CIL opcodes.
4 // Author: Cesar Octavio Lopez Nataren <cesar@ciencias.unam.mx>
7 namespace Microsoft.JScript
11 using System.Collections;
12 using System.Reflection.Emit;
13 using System.Reflection;
14 using System.Runtime.CompilerServices;
18 public Hashtable variables = new Hashtable ();
19 public ILGenerator ig;
20 public TypeBuilder type;
29 AssemblyName assemblyName;
30 AssemblyBuilder assemblyBuilder;
31 ModuleBuilder moduleBuilder;
32 MethodBuilder methodBuilder;
38 string JSCRIPT_MODULE = "Jscript Module";
40 public Jsc (string output)
44 assemblyName = new AssemblyName ();
46 assemblyName.Name = basename;
48 assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (assemblyName,
49 AssemblyBuilderAccess.RunAndSave, ".");
50 // FIXME: hard coded ".exe" extension
51 moduleBuilder = assemblyBuilder.DefineDynamicModule (JSCRIPT_MODULE, basename + ".exe", false);
53 context = new Context ();
57 public void GetAST (string filename)
59 StreamReader reader = new StreamReader (filename);
60 JScriptLexer lexer = new JScriptLexer (reader);
61 JScriptParser parser = new JScriptParser (lexer);
63 mainProgram = new Program ();
64 parser.program (mainProgram);
68 private void EmitJScript0Type ()
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 [] {}));
76 private void EmitJScript0Cons ()
78 ConstructorBuilder constructor;
79 constructor = context.type.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard,
80 new Type [] {typeof (GlobalScope)});
82 context.ig = constructor.GetILGenerator ();
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);
95 private void EmitGlobalCode ()
97 methodBuilder = context.type.DefineMethod ("Global Code",
98 MethodAttributes.Public,
102 context.ig = methodBuilder.GetILGenerator ();
104 context.ig.Emit (OpCodes.Ldarg_0);
106 context.ig.Emit (OpCodes.Ldfld,
107 typeof (ScriptObject).GetField ("engine"));
109 context.ig.Emit (OpCodes.Ldarg_0);
111 context.ig.Emit (OpCodes.Call,
112 typeof (Microsoft.JScript.Vsa.VsaEngine).GetMethod ("PushScriptObject", new Type [] {typeof (Microsoft.JScript.ScriptObject)}));
115 int size = mainProgram.SourceElements.Size;
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);
123 context.ig.Emit (OpCodes.Ldsfld,
124 typeof (Microsoft.JScript.Empty).GetField ("Value"));
126 context.ig.Emit (OpCodes.Ldarg_0);
128 context.ig.Emit (OpCodes.Ldfld,
129 typeof (ScriptObject).GetField ("engine"));
131 context.ig.Emit (OpCodes.Call,
132 typeof (Microsoft.JScript.Vsa.VsaEngine).GetMethod ("PopScriptObject"));
134 context.ig.Emit (OpCodes.Pop);
136 context.ig.Emit (OpCodes.Ret);
140 private void EmitJScript0 ()
146 Type t = context.type.CreateType ();
151 private void EmitJScriptMainType ()
153 context.type = moduleBuilder.DefineType ("JScript Main", TypeAttributes.Public);
154 context.type.SetParent (typeof (System.Object));
157 private void EmitJScriptMainCons ()
159 // constructor for JScript Main
160 ConstructorBuilder constructor;
161 constructor = context.type.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard,
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);
171 private void EmitJScriptMainFunction ()
173 // define Main for JScript Main
174 MethodBuilder methodBuilder;
175 methodBuilder = context.type.DefineMethod ("Main",
176 MethodAttributes.Public | MethodAttributes.Static,
178 new Type [] {typeof (String [])});
180 methodBuilder.SetCustomAttribute (new CustomAttributeBuilder
181 (typeof (STAThreadAttribute).GetConstructor (new Type [] {}),
185 context.ig = methodBuilder.GetILGenerator ();
187 // declare local vars
188 context.ig.DeclareLocal (typeof (Microsoft.JScript.GlobalScope));
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 [])}));
201 context.ig.Emit (OpCodes.Stloc_0);
202 context.ig.Emit (OpCodes.Ldloc_0);
205 context.ig.Emit (OpCodes.Newobj,
206 assemblyBuilder.GetType ("JScript 0").GetConstructor (new Type [] {typeof (Microsoft.JScript.GlobalScope)}));
208 context.ig.Emit (OpCodes.Call, assemblyBuilder.GetType ("JScript 0").GetMethod ("Global Code", new Type [] {}));
210 context.ig.Emit (OpCodes.Pop);
211 context.ig.Emit (OpCodes.Ret);
213 assemblyBuilder.SetEntryPoint (methodBuilder);
217 private void EmitJScriptMain ()
219 EmitJScriptMainType ();
220 EmitJScriptMainCons ();
221 EmitJScriptMainFunction ();
223 Type t2 = context.type.CreateType ();
227 public void Emit (string outputFile)
231 assemblyBuilder.Save (outputFile);
234 public static void Main (string [] args)
237 string basename = Path.GetFileNameWithoutExtension (args [0]);
238 Jsc compiler = new Jsc (basename);
239 compiler.GetAST (args [0]);
240 // compiler.Emit (compiler.basename + ".exe");
242 } catch (IndexOutOfRangeException) {
243 Console.WriteLine ("Usage: [mono] mjsc.exe filename.js");