diff --git a/BeefLibs/corlib/src/Interop.bf b/BeefLibs/corlib/src/Interop.bf index 1dc4728d..5a4c5521 100644 --- a/BeefLibs/corlib/src/Interop.bf +++ b/BeefLibs/corlib/src/Interop.bf @@ -89,7 +89,7 @@ namespace System } } - [AttributeUsage(.Struct)] + [AttributeUsage(.Struct, .DisallowAllowMultiple)] struct FlexibleArrayAttribute : Attribute, IOnTypeInit { String mName; @@ -99,20 +99,61 @@ namespace System mName = name; } + public this(params Span names) + { + mName = new String(); + for (var name in names) + { + if (!mName.IsEmpty) + mName.Append("\n"); + mName.Append(name); + } + } + [Comptime] public void OnTypeInit(Type type, Self* prev) { if (type.IsGenericParam) return; var field = type.GetField(type.FieldCount - 1).GetValueOrDefault(); - if ((field.FieldType == null) || (!field.FieldType.IsSizedArray) || (field.FieldType.Size != 0)) - Runtime.FatalError("Type must end in a zero-sized array"); - var elementType = (field.FieldType as SizedArrayType).UnderlyingType; - Compiler.Align(type, elementType.Align); - Compiler.EmitTypeBody(type, scope $""" - public {elementType}* {mName} mut => (({elementType}*)((uint8*)&this + Math.Align(typeof(Self).Size, typeof({elementType}).Align))); - public static int GetAllocSize(int arrayCount) => Math.Align(typeof(Self).Size, typeof({elementType}).Align) + typeof({elementType}).Size*arrayCount; - """); + if (field.FieldType?.IsUnion == true) + { + int diff = 0; + for (var unionField in field.FieldType.GetFields(.Instance)) + diff++; + for (var names in mName.Split('\n')) + diff--; + if (diff != 0) + Runtime.FatalError("Incorrect number of names specified"); + + var nameItr = mName.Split('\n'); + for (var unionField in field.FieldType.GetFields(.Instance)) + { + var name = nameItr.GetNext().Value; + if ((!unionField.FieldType.IsSizedArray) || (unionField.FieldType.Size != 0)) + Runtime.FatalError(scope $"Union field '{unionField.Name}' must be a zero-sized array"); + var elementType = (unionField.FieldType as SizedArrayType).UnderlyingType; + Compiler.Align(type, elementType.Align); + Compiler.EmitTypeBody(type, scope $""" + public {elementType}* {name} mut => (({elementType}*)((uint8*)&this + typeof(Self).Size)); + public static int GetAllocSize_{name}(int arrayCount) => typeof(Self).Size + typeof({elementType}).Size*arrayCount; + + """); + } + } + else + { + if (mName.Contains('\n')) + Runtime.FatalError("Only a single accessor name expected"); + if ((field.FieldType == null) || (!field.FieldType.IsSizedArray) || (field.FieldType.Size != 0)) + Runtime.FatalError("Type must end in a zero-sized array"); + var elementType = (field.FieldType as SizedArrayType).UnderlyingType; + Compiler.Align(type, elementType.Align); + Compiler.EmitTypeBody(type, scope $""" + public {elementType}* {mName} mut => (({elementType}*)((uint8*)&this + typeof(Self).Size)); + public static int GetAllocSize(int arrayCount) => typeof(Self).Size + typeof({elementType}).Size*arrayCount; + """); + } } } } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 9556afea..7f0e1c9d 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -11777,6 +11777,14 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con newVals.Add(ConstantToCurrent(constHolder->GetConstant(val), constHolder, elementType)); } } + else if (wantType->IsInstanceOf(mCompiler->mSpanTypeDef)) + { + auto elementType = wantType->GetUnderlyingType(); + for (auto val : constArray->mValues) + { + newVals.Add(ConstantToCurrent(constHolder->GetConstant(val), constHolder, elementType)); + } + } else { auto wantTypeInst = wantType->ToTypeInstance();