예제 #1
0
        public override void Visit(ImportSyntax pNode)
        {
            if (!_importPath.Contains(pNode.Path))
            {
                _importPath.Add(pNode.Path);
                var path = System.IO.Path.GetFullPath(System.IO.Path.Combine(_path, pNode.Path + ".dll"));

                Assembly asm = null;
                try
                {
                    asm = Assembly.LoadFile(path);
                }
                catch (Exception)
                {
                    Compiler.ReportError(CompilerErrorType.InvalidImport, pNode, pNode.Path);
                    return;
                }

                try
                {
                    System.IO.File.Copy(path, System.IO.Path.Combine(_path, System.IO.Path.GetFileName(path)), true);
                }
                catch (Exception)
                {
                    Compiler.ReportError("Unable to copy import to local directory");
                }

                //Import all types from the import
                //TODO move this to struct definition thing?
                foreach (var t in asm.GetTypes())
                {
                    if (t.IsValueType && t.IsPublic)
                    {
                        string prefix = "";
                        var    attr   = t.GetCustomAttributes <Emitting.TypePrefixAttribute>().SingleOrDefault();

                        //All exported types must have a TypePrefixAttribute in order to be imported
                        if (attr != null)
                        {
                            //
                            //Create type
                            //
                            prefix = attr.Prefix;

                            //Get any generic type parameters of the type
                            List <string> typeParameters = new List <string>();
                            if (t.IsGenericType)
                            {
                                var ga = t.GetGenericArguments();
                                for (int i = 0; i < ga.Length; i++)
                                {
                                    typeParameters.Add(ga[i].Name);
                                }
                            }
                            var st = SmallType.RegisterType(pNode.Alias, prefix, true, typeParameters);
                            st.SetSystemType(t);

                            foreach (var f in t.GetFields())
                            {
                                SmallType fieldType = null;
                                if (f.FieldType.IsGenericParameter)
                                {
                                    //If it's a generic type parameter, use the generic type
                                    foreach (var s in st.GenericTypeParameters)
                                    {
                                        if (s.Name.Equals(f.FieldType.Name, StringComparison.OrdinalIgnoreCase))
                                        {
                                            fieldType = s;
                                        }
                                    }
                                }
                                else
                                {
                                    fieldType = SmallType.FromSystemType(f.FieldType);
                                }

                                typeParameters.Clear();

                                //Get field type parameters
                                if (f.FieldType.ContainsGenericParameters)
                                {
                                    var typeArguments = t.GetGenericArguments();
                                    foreach (var tp in typeArguments)
                                    {
                                        if (tp.IsGenericParameter)
                                        {
                                            typeParameters.Add(tp.Name);
                                        }
                                    }
                                }

                                st.AddField(f.Name, typeParameters, fieldType);
                            }

                            //Check if we have an initializer function
                            var m = t.GetMethod("Initialize");
                            if (m != null)
                            {
                                var ii = new InitializerInfo(null);
                                ii.SetMethod(m);
                                st.SetInitializer(ii);
                            }
                        }
                    }
                }

                foreach (var t in asm.GetTypes())
                {
                    foreach (var m in t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
                    {
                        var p = m.GetParameters();
                        MethodDefinition.Parameter[] parameters = new MethodDefinition.Parameter[p.Length];
                        for (int i = 0; i < p.Length; i++)
                        {
                            parameters[i] = new MethodDefinition.Parameter(SmallType.FromSystemType(p[i].ParameterType), p[i].Name, p[i].ParameterType.IsByRef);
                        }

                        SmallType[] returnType;
                        if (m.ReturnType.IsConstructedGenericType)
                        {
                            var types = m.ReturnType.GetGenericArguments();
                            returnType = new SmallType[types.Length];
                            for (int i = 0; i < types.Length; i++)
                            {
                                returnType[i] = SmallType.FromSystemType(types[i]);
                            }
                        }
                        else if (m.ReturnType.IsGenericParameter)
                        {
                            returnType = new SmallType[] { SmallType.CreateGenericParameter(m.ReturnType.Name) };
                        }
                        else if (m.ReturnType != typeof(void))
                        {
                            returnType = new SmallType[] { SmallType.FromSystemType(m.ReturnType) }
                        }
                        ;
                        else
                        {
                            returnType = new SmallType[0];
                        }

                        List <SmallType> typeHints = new List <SmallType>();
                        if (m.IsGenericMethodDefinition)
                        {
                            var typeParameters = m.GetGenericArguments();
                            foreach (var tp in typeParameters)
                            {
                                if (tp.IsGenericParameter)
                                {
                                    typeHints.Add(SmallType.CreateGenericParameter(tp.Name));
                                }
                            }
                        }

                        MethodDefinition md = null;
                        if (returnType.Length == 1 && parameters.Length == 1 &&
                            m.Name == MetadataCache.CastFunction(parameters[0].Type, returnType[0]))
                        {
                            md = MetadataCache.AddImportedCast(pNode.Alias, parameters[0].Type, parameters[0].Name, returnType[0]);
                        }
                        else
                        {
                            md = MetadataCache.AddImportedMethod(pNode.Alias, m.Name, parameters, returnType, typeHints);
                        }
                        md.SetExternMethod(m);
                    }
                }
            }

            if (MetadataCache.ImportedNamespaces().Contains(pNode.Alias))
            {
                Compiler.ReportError(CompilerErrorType.DuplicateImportAlias, pNode, pNode.Alias);
            }
            else
            {
                MetadataCache.AddNamespace(pNode.Alias);
            }
        }
예제 #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ImportSymbol"/> class.
 /// </summary>
 /// <param name="name">The import name.</param>
 /// <param name="declaration">The declaration.</param>
 public ImportSymbol(string name, ImportSyntax declaration)
     : base(name)
 {
     Declaration = declaration;
 }