//
using System;
+using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
internal static AssemblyBuilder assembly_builder;
internal static ModuleBuilder module_builder;
+ internal static string Basename (string name)
+ {
+ int pos = name.LastIndexOf ('/');
+
+ if (pos != -1)
+ return name.Substring (pos + 1);
+
+ pos = name.LastIndexOf ('\\');
+ if (pos != -1)
+ return name.Substring (pos + 1);
+
+ return name;
+ }
+
+ internal static string Dirname (string name)
+ {
+ int pos = name.LastIndexOf ('/');
+
+ if (pos != -1)
+ return name.Substring (0, pos);
+
+ pos = name.LastIndexOf ('\\');
+ if (pos != -1)
+ return name.Substring (0, pos);
+
+ return ".";
+ }
+
internal static void Init (string file_name)
{
app_domain = Thread.GetDomain ();
assembly_name = new AssemblyName ();
- assembly_name.Name = trim_extension (file_name);
-
+ assembly_name.Name = Path.GetFileNameWithoutExtension (file_name);
mod_name = MODULE;
assembly_builder = app_domain.DefineDynamicAssembly (
assembly_name,
- AssemblyBuilderAccess.RunAndSave);
+ AssemblyBuilderAccess.RunAndSave,
+ Dirname (file_name));
ConstructorInfo ctr_info = typeof (Microsoft.JScript.ReferenceAttribute).GetConstructor (new Type [] { typeof (string) });
// FIXME: find out which is the blob.
assembly_builder.SetCustomAttribute (ctr_info, blob);
module_builder = assembly_builder.DefineDynamicModule (
- mod_name,
- assembly_name.Name + ".exe",
- false);
+ mod_name,
+ Basename (assembly_name.Name + ".exe"),
+ false);
}
internal static string trim_extension (string file_name)
internal static void Save (string target_name)
{
- assembly_builder.Save (target_name);
+ assembly_builder.Save (CodeGenerator.Basename (target_name));
}
internal static void Emit (AST prog)
CodeGenerator.Save (trim_extension (file_name) + ".exe");
}
- internal static void fall_true (EmitContext ec, AST ast, Label lbl)
+ static void emit_default_case (EmitContext ec, AST ast, OpCode op, Label lbl)
+ {
+ ast.Emit (ec);
+ if (need_convert_to_boolean (ast))
+ emit_to_boolean (ast, ec.ig, 0);
+ ec.ig.Emit (op, lbl);
+ }
+
+ static void ft_binary_recursion (EmitContext ec, AST ast, Label lbl)
{
ILGenerator ig = ec.ig;
if (ast is Binary) {
Binary b = ast as Binary;
- switch (b.current_op) {
+ switch (b.op) {
case JSToken.LogicalOr:
Label ftLb = ig.DefineLabel ();
fall_false (ec, b.left, ftLb);
fall_true (ec, b.left, lbl);
fall_true (ec, b.right, lbl);
break;
+
+ case JSToken.LessThan:
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Conv_R8);
+ ig.Emit (OpCodes.Blt, lbl);
+ break;
}
- } else {
- ast.Emit (ec);
- if (need_convert_to_boolean (ast))
- emit_to_boolean (ast, ig, 0);
- ig.Emit (OpCodes.Brfalse, lbl);
}
}
- internal static void fall_false (EmitContext ec, AST ast, Label lbl)
+ static void ft_emit_equality (EmitContext ec, AST ast, Label lbl)
{
ILGenerator ig = ec.ig;
- if (ast is Binary) {
- Binary b = ast as Binary;
- switch (b.current_op) {
- case JSToken.LogicalOr:
- fall_false (ec, b.left, lbl);
- fall_false (ec, b.right, lbl);
- break;
- case JSToken.LogicalAnd:
- Label ftLb = ig.DefineLabel ();
- fall_true (ec, b.left, ftLb);
- fall_false (ec, b.right, lbl);
- ig.MarkLabel (ftLb);
- break;
- }
- } else {
- ast.Emit (ec);
- if (need_convert_to_boolean (ast))
- emit_to_boolean (ast, ig, 0);
+ Equality eq = ast as Equality;
+
+ switch (eq.op) {
+ case JSToken.NotEqual:
ig.Emit (OpCodes.Brtrue, lbl);
+ break;
+ case JSToken.Equal:
+ ig.Emit (OpCodes.Brfalse, lbl);
+ break;
+ }
+ }
+
+ internal static void fall_true (EmitContext ec, AST ast, Label lbl)
+ {
+ Type type = ast.GetType ();
+
+ if (type == typeof (Expression)) {
+ Expression exp = ast as Expression;
+ exp.Emit (ec);
+ AST last_exp = (AST) exp.exprs [exp.exprs.Count - 1];
+
+ if (last_exp is Binary)
+ ft_binary_recursion (ec, last_exp, lbl);
+ else if (last_exp is Equality)
+ ft_emit_equality (ec, last_exp, lbl);
+ } else if (type == typeof (Binary))
+ ft_binary_recursion (ec, ast, lbl);
+ else
+ emit_default_case (ec, ast, OpCodes.Brfalse, lbl);
+ }
+
+ static void ff_emit_relational (EmitContext ec, AST ast, Label lbl)
+ {
+ ILGenerator ig = ec.ig;
+ Relational r = ast as Relational;
+ r.Emit (ec);
+
+ switch (r.op) {
+ case JSToken.LessThan:
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Conv_R8);
+ ig.Emit (OpCodes.Blt, lbl);
+ break;
+ }
+ }
+
+ static void ff_binary_recursion (EmitContext ec, AST ast, Label lbl)
+ {
+ ILGenerator ig = ec.ig;
+ Binary b = ast as Binary;
+
+ switch (b.op) {
+ case JSToken.LogicalOr:
+ fall_false (ec, b.left, lbl);
+ fall_false (ec, b.right, lbl);
+ break;
+
+ case JSToken.LogicalAnd:
+ Label ftLb = ig.DefineLabel ();
+ fall_true (ec, b.left, ftLb);
+ fall_false (ec, b.right, lbl);
+ ig.MarkLabel (ftLb);
+ break;
+ }
+ }
+
+ static void ff_emit_equality_cond (EmitContext ec, AST ast, Label lbl)
+ {
+ ILGenerator ig = ec.ig;
+ Equality eq = ast as Equality;
+ eq.Emit (ec);
+
+ switch (eq.op) {
+ case JSToken.NotEqual:
+ case JSToken.Equal:
+ ig.Emit (OpCodes.Brfalse, lbl);
+ break;
}
}
+
+ internal static void fall_false (EmitContext ec, AST ast, Label lbl)
+ {
+ Type type = ast.GetType ();
- internal static void emit_to_boolean (AST ast, ILGenerator ig, int i)
+ if (type == typeof (Expression)) {
+ Expression exp = ast as Expression;
+
+ if (exp.Size > 1)
+ exp.Emit (ec);
+
+ AST last_exp = (AST) exp.exprs [exp.exprs.Count - 1];
+
+ if (last_exp is Relational)
+ ff_emit_relational (ec, last_exp, lbl);
+ else if (last_exp is Binary)
+ ff_binary_recursion (ec, last_exp, lbl);
+ else if (last_exp is Identifier || last_exp is BooleanLiteral)
+ emit_default_case (ec, last_exp, OpCodes.Brtrue, lbl);
+ else if (last_exp is Equality)
+ ff_emit_equality_cond (ec, last_exp, lbl);
+ else {
+ Console.WriteLine ("fall_false, last_exp.GetType () == {0}", last_exp);
+ throw new Exception ("uknown type: " + last_exp.GetType ().ToString ());
+ }
+ } else if (type == typeof (Binary))
+ ff_binary_recursion (ec, ast, lbl);
+ else
+ emit_default_case (ec, ast, OpCodes.Brtrue, lbl);
+ }
+
+ internal static void emit_to_boolean (AST ast, ILGenerator ig, int i)
{
ig.Emit (OpCodes.Ldc_I4, i);
ig.Emit (OpCodes.Call, typeof (Convert).GetMethod ("ToBoolean",
} else
return false;
}
+
+ //
+ // Loads a current VsaEngine
+ //
+ internal static void load_engine (AST parent, ILGenerator ig)
+ {
+ //
+ // If we are in a function declaration at global level,
+ // we must load the engine associated to the current 'JScript N' instance,
+ // otherwise pick up the engine at second place in method's signature.
+ //
+ if (parent == null || parent.GetType () == typeof (ScriptBlock)) {
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, typeof (ScriptObject).GetField ("engine"));
+ } else if (parent != null && parent.GetType () == typeof (FunctionDeclaration ))
+ ig.Emit (OpCodes.Ldarg_1);
+ }
}
}