Beispiel #1
0
        public static RuntimeIshtarModule Read(AppVault vault, byte[] arr, IReadOnlyList <VeinModule> deps, Func <string, Version, VeinModule> resolver)
        {
            var module = new RuntimeIshtarModule(vault);

            using var mem    = new MemoryStream(arr);
            using var reader = new BinaryReader(mem);
            module.Deps.AddRange(deps);

            var idx       = reader.ReadInt32(); // name index
            var vdx       = reader.ReadInt32(); // version index
            var ilVersion = reader.ReadInt32();

            if (ilVersion != OpCodes.SetVersion)
            {
                var exp = new ILCompatibleException(ilVersion, OpCodes.SetVersion);

                VM.FastFail(WNE.ASSEMBLY_COULD_NOT_LOAD, $"Unable to load assembly: '{exp.Message}'.", sys_frame);
                VM.ValidateLastError();
                return(null);
            }

            // read strings table
            foreach (var _ in..reader.ReadInt32())
            {
                var key   = reader.ReadInt32();
                var value = reader.ReadIshtarString();
                module.strings_table.Add(key, value);
            }
            // read types table
            foreach (var _ in..reader.ReadInt32())
            {
                var key     = reader.ReadInt32();
                var asmName = reader.ReadIshtarString();
                var ns      = reader.ReadIshtarString();
                var name    = reader.ReadIshtarString();
                module.types_table.Add(key, new QualityTypeName(asmName, name, ns));
            }
            // read fields table
            foreach (var _ in..reader.ReadInt32())
            {
                var key   = reader.ReadInt32();
                var name  = reader.ReadIshtarString();
                var clazz = reader.ReadIshtarString();
                module.fields_table.Add(key, new FieldName(name, clazz));
            }

            // read deps refs
            foreach (var _ in..reader.ReadInt32())
            {
                var name = reader.ReadIshtarString();
                var ver  = Version.Parse(reader.ReadIshtarString());
                if (module.Deps.Any(x => x.Version.Equals(ver) && x.Name.Equals(name)))
                {
                    continue;
                }
                var dep = resolver(name, ver);
                module.Deps.Add(dep);
            }
            // read class storage
            foreach (var _ in..reader.ReadInt32())
            {
                var body   = reader.ReadBytes(reader.ReadInt32());
                var @class = DecodeClass(body, module);
                module.class_table.Add(@class);
                if (@class.IsSpecial)
                {
                    if (VeinCore.All.Any(x => x.FullName == @class.FullName))
                    {
                        TypeForwarder.Indicate(@class);
                    }
                }
            }
            // restore unresolved types
            foreach (var @class in module.class_table)
            {
                for (var index = 0; index < @class.Parents.Count; index++)
                {
                    var parent = @class.Parents[index];
                    if (parent is not UnresolvedVeinClass)
                    {
                        continue;
                    }
                    @class.Parents[index] =
                        parent.FullName != @class.FullName
                            ? module.FindType(parent.FullName, true)
                            : null;
                }
            }
            // restore unresolved types
            foreach (var @class in module.class_table)
            {
                foreach (var method in @class.Methods)
                {
                    if (method.ReturnType is not UnresolvedVeinClass)
                    {
                        continue;
                    }
                    method.ReturnType = module.FindType(method.ReturnType.FullName, true);
                }

                foreach (var method in @class.Methods)
                {
                    foreach (var argument in method.Arguments)
                    {
                        if (argument.Type is not UnresolvedVeinClass)
                        {
                            continue;
                        }
                        argument.Type = module.FindType(argument.Type.FullName, true);
                    }
                }
                foreach (var field in @class.Fields)
                {
                    if (field.FieldType is not UnresolvedVeinClass)
                    {
                        continue;
                    }
                    field.FieldType = module.FindType(field.FieldType.FullName, true);
                }
            }

            var const_body_len = reader.ReadInt32();
            var const_body     = reader.ReadBytes(const_body_len);

            module.const_table = const_body.ToConstStorage();

            module.Name    = module.GetConstStringByIndex(idx);
            module.Version = Version.Parse(module.GetConstStringByIndex(vdx));
            module.aspects.AddRange(Aspect.Deconstruct(module.const_table.storage));

            module.SetupBootstraper(vault);

            DistributionAspects(module);
            ValidateRuntimeTokens(module);
            LinkFFIMethods(module);
            InitVTables(module);

            return(module);
        }
Beispiel #2
0
        // shit, todo: refactoring
        public static void DistributionAspects(RuntimeIshtarModule module)
        {
            var errors  = new StringBuilder();
            var classes = module.class_table;

            var class_eq = (VeinClass x, string clazz) => x.Name.Equals(clazz);

            foreach (var aspect in module.aspects)
            {
                switch (aspect)
                {
                case AspectOfClass classAspect:
                {
                    var @class = classes.FirstOrDefault(x => class_eq(x, classAspect.ClassName));
                    if (@class is not null)
                    {
                        @class.Aspects.Add(aspect);
                    }
                    else
                    {
                        errors.AppendLine($"Aspect '{classAspect.Name}': class '{classAspect.ClassName}' not found.");
                    }
                    break;
                }

                case AspectOfMethod ma:
                {
                    var method = classes
                                 .Where(x => class_eq(x, ma.ClassName))
                                 .SelectMany(x => x.Methods)
                                 .FirstOrDefault(method => method.Name.Equals(ma.MethodName));
                    if (method is not null)
                    {
                        method.Aspects.Add(aspect);
                    }
                    else
                    {
                        errors.AppendLine($"Aspect '{ma.Name}': method '{ma.ClassName}/{ma.MethodName}' not found.");
                    }
                    break;
                }

                case AspectOfField fa when !fa.IsNative():     // currently ignoring native aspect, todo
                {
                    var field = classes
                                .Where(x => class_eq(x, fa.ClassName))
                                .SelectMany(@class => @class.Fields)
                                .FirstOrDefault(field => field.Name.Equals(fa.FieldName));
                    if (field is not null)
                    {
                        field.Aspects.Add(aspect);
                    }
                    else
                    {
                        errors.AppendLine($"Aspect '{fa.Name}': field '{fa.ClassName}/{fa.FieldName}' not found.");
                    }
                    break;
                }
                }
            }

            if (errors.Length != 0)
            {
                VM.FastFail(WNE.TYPE_LOAD, $"\n{errors}", sys_frame);
                VM.ValidateLastError();
            }
        }