Skip to content

Commit f98760e

Browse files
committed
Simplify LCB records.
This commit simplifies record support for LiveCode builder in two important ways: - Removal of the concept of a "base type" for a record. This simplifies the implementation a lot, and most of the benefits of the base type feature can still be obtained by composition. - Record types are no longer considered equivalent if they're made up of the same fields. This is important, since it ensures that two records that happen to just contain a pointer don't get treated as interchangeable by the VM, eg record type RenderBuffer mPointer as Pointer end type record type WindowHandle mPointer as Pointer end type These are not interchangeable!
1 parent 0c7ae50 commit f98760e

File tree

15 files changed

+25
-252
lines changed

15 files changed

+25
-252
lines changed

libfoundation/include/foundation.h

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,10 +1740,7 @@ struct MCRecordTypeFieldInfo
17401740
};
17411741

17421742
// Create a description of a record with the given fields.
1743-
MC_DLLEXPORT bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *fields, index_t field_count, MCTypeInfoRef base_type, MCTypeInfoRef& r_typeinfo);
1744-
1745-
// Return the base type of the record.
1746-
MC_DLLEXPORT MCTypeInfoRef MCRecordTypeInfoGetBaseType(MCTypeInfoRef typeinfo);
1743+
MC_DLLEXPORT bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *fields, index_t field_count, MCTypeInfoRef& r_typeinfo);
17471744

17481745
// Return the number of fields in the record.
17491746
MC_DLLEXPORT uindex_t MCRecordTypeInfoGetFieldCount(MCTypeInfoRef typeinfo);
@@ -1754,9 +1751,6 @@ MC_DLLEXPORT MCNameRef MCRecordTypeInfoGetFieldName(MCTypeInfoRef typeinfo, uind
17541751
// Return the type of the field at the given index.
17551752
MC_DLLEXPORT MCTypeInfoRef MCRecordTypeInfoGetFieldType(MCTypeInfoRef typeinfo, uindex_t index);
17561753

1757-
// Return true if typeinfo is derived from p_base_typeinfo.
1758-
MC_DLLEXPORT bool MCRecordTypeInfoIsDerivedFrom(MCTypeInfoRef typeinfo, MCTypeInfoRef p_base_typeinfo);
1759-
17601754
//////////
17611755

17621756
// Handler types describe the signature of a function.
@@ -2821,12 +2815,6 @@ MC_DLLEXPORT bool MCRecordCopyAndRelease(MCRecordRef record, MCRecordRef& r_new_
28212815
MC_DLLEXPORT bool MCRecordMutableCopy(MCRecordRef record, MCRecordRef& r_new_record);
28222816
MC_DLLEXPORT bool MCRecordMutableCopyAndRelease(MCRecordRef record, MCRecordRef& r_new_record);
28232817

2824-
MC_DLLEXPORT bool MCRecordCopyAsBaseType(MCRecordRef record, MCTypeInfoRef p_base_typeinfo, MCRecordRef & r_new_record);
2825-
MC_DLLEXPORT bool MCRecordCopyAsBaseTypeAndRelease(MCRecordRef record, MCTypeInfoRef p_base_typeinfo, MCRecordRef & r_new_record);
2826-
2827-
MC_DLLEXPORT bool MCRecordCopyAsDerivedType(MCRecordRef record, MCTypeInfoRef p_derived_typeinfo, MCRecordRef & r_new_record);
2828-
MC_DLLEXPORT bool MCRecordCopyAsDerivedTypeAndRelease(MCRecordRef record, MCTypeInfoRef p_derived_typeinfo, MCRecordRef & r_new_record);
2829-
28302818
MC_DLLEXPORT bool MCRecordIsMutable(MCRecordRef self);
28312819

28322820
MC_DLLEXPORT bool MCRecordFetchValue(MCRecordRef record, MCNameRef field, MCValueRef& r_value);

libfoundation/src/foundation-private.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ struct __MCTypeInfo: public __MCValue
9090
{
9191
MCRecordTypeFieldInfo *fields;
9292
uindex_t field_count;
93-
MCTypeInfoRef base;
9493
} record;
9594
struct
9695
{
@@ -558,7 +557,6 @@ bool __MCTypeInfoCopyDescription(__MCTypeInfo *self, MCStringRef& r_description)
558557
MCTypeInfoRef __MCTypeInfoResolve(__MCTypeInfo *self);
559558

560559
uindex_t __MCRecordTypeInfoGetFieldCount (__MCTypeInfo *self);
561-
void __MCRecordTypeInfoGetBaseTypeForField (__MCTypeInfo *self, uindex_t p_index, __MCTypeInfo *& r_base_type, uindex_t & r_base_index);
562560

563561
bool __MCForeignValueInitialize(void);
564562
void __MCForeignValueFinalize(void);

libfoundation/src/foundation-record.cpp

Lines changed: 0 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@
2222

2323
static bool __check_conformance(MCTypeInfoRef p_typeinfo, const MCValueRef *p_values, uindex_t p_value_count, uindex_t& x_offset)
2424
{
25-
if (p_typeinfo -> record . base != kMCNullTypeInfo)
26-
{
27-
MCTypeInfoRef t_resolved_typeinfo;
28-
t_resolved_typeinfo = __MCTypeInfoResolve(p_typeinfo);
29-
if (!__check_conformance(t_resolved_typeinfo, p_values, p_value_count, x_offset))
30-
return false;
31-
}
32-
3325
if (x_offset + p_typeinfo -> record . field_count > p_value_count)
3426
return MCErrorThrowGeneric(nil);
3527

@@ -219,9 +211,6 @@ static bool __fetch_value(MCTypeInfoRef p_typeinfo, MCRecordRef self, MCNameRef
219211
return true;
220212
}
221213

222-
if (p_typeinfo -> record . base != kMCNullTypeInfo)
223-
return __fetch_value(p_typeinfo -> record . base, self, p_field, r_value);
224-
225214
return false;
226215
}
227216

@@ -248,9 +237,6 @@ static bool __store_value(MCTypeInfoRef p_typeinfo, MCRecordRef self, MCNameRef
248237
return true;
249238
}
250239

251-
if (p_typeinfo -> record . base != kMCNullTypeInfo)
252-
return __store_value(p_typeinfo -> record . base, self, p_field, p_value);
253-
254240
return false;
255241
}
256242

@@ -265,108 +251,6 @@ bool MCRecordStoreValue(MCRecordRef self, MCNameRef p_field, MCValueRef p_value)
265251

266252
////////////////////////////////////////////////////////////////////////////////
267253

268-
MC_DLLEXPORT_DEF bool
269-
MCRecordCopyAsBaseType(MCRecordRef self,
270-
MCTypeInfoRef p_base_typeinfo,
271-
MCRecordRef & r_new_record)
272-
{
273-
bool t_success;
274-
MCValueRetain(self);
275-
t_success = MCRecordCopyAsBaseTypeAndRelease(self,
276-
p_base_typeinfo,
277-
r_new_record);
278-
if (!t_success) MCValueRelease(self);
279-
return t_success;
280-
}
281-
282-
MC_DLLEXPORT_DEF bool
283-
MCRecordCopyAsBaseTypeAndRelease(MCRecordRef self,
284-
MCTypeInfoRef p_base_typeinfo,
285-
MCRecordRef & r_new_record)
286-
{
287-
__MCAssertIsRecord(self);
288-
MCAssert(MCRecordTypeInfoIsDerivedFrom(self -> typeinfo, p_base_typeinfo));
289-
290-
/* If there's only one reference, just swap the typeinfo out and
291-
* make it immutable */
292-
if (self -> references == 1)
293-
{
294-
MCValueRelease(self -> typeinfo);
295-
self -> typeinfo = MCValueRetain(p_base_typeinfo);
296-
self -> flags &= ~kMCRecordFlagIsMutable;
297-
r_new_record = self;
298-
return true;
299-
}
300-
301-
if (!MCRecordCreate(p_base_typeinfo, self -> fields,
302-
MCRecordTypeInfoGetFieldCount (p_base_typeinfo),
303-
r_new_record))
304-
return false;
305-
306-
MCValueRelease(self);
307-
return true;
308-
}
309-
310-
MC_DLLEXPORT_DEF bool
311-
MCRecordCopyAsDerivedType(MCRecordRef self,
312-
MCTypeInfoRef p_derived_typeinfo,
313-
MCRecordRef & r_new_record)
314-
{
315-
bool t_success;
316-
MCValueRetain(self);
317-
t_success = MCRecordCopyAsDerivedTypeAndRelease(self,
318-
p_derived_typeinfo,
319-
r_new_record);
320-
if (!t_success) MCValueRelease(self);
321-
return t_success;
322-
}
323-
324-
MC_DLLEXPORT_DEF bool
325-
MCRecordCopyAsDerivedTypeAndRelease(MCRecordRef self,
326-
MCTypeInfoRef p_derived_typeinfo,
327-
MCRecordRef & r_new_record)
328-
{
329-
__MCAssertIsRecord(self);
330-
MCAssert(MCRecordTypeInfoIsDerivedFrom(p_derived_typeinfo, self -> typeinfo));
331-
332-
uindex_t t_field_count, t_new_field_count;
333-
t_field_count = MCRecordTypeInfoGetFieldCount(self -> typeinfo);
334-
t_new_field_count = MCRecordTypeInfoGetFieldCount(p_derived_typeinfo);
335-
336-
/* If there's only one reference, then we need to: 1) swap the
337-
* typeinfo, 2) resize the field array and fill the new fields
338-
* with null values, and 3) make the record immutable. */
339-
if (self -> references == 1)
340-
{
341-
/* Resize the array */
342-
if (!MCMemoryResizeArray(t_new_field_count, self -> fields, t_field_count))
343-
return false;
344-
/* Clear new values */
345-
for (uindex_t i = t_field_count; i < t_new_field_count; ++i)
346-
self -> fields[i] = MCValueRetain(kMCNull);
347-
348-
/* Set the typeinfo and make immutable */
349-
MCValueRelease(self -> typeinfo);
350-
self -> typeinfo = MCValueRetain(p_derived_typeinfo);
351-
self -> flags &= ~kMCRecordFlagIsMutable;
352-
353-
r_new_record = self;
354-
return true;
355-
}
356-
357-
/* Otherwise, create and manually populate the new array */
358-
MCRecordRef t_result;
359-
if (!MCRecordCreateMutable(p_derived_typeinfo, t_result))
360-
return false;
361-
362-
for (uindex_t i = 0; i < t_field_count; ++i)
363-
t_result -> fields[i] = MCValueRetain(self -> fields[i]);
364-
365-
return MCRecordCopyAndRelease(t_result, r_new_record);
366-
}
367-
368-
////////////////////////////////////////////////////////////////////////////////
369-
370254
MC_DLLEXPORT_DEF bool
371255
MCRecordEncodeAsArray(MCRecordRef record,
372256
MCArrayRef & r_array)

libfoundation/src/foundation-typeinfo.cpp

Lines changed: 8 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -295,15 +295,9 @@ bool MCResolvedTypeInfoConforms(const MCResolvedTypeInfo& source, const MCResolv
295295
return false;
296296
}
297297

298-
// If the source is of record type, then the target must be the same type or
299-
// one of the source's super types.
298+
// If the source is of record type, then the target must be the same type.
300299
if (MCTypeInfoIsRecord(source . type))
301300
{
302-
// Now check to see if the target is one of the source's supertypes.
303-
for(MCTypeInfoRef t_supertype = source . type; t_supertype != kMCNullTypeInfo; t_supertype = __MCTypeInfoResolve(t_supertype) -> record . base)
304-
if (target . named_type == t_supertype)
305-
return true;
306-
307301
return false;
308302
}
309303

@@ -688,19 +682,11 @@ void *MCForeignTypeInfoGetLayoutType(MCTypeInfoRef unresolved_self)
688682
////////////////////////////////////////////////////////////////////////////////
689683

690684
MC_DLLEXPORT_DEF
691-
bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *p_fields, index_t p_field_count, MCTypeInfoRef p_base, MCTypeInfoRef& r_typeinfo)
685+
bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *p_fields, index_t p_field_count, MCTypeInfoRef& r_typeinfo)
692686

693687
{
694688
MCAssert(nil != p_fields || p_field_count == 0);
695689

696-
MCTypeInfoRef t_resolved_base;
697-
t_resolved_base = kMCNullTypeInfo;
698-
if (p_base != kMCNullTypeInfo)
699-
{
700-
t_resolved_base = __MCTypeInfoResolve(p_base);
701-
MCAssert(MCTypeInfoIsRecord (t_resolved_base));
702-
}
703-
704690
/* If the p_field_count < 0 then the p_fields are expected to be
705691
* terminated by a custodian with name = nil. */
706692
if (p_field_count < 0)
@@ -733,7 +719,6 @@ bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *p_fields, index_t p_fie
733719
self -> record . fields[i] . type = MCValueRetain(p_fields[i] . type);
734720
}
735721
self -> record . field_count = p_field_count;
736-
self -> record . base = MCValueRetain(t_resolved_base);
737722

738723
if (MCValueInterAndRelease(self, r_typeinfo))
739724
return true;
@@ -743,15 +728,6 @@ bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *p_fields, index_t p_fie
743728
return false;
744729
}
745730

746-
MC_DLLEXPORT_DEF
747-
MCTypeInfoRef MCRecordTypeInfoGetBaseType(MCTypeInfoRef unresolved_self)
748-
{
749-
MCTypeInfoRef self;
750-
self = __MCTypeInfoResolve(unresolved_self);
751-
MCAssert(MCTypeInfoIsRecord (self));
752-
return self -> record . base;
753-
}
754-
755731
MC_DLLEXPORT_DEF
756732
uindex_t MCRecordTypeInfoGetFieldCount(MCTypeInfoRef unresolved_self)
757733
{
@@ -765,15 +741,7 @@ uindex_t MCRecordTypeInfoGetFieldCount(MCTypeInfoRef unresolved_self)
765741
uindex_t
766742
__MCRecordTypeInfoGetFieldCount(MCTypeInfoRef self)
767743
{
768-
/* Sum field counts of all base record types */
769-
uindex_t t_field_count;
770-
t_field_count = 0;
771-
while (self != kMCNullTypeInfo) {
772-
t_field_count += self -> record . field_count;
773-
self = MCRecordTypeInfoGetBaseType (self);
774-
}
775-
776-
return t_field_count;
744+
return self->record.field_count;
777745
}
778746

779747
MC_DLLEXPORT_DEF
@@ -784,12 +752,8 @@ MCNameRef MCRecordTypeInfoGetFieldName(MCTypeInfoRef unresolved_self, uindex_t p
784752

785753
MCAssert((self -> flags & kMCTypeInfoTypeCodeMask) == kMCValueTypeCodeRecord);
786754

787-
MCTypeInfoRef t_base_type;
788-
uindex_t t_base_index;
789-
__MCRecordTypeInfoGetBaseTypeForField(self, p_index,
790-
t_base_type, t_base_index);
791-
792-
return t_base_type -> record . fields[t_base_index] . name;
755+
MCAssert(p_index < self->record.field_count);
756+
return self -> record . fields[p_index] . name;
793757
}
794758

795759
MC_DLLEXPORT_DEF
@@ -800,48 +764,8 @@ MCTypeInfoRef MCRecordTypeInfoGetFieldType(MCTypeInfoRef unresolved_self, uindex
800764

801765
MCAssert((self -> flags & kMCTypeInfoTypeCodeMask) == kMCValueTypeCodeRecord);
802766

803-
MCTypeInfoRef t_base_type;
804-
uindex_t t_base_index;
805-
__MCRecordTypeInfoGetBaseTypeForField(self, p_index,
806-
t_base_type, t_base_index);
807-
808-
return t_base_type -> record . fields[t_base_index] . type;
809-
}
810-
811-
MC_DLLEXPORT_DEF bool
812-
MCRecordTypeInfoIsDerivedFrom(MCTypeInfoRef self,
813-
MCTypeInfoRef other)
814-
{
815-
MCAssert(MCTypeInfoIsRecord (self));
816-
MCAssert(MCTypeInfoIsRecord (other));
817-
return MCTypeInfoConforms(self, other);
818-
}
819-
820-
////////////////////////////////////////////////////////////////////////////////
821-
822-
void
823-
__MCRecordTypeInfoGetBaseTypeForField (__MCTypeInfo *self,
824-
uindex_t p_index,
825-
__MCTypeInfo *& r_base,
826-
uindex_t & r_base_index)
827-
{
828-
uindex_t t_total_field_count;
829-
t_total_field_count = MCRecordTypeInfoGetFieldCount(self);
830-
MCAssert(t_total_field_count > p_index);
831-
832-
/* Search for the base record type where the requested field is
833-
* defined. */
834-
uindex_t t_base_field_count;
835-
t_base_field_count = t_total_field_count;
836-
while (t_base_field_count > p_index)
837-
{
838-
MCAssert (self != kMCNullTypeInfo);
839-
t_base_field_count -= self -> record . field_count;
840-
self = MCRecordTypeInfoGetBaseType(self);
841-
}
842-
843-
r_base = self;
844-
r_base_index = p_index - t_base_field_count;
767+
MCAssert(p_index < self->record.field_count);
768+
return self -> record . fields[p_index] . type;
845769
}
846770

847771
////////////////////////////////////////////////////////////////////////////////
@@ -1242,7 +1166,6 @@ void __MCTypeInfoDestroy(__MCTypeInfo *self)
12421166
}
12431167
else if (t_ext_typecode == kMCValueTypeCodeRecord)
12441168
{
1245-
MCValueRelease(self -> record . base);
12461169
for(uindex_t i = 0; i < self -> record . field_count; i++)
12471170
{
12481171
MCValueRelease(self -> record . fields[i] . name);
@@ -1318,7 +1241,6 @@ hash_t __MCTypeInfoHash(__MCTypeInfo *self)
13181241
}
13191242
else if (t_code == kMCValueTypeCodeRecord)
13201243
{
1321-
t_hash = MCHashBytesStream(t_hash, &self -> record . base, sizeof(self -> record . base));
13221244
t_hash = MCHashBytesStream(t_hash, &self -> record . field_count, sizeof(self -> record . field_count));
13231245
t_hash = MCHashBytesStream(t_hash, self -> record . fields, sizeof(MCRecordTypeFieldInfo) * self -> record . field_count);
13241246
}
@@ -1369,16 +1291,7 @@ bool __MCTypeInfoIsEqualTo(__MCTypeInfo *self, __MCTypeInfo *other_self)
13691291

13701292
if (t_code == kMCValueTypeCodeRecord)
13711293
{
1372-
if (self -> record . base != other_self -> record . base)
1373-
return false;
1374-
1375-
if (self -> record . field_count != other_self -> record . field_count)
1376-
return false;
1377-
1378-
for(uindex_t i = 0; i < self -> record . field_count; i++)
1379-
if (!MCNameIsEqualTo(self -> record . fields[i] . name, other_self -> record . fields[i] . name) ||
1380-
self -> record . fields[i] . type != other_self -> record . fields[i] . type)
1381-
return false;
1294+
return self == other_self;
13821295
}
13831296
else if (t_code == kMCValueTypeCodeHandler)
13841297
{

libscript/include/libscript/script.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ void MCScriptBeginHandlerTypeInModule(MCScriptModuleBuilderRef builder, uindex_t
360360
void MCScriptBeginForeignHandlerTypeInModule(MCScriptModuleBuilderRef builder, uindex_t return_type);
361361
void MCScriptContinueHandlerTypeInModule(MCScriptModuleBuilderRef builder, MCScriptHandlerTypeParameterMode mode, MCNameRef name, uindex_t type);
362362
void MCScriptEndHandlerTypeInModule(MCScriptModuleBuilderRef builder, uindex_t& r_new_type);
363-
void MCScriptBeginRecordTypeInModule(MCScriptModuleBuilderRef builder, uindex_t base_type);
363+
void MCScriptBeginRecordTypeInModule(MCScriptModuleBuilderRef builder);
364364
void MCScriptContinueRecordTypeInModule(MCScriptModuleBuilderRef builder, MCNameRef name, uindex_t type);
365365
void MCScriptEndRecordTypeInModule(MCScriptModuleBuilderRef builder, uindex_t& r_new_type);
366366

0 commit comments

Comments
 (0)