Index: Microsoft.JScript/expression.cs =================================================================== --- Microsoft.JScript/expression.cs (revision 51911) +++ Microsoft.JScript/expression.cs (working copy) @@ -235,6 +235,7 @@ internal bool assign, late_bind = false; internal AST right_side; + MemberInfo externTypeInfo = null; internal Binary (AST parent, AST left, JSToken op, Location location) : this (parent, left, null, op, location) @@ -282,7 +283,7 @@ found &= left.Resolve (env); if (right != null) if (op == JSToken.AccessField && right is IAccessible) { - found &= ((IAccessible) right).ResolveFieldAccess (left); + found &= ((IAccessible) right).ResolveFieldAccess (left, env, out externTypeInfo); if (!found) late_bind = true; } else @@ -308,8 +309,10 @@ } internal MemberInfo Binding { - get { - return SemanticAnalyser.get_member (left, right); + get { + if (externTypeInfo == null) + return SemanticAnalyser.get_member (left, right); + return externTypeInfo; } } @@ -768,6 +771,11 @@ binding = bin.Binding; if (binding is MethodInfo) NeedThis ((MethodInfo) binding); + else { + // Console.WriteLine ("binding = {0}", binding); + // if (binding == null) + // throw new Exception ("needs to assign the binding"); + } } else r &= member_exp.Resolve (env); @@ -862,6 +870,7 @@ args.Emit (ec); MethodInfo method = (MethodInfo) minfo; ig.Emit (OpCodes.Call, method); + no_effect = method.ReturnType != typeof (void); Type return_type = method.ReturnType; if (return_type != typeof (void) && return_type != typeof (string)) ig.Emit (OpCodes.Box, return_type); @@ -1207,7 +1216,7 @@ } interface IAccessible { - bool ResolveFieldAccess (AST parent); + bool ResolveFieldAccess (AST parent, Environment env, out MemberInfo externTypeInfo); } internal interface ICanLookupPrototype { @@ -1220,7 +1229,12 @@ internal AST binding; internal bool assign; AST right_side; - + + internal ExternalType external_type = null; + internal ExternalType ExternalType { + get { return external_type; } + } + int lexical_difference; const int MINIMUM_DIFFERENCE = 1; bool no_field; @@ -1259,7 +1273,10 @@ env.Enter (String.Empty, Symbol.CreateSymbol (decl.id), decl); SemanticAnalyser.AddMethodVarsUsedNested (decl.GetContainerFunction.func_obj.name, decl); } - } + } else if (binding is ExternalType) + external_type = (ExternalType) binding; + else + throw new Exception (binding.GetType ().ToString ()); } else if (SemanticAnalyser.NoFast) { undeclared = true; Console.WriteLine ("warning JS1135: Variable '" + name + "' has not been declared"); @@ -1297,12 +1314,18 @@ // Returns false if parent is not a native object, // this indicate that late binding code must get generated. // - public bool ResolveFieldAccess (AST parent) + public bool ResolveFieldAccess (AST parent, Environment env, out MemberInfo externalTypeInfo) { if (parent is Identifier) { Identifier p = parent as Identifier; - return is_static_property (p.name.Value, name.Value); + object binding = env.Get (String.Empty, p.name); + // Console.WriteLine ("binding = {0}", binding.GetType ()); + ExternalType externalType = null; + if (binding is ExternalType) + externalType = (ExternalType) binding; + return is_static_property (p.name.Value, name.Value, externalType, out externalTypeInfo); } + externalTypeInfo = null; // // Return false so late binding will take place // @@ -1313,20 +1336,33 @@ // If obj_name is a native object, search in its // constructor if contains a prop_name, otherwise return // false letting late binding taking place + // If externType is not null, resolve the property via Reflection // - bool is_static_property (string obj_name, string prop_name) + bool is_static_property (string obj_name, string prop_name, ExternalType externalType, out MemberInfo externalTypeInfo) { - bool native_obj = SemanticAnalyser.is_js_object (obj_name); + bool contains = false; - if (!native_obj) - return false; + if (externalType == null) { + externalTypeInfo = null; + bool native_obj = SemanticAnalyser.is_js_object (obj_name); - bool contains_method; - contains_method = SemanticAnalyser.object_contains ( - SemanticAnalyser.map_to_ctr (obj_name), LateBinding.MapToInternalName (prop_name)); - if (!contains_method) - throw new Exception ("error: JS0438: Object " + obj_name + " doesn't support this property or method:" + prop_name); - return true; + if (!native_obj) + return false; + + contains = SemanticAnalyser.object_contains (SemanticAnalyser.map_to_ctr (obj_name), + LateBinding.MapToInternalName (prop_name)); + } else { + Type extern_type = externalType.Type; + MemberInfo [] members = extern_type.GetMember (prop_name, BindingFlags.Static | BindingFlags.Public); + contains = members != null; + if (contains) + externalTypeInfo = members [0]; + else + externalTypeInfo = null; + } + if (contains) + return true; + throw new Exception ("error: JS0438: Object " + obj_name + " doesn't support this property or method:" + prop_name); } internal override void Emit (EmitContext ec) @@ -1380,7 +1416,7 @@ emit_undeclared_use (ig); } } else - Console.WriteLine ("Identifier.Emit, binding.GetType = {0}", binding.GetType ()); + // Console.WriteLine ("Identifier.Emit, binding.GetType = {0}", binding.GetType ()); if (!assign && no_effect && !undeclared) ig.Emit (OpCodes.Pop); @@ -2114,6 +2150,7 @@ AST exp; Args args; bool late_bind = false; + ConstructorInfo ctr_info = null; internal New (AST parent, AST exp, Location location) : base (parent, location) @@ -2131,11 +2168,24 @@ { bool r = true; + exp.Resolve (env); + if (exp != null && exp.GetType () == typeof (Identifier)) { Identifier id = (Identifier) exp; - late_bind = !SemanticAnalyser.is_js_object (id.name.Value); - } - exp.Resolve (env); + if (id.ExternalType == null) { + Console.WriteLine ("late_bind will happen on New"); + late_bind = !SemanticAnalyser.is_js_object (id.name.Value); + } else { + Type type = id.ExternalType.Type; + int size = args.Size; + ConstructorInfo [] ctrs = type.GetConstructors (); + ParameterInfo [][] params_info = new ParameterInfo [ctrs.Length][]; + int i = 0; + foreach (ConstructorInfo ctr in ctrs) + if (ctr.GetParameters ().Length == size) + ctr_info = ctr; + } + } if (args != null) { args.InNew = true; @@ -2172,6 +2222,10 @@ CodeGenerator.load_engine (InFunction, ig); ig.Emit (OpCodes.Call, typeof (LateBinding).GetMethod ("CallValue")); + } else if (ctr_info != null) { + for (int i = 0; i < args.Size; i++) + args.get_element (i).Emit (ec); + ig.Emit (OpCodes.Newobj, ctr_info); } else { if (exp != null) exp.Emit (ec); Index: Microsoft.JScript/IdentificationTable.cs =================================================================== --- Microsoft.JScript/IdentificationTable.cs (revision 51911) +++ Microsoft.JScript/IdentificationTable.cs (working copy) @@ -351,7 +351,35 @@ if (symbols == null) return false; - return symbols.Contains (key); + bool contained = symbols.Contains (key); + if (contained) + return true; + + // + // Assembly type lookup through reflection + // + Assembly [] assemblies = SemanticAnalyser.Assemblies; + Type found_type = null; + + foreach (Assembly asm in assemblies) { + foreach (string @namespace in SemanticAnalyser.ImportedNamespaces.Keys) { + Type t = asm.GetType (@namespace + "." + key.Value); + if (t == null) + continue; + + TypeAttributes ta = t.Attributes & TypeAttributes.VisibilityMask; + if (ta != TypeAttributes.NotPublic && ta != TypeAttributes.NestedPrivate && + ta != TypeAttributes.NestedAssembly && ta != TypeAttributes.NestedFamANDAssem) { + if (found_type == null) { + found_type = t; + Enter (String.Empty, key, new ExternalType (key.Value, t)); + break; + } + } + } + break; + } + return found_type != null; } internal object Get (string ns, Symbol key) Index: Microsoft.JScript/Import.cs =================================================================== --- Microsoft.JScript/Import.cs (revision 51911) +++ Microsoft.JScript/Import.cs (working copy) @@ -55,7 +55,15 @@ "error JS1229: The import statement is not valid in this context"; throw new Exception (err); } - return Mono.CSharp.Namespace.IsNamespace (name); + + bool ns_found = Mono.CSharp.Namespace.IsNamespace (name); + + if (ns_found) + SemanticAnalyser.AddNamespace (name); + else + throw new Exception (Location.SourceName + " (" + Location.LineNumber + ",0) error : " + "Namespace '" + name + "' not found"); + + return ns_found; } internal override void Emit (EmitContext ec) Index: Microsoft.JScript/Parser.cs =================================================================== --- Microsoft.JScript/Parser.cs (revision 51911) +++ Microsoft.JScript/Parser.cs (working copy) @@ -376,7 +376,7 @@ // FIXME, research about createExprStatement if (ft != FunctionType.Expression) - ; + throw new NotImplementedException (); } return pn; } Index: Microsoft.JScript/SemanticAnalizer.cs =================================================================== --- Microsoft.JScript/SemanticAnalizer.cs (revision 51911) +++ Microsoft.JScript/SemanticAnalizer.cs (working copy) @@ -48,6 +48,11 @@ internal static Hashtable methods_with_outter_scope_refs = new Hashtable (); internal static Hashtable methods_with_vars_used_nested = new Hashtable (); internal static Environment Ocurrences = new Environment (); + + private static Hashtable imported_ns = new Hashtable (); + internal static Hashtable ImportedNamespaces { + get { return imported_ns; } + } // // Type to GlobalObject @@ -55,7 +60,11 @@ private static Type global_obj = typeof (GlobalObject); internal static bool NoFast = true; + private static Assembly [] assemblies; + internal static Assembly [] Assemblies { + get { return assemblies; } + } private static readonly string global_namespace = String.Empty; internal static string GlobalNamespace { @@ -419,5 +428,40 @@ } } } + + internal static void AddNamespace (string ns) + { + imported_ns.Add (ns, ns); + } } + + // + // Represents a type from the bcl (base class library) or another assembly + // + internal class ExternalType : AST { + + string name; + Type type; + + internal Type Type { + get { return type; } + } + + internal ExternalType (string name, Type type) + : base (null, null) + { + this.name = name; + this.type = type; + } + + internal override bool Resolve (Environment env) + { + throw new NotImplementedException (); + } + + internal override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + } }