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); }
// 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(); } }