Skip to content

Commit 931f65b

Browse files
committed
[[ FoundationRecord ]] Added 'basetype' to records allowing record extension.
1 parent 9f6e940 commit 931f65b

4 files changed

Lines changed: 75 additions & 20 deletions

File tree

libfoundation/include/foundation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,7 @@ struct MCRecordTypeFieldInfo
12491249
};
12501250

12511251
// Create a description of a record with the given fields.
1252-
bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *fields, uindex_t field_count, MCTypeInfoRef& r_typeinfo);
1252+
bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *fields, uindex_t field_count, MCTypeInfoRef base_type, MCTypeInfoRef& r_typeinfo);
12531253

12541254
// Return the number of fields in the record.
12551255
uindex_t MCRecordTypeInfoGetFieldCount(MCTypeInfoRef typeinfo);

libfoundation/src/foundation-private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct __MCTypeInfo: public __MCValue
6565
{
6666
MCRecordTypeFieldInfo *fields;
6767
uindex_t field_count;
68+
MCTypeInfoRef base;
6869
} record;
6970
struct
7071
{

libfoundation/src/foundation-record.cpp

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,41 @@
2020

2121
////////////////////////////////////////////////////////////////////////////////
2222

23+
static bool __check_conformance(MCTypeInfoRef p_typeinfo, const MCValueRef *p_values, uindex_t p_value_count, uindex_t& x_offset)
24+
{
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+
33+
if (x_offset + p_typeinfo -> record . field_count > p_value_count)
34+
return MCErrorThrowGeneric();
35+
36+
for(uindex_t i = 0; i < p_typeinfo -> record . field_count; i++)
37+
if (MCTypeInfoConforms(MCValueGetTypeInfo(p_values[x_offset + i]), p_typeinfo -> record . fields[i] . type))
38+
return MCErrorThrowGeneric();
39+
40+
return true;
41+
}
42+
43+
static uindex_t __count_fields(MCTypeInfoRef p_typeinfo)
44+
{
45+
uindex_t t_count;
46+
if (p_typeinfo -> record . base != kMCNullTypeInfo)
47+
{
48+
MCTypeInfoRef t_resolved_typeinfo;
49+
t_resolved_typeinfo = __MCTypeInfoResolve(p_typeinfo);
50+
t_count = __count_fields(t_resolved_typeinfo);
51+
}
52+
else
53+
t_count = 0;
54+
55+
return t_count + p_typeinfo -> record . field_count;
56+
}
57+
2358
bool MCRecordCreate(MCTypeInfoRef p_typeinfo, const MCValueRef *p_values, uindex_t p_value_count, MCRecordRef& r_record)
2459
{
2560
bool t_success;
@@ -28,20 +63,18 @@ bool MCRecordCreate(MCTypeInfoRef p_typeinfo, const MCValueRef *p_values, uindex
2863
MCTypeInfoRef t_resolved_typeinfo;
2964
t_resolved_typeinfo = __MCTypeInfoResolve(p_typeinfo);
3065

31-
if (p_value_count != t_resolved_typeinfo -> record . field_count)
32-
return MCErrorThrowGeneric();
33-
34-
for(uindex_t i = 0; i < p_value_count; i++)
35-
if (MCTypeInfoConforms(MCValueGetTypeInfo(p_values[i]), t_resolved_typeinfo -> record . fields[i] . type))
36-
return MCErrorThrowGeneric();
66+
uindex_t t_offset;
67+
if (!__check_conformance(t_resolved_typeinfo, p_values, p_value_count, t_offset))
68+
return false;
3769

3870
__MCRecord *self;
3971
self = nil;
4072
if (t_success)
4173
t_success = __MCValueCreate(kMCValueTypeCodeRecord, self);
4274

75+
// Here 'offset' will be the total count of all fields.
4376
if (t_success)
44-
t_success = MCMemoryNewArray(p_value_count, self -> fields);
77+
t_success = MCMemoryNewArray(t_offset, self -> fields);
4578

4679
if (t_success)
4780
{
@@ -70,17 +103,20 @@ bool MCRecordCreateMutable(MCTypeInfoRef p_typeinfo, MCRecordRef& r_record)
70103
MCTypeInfoRef t_resolved_typeinfo;
71104
t_resolved_typeinfo = __MCTypeInfoResolve(p_typeinfo);
72105

106+
uindex_t t_field_count;
107+
t_field_count = __count_fields(t_resolved_typeinfo);
108+
73109
__MCRecord *self;
74110
self = nil;
75111
if (t_success)
76112
t_success = __MCValueCreate(kMCValueTypeCodeRecord, self);
77113

78114
if (t_success)
79-
t_success = MCMemoryNewArray(t_resolved_typeinfo -> record . field_count, self -> fields);
115+
t_success = MCMemoryNewArray(t_field_count, self -> fields);
80116

81117
if (t_success)
82118
{
83-
for(uindex_t i = 0; i < t_resolved_typeinfo -> record . field_count; i++)
119+
for(uindex_t i = 0; i < t_field_count; i++)
84120
self -> fields[i] = MCValueRetain(kMCNull);
85121

86122
self -> flags |= kMCRecordFlagIsMutable;
@@ -108,7 +144,7 @@ bool MCRecordCopy(MCRecordRef self, MCRecordRef& r_new_record)
108144
MCTypeInfoRef t_resolved_typeinfo;
109145
t_resolved_typeinfo = __MCTypeInfoResolve(self -> typeinfo);
110146

111-
return MCRecordCreate(self -> typeinfo, self -> fields, t_resolved_typeinfo -> record . field_count, r_new_record);
147+
return MCRecordCreate(self -> typeinfo, self -> fields, __count_fields(t_resolved_typeinfo), r_new_record);
112148
}
113149

114150
bool MCRecordCopyAndRelease(MCRecordRef self, MCRecordRef& r_new_record)
@@ -133,7 +169,7 @@ bool MCRecordCopyAndRelease(MCRecordRef self, MCRecordRef& r_new_record)
133169

134170
// Otherwise make a copy of the data and then release the original
135171
bool t_success;
136-
t_success = MCRecordCreate(self -> typeinfo, self -> fields, t_resolved_typeinfo -> record . field_count, r_new_record);
172+
t_success = MCRecordCreate(self -> typeinfo, self -> fields, __count_fields(t_resolved_typeinfo), r_new_record);
137173
MCValueRelease(self);
138174

139175
return t_success;
@@ -145,7 +181,7 @@ bool MCRecordMutableCopy(MCRecordRef self, MCRecordRef& r_new_record)
145181
t_resolved_typeinfo = __MCTypeInfoResolve(self -> typeinfo);
146182

147183
MCRecordRef t_new_self;
148-
if (!MCRecordCreate(self -> typeinfo, self -> fields, t_resolved_typeinfo -> record . field_count, t_new_self))
184+
if (!MCRecordCreate(self -> typeinfo, self -> fields, __count_fields(t_resolved_typeinfo), t_new_self))
149185
return false;
150186

151187
t_new_self -> flags |= kMCRecordFlagIsMutable;
@@ -171,7 +207,7 @@ bool MCRecordIsMutable(MCRecordRef self)
171207
return (self -> flags & kMCRecordFlagIsMutable) != 0;
172208
}
173209

174-
bool MCRecordFetchValue(MCRecordRef self, MCNameRef p_field, MCValueRef& r_value)
210+
static bool __fetch_value(MCTypeInfoRef p_typeinfo, MCRecordRef self, MCNameRef p_field, MCValueRef& r_value)
175211
{
176212
MCTypeInfoRef t_resolved_typeinfo;
177213
t_resolved_typeinfo = __MCTypeInfoResolve(self -> typeinfo);
@@ -183,10 +219,18 @@ bool MCRecordFetchValue(MCRecordRef self, MCNameRef p_field, MCValueRef& r_value
183219
return true;
184220
}
185221

222+
if (p_typeinfo -> record . base != kMCNullTypeInfo)
223+
return __fetch_value(p_typeinfo -> record . base, self, p_field, r_value);
224+
186225
return false;
187226
}
188227

189-
bool MCRecordStoreValue(MCRecordRef self, MCNameRef p_field, MCValueRef p_value)
228+
bool MCRecordFetchValue(MCRecordRef self, MCNameRef p_field, MCValueRef& r_value)
229+
{
230+
return __fetch_value(self -> typeinfo, self, p_field, r_value);
231+
}
232+
233+
static bool __store_value(MCTypeInfoRef p_typeinfo, MCRecordRef self, MCNameRef p_field, MCValueRef p_value)
190234
{
191235
MCTypeInfoRef t_resolved_typeinfo;
192236
t_resolved_typeinfo = __MCTypeInfoResolve(self -> typeinfo);
@@ -200,18 +244,26 @@ bool MCRecordStoreValue(MCRecordRef self, MCNameRef p_field, MCValueRef p_value)
200244
self -> fields[i] = MCValueRetain(p_value);
201245
return true;
202246
}
203-
247+
248+
if (p_typeinfo -> record . base != kMCNullTypeInfo)
249+
return __store_value(p_typeinfo -> record . base, self, p_field, p_value);
250+
204251
return false;
205252
}
206253

254+
bool MCRecordStoreValue(MCRecordRef self, MCNameRef p_field, MCValueRef p_value)
255+
{
256+
return __store_value(self -> typeinfo, self, p_field, p_value);
257+
}
258+
207259
////////////////////////////////////////////////////////////////////////////////
208260

209261
void __MCRecordDestroy(__MCRecord *self)
210262
{
211263
MCTypeInfoRef t_resolved_typeinfo;
212264
t_resolved_typeinfo = __MCTypeInfoResolve(self -> typeinfo);
213265

214-
for(uindex_t i = 0; i < t_resolved_typeinfo -> record . field_count; i++)
266+
for(uindex_t i = 0; i < __count_fields(t_resolved_typeinfo); i++)
215267
MCValueRelease(self -> fields[i]);
216268
MCMemoryDelete(self -> fields);
217269
}
@@ -223,7 +275,7 @@ hash_t __MCRecordHash(__MCRecord *self)
223275

224276
hash_t t_hash;
225277
t_hash = 0;
226-
for(uindex_t i = 0; i < t_resolved_typeinfo -> record . field_count; i++)
278+
for(uindex_t i = 0; i < __count_fields(t_resolved_typeinfo); i++)
227279
{
228280
hash_t t_element_hash;
229281
t_element_hash = MCValueHash(self -> fields[i]);
@@ -242,7 +294,7 @@ bool __MCRecordIsEqualTo(__MCRecord *self, __MCRecord *other_self)
242294
t_resolved_typeinfo = __MCTypeInfoResolve(self -> typeinfo);
243295

244296
// Each field within the record must be equal to be equal.
245-
for(uindex_t i = 0; i < t_resolved_typeinfo -> record . field_count; i++)
297+
for(uindex_t i = 0; i < __count_fields(t_resolved_typeinfo); i++)
246298
if (!MCValueIsEqualTo(self -> fields[i], other_self -> fields[i]))
247299
return false;
248300

libfoundation/src/foundation-typeinfo.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ bool MCTypeInfoBindAndRelease(MCNameRef p_name, MCTypeInfoRef p_typeinfo, MCType
8787

8888
////////////////////////////////////////////////////////////////////////////////
8989

90-
bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *p_fields, uindex_t p_field_count, MCTypeInfoRef& r_typeinfo)
90+
bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *p_fields, uindex_t p_field_count, MCTypeInfoRef p_base, MCTypeInfoRef& r_typeinfo)
9191
{
9292
__MCTypeInfo *self;
9393
if (!__MCValueCreate(kMCValueTypeCodeTypeInfo, self))
@@ -107,6 +107,7 @@ bool MCRecordTypeInfoCreate(const MCRecordTypeFieldInfo *p_fields, uindex_t p_fi
107107
self -> record . fields[i] . type = MCValueRetain(p_fields[i] . type);
108108
}
109109
self -> record . field_count = p_field_count;
110+
self -> record . base = MCValueRetain(p_base != nil ? p_base : kMCNullTypeInfo);
110111

111112
if (MCValueInterAndRelease(self, r_typeinfo))
112113
return true;
@@ -313,6 +314,7 @@ void __MCTypeInfoDestroy(__MCTypeInfo *self)
313314
}
314315
else if (__MCTypeInfoGetTypeCode(self) == kMCValueTypeCodeRecord)
315316
{
317+
MCValueRelease(self -> record . base);
316318
for(uindex_t i = 0; i < self -> record . field_count; i++)
317319
{
318320
MCValueRelease(self -> record . fields[i] . name);

0 commit comments

Comments
 (0)