Skip to content

Commit 821921e

Browse files
committed
Detect duplicate field initializers (#416)
1 parent e7bb46b commit 821921e

File tree

5 files changed

+37
-17
lines changed

5 files changed

+37
-17
lines changed

playground/umka.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/umka_decl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ static void parseFnDecl(Compiler *comp)
747747
{
748748
Type *rcvBaseType = fnType->sig.param[0]->type->base;
749749

750-
if (rcvBaseType->kind == TYPE_STRUCT && typeFindField(rcvBaseType, name))
750+
if (rcvBaseType->kind == TYPE_STRUCT && typeFindField(rcvBaseType, name, NULL))
751751
comp->error.handler(comp->error.context, "Structure already has field %s", name);
752752
}
753753

src/umka_expr.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ static void doPtrToInterfaceConv(Compiler *comp, Type *dest, Type **src, Const *
387387
genSwapAssign(&comp->gen, TYPE_PTR, 0); // Assign to dest.__self
388388

389389
// Assign to __selftype (RTTI)
390-
Field *selfType = typeAssertFindField(&comp->types, dest, "__selftype");
390+
Field *selfType = typeAssertFindField(&comp->types, dest, "__selftype", NULL);
391391

392392
genPushGlobalPtr(&comp->gen, *src); // Push src type
393393
genPushLocalPtr(&comp->gen, destOffset + selfType->offset); // Push dest.__selftype pointer
@@ -440,7 +440,7 @@ static void doInterfaceToInterfaceConv(Compiler *comp, Type *dest, Type **src, C
440440
genSwapAssign(&comp->gen, TYPE_PTR, 0); // Assign to dest.__self (NULL means a dynamic type)
441441

442442
// Assign to __selftype (RTTI)
443-
Field *selfType = typeAssertFindField(&comp->types, dest, "__selftype");
443+
Field *selfType = typeAssertFindField(&comp->types, dest, "__selftype", NULL);
444444

445445
genDup(&comp->gen); // Duplicate src pointer
446446
genGetFieldPtr(&comp->gen, selfType->offset); // Get src.__selftype pointer
@@ -452,7 +452,7 @@ static void doInterfaceToInterfaceConv(Compiler *comp, Type *dest, Type **src, C
452452
for (int i = 2; i < dest->numItems; i++)
453453
{
454454
const char *name = dest->field[i]->name;
455-
Field *srcMethod = typeFindField(*src, name);
455+
Field *srcMethod = typeFindField(*src, name, NULL);
456456
if (!srcMethod)
457457
comp->error.handler(comp->error.context, "Method %s is not implemented", name);
458458

@@ -1557,7 +1557,7 @@ static void parseCall(Compiler *comp, Type **type, Const *constant)
15571557
if ((*type)->kind == TYPE_CLOSURE)
15581558
{
15591559
// Closure upvalue
1560-
Field *fn = typeAssertFindField(&comp->types, *type, "__fn");
1560+
Field *fn = typeAssertFindField(&comp->types, *type, "__fn", NULL);
15611561
*type = fn->type;
15621562

15631563
genPushUpvalue(&comp->gen);
@@ -1768,6 +1768,8 @@ static void parseArrayOrStructLiteral(Compiler *comp, Type **type, Const *consta
17681768
lexEat(&comp->lex, TOK_LBRACE);
17691769

17701770
bool namedFields = false;
1771+
bool *fieldInitialized = NULL;
1772+
17711773
if ((*type)->kind == TYPE_STRUCT)
17721774
{
17731775
if (comp->lex.tok.kind == TOK_RBRACE)
@@ -1780,6 +1782,9 @@ static void parseArrayOrStructLiteral(Compiler *comp, Type **type, Const *consta
17801782
}
17811783
}
17821784

1785+
if (namedFields)
1786+
fieldInitialized = calloc((*type)->numItems + 1, sizeof(bool));
1787+
17831788
const int size = typeSize(&comp->types, *type);
17841789
Ident *arrayOrStruct = NULL;
17851790

@@ -1808,7 +1813,14 @@ static void parseArrayOrStructLiteral(Compiler *comp, Type **type, Const *consta
18081813
if (namedFields)
18091814
{
18101815
lexCheck(&comp->lex, TOK_IDENT);
1811-
field = typeAssertFindField(&comp->types, *type, comp->lex.tok.name);
1816+
1817+
int fieldIndex = 0;
1818+
field = typeAssertFindField(&comp->types, *type, comp->lex.tok.name, &fieldIndex);
1819+
1820+
if (field && fieldInitialized[fieldIndex])
1821+
comp->error.handler(comp->error.context, "Duplicate field %s", field->name);
1822+
1823+
fieldInitialized[fieldIndex] = true;
18121824
itemOffset = field->offset;
18131825

18141826
lexNext(&comp->lex);
@@ -1846,9 +1858,13 @@ static void parseArrayOrStructLiteral(Compiler *comp, Type **type, Const *consta
18461858
lexNext(&comp->lex);
18471859
}
18481860
}
1861+
18491862
if (!namedFields && numItems < (*type)->numItems)
18501863
comp->error.handler(comp->error.context, "Too few elements in literal");
18511864

1865+
if (fieldInitialized)
1866+
free(fieldInitialized);
1867+
18521868
if (!constant)
18531869
doPushVarPtr(comp, arrayOrStruct);
18541870

@@ -2028,7 +2044,7 @@ static void parseClosureLiteral(Compiler *comp, Type **type, Const *constant)
20282044
if (comp->blocks.top != 0)
20292045
genNop(&comp->gen); // Jump over the nested function block (stub)
20302046

2031-
Field *fn = typeAssertFindField(&comp->types, *type, "__fn");
2047+
Field *fn = typeAssertFindField(&comp->types, *type, "__fn", NULL);
20322048

20332049
Const fnConstant = {.intVal = comp->gen.ip};
20342050
Ident *fnConstantIdent = identAddTempConst(&comp->idents, &comp->modules, &comp->blocks, fn->type, fnConstant);
@@ -2095,7 +2111,7 @@ static void parseClosureLiteral(Compiler *comp, Type **type, Const *constant)
20952111
}
20962112

20972113
// Assign closure upvalues
2098-
Field *upvalues = typeAssertFindField(&comp->types, closureIdent->type, "__upvalues");
2114+
Field *upvalues = typeAssertFindField(&comp->types, closureIdent->type, "__upvalues", NULL);
20992115
Type *upvaluesType = upvaluesStructIdent->type;
21002116

21012117
doPushVarPtr(comp, closureIdent);
@@ -2113,7 +2129,7 @@ static void parseClosureLiteral(Compiler *comp, Type **type, Const *constant)
21132129

21142130
genNop(&comp->gen); // Jump over the nested function block (stub)
21152131

2116-
Field *fn = typeAssertFindField(&comp->types, closureIdent->type, "__fn");
2132+
Field *fn = typeAssertFindField(&comp->types, closureIdent->type, "__fn", NULL);
21172133

21182134
Const fnConstant = {.intVal = comp->gen.ip};
21192135
Ident *fnConstantIdent = identAddTempConst(&comp->idents, &comp->modules, &comp->blocks, fn->type, fnConstant);
@@ -2365,7 +2381,7 @@ static void parseFieldSelector(Compiler *comp, Type **type, Const *constant, boo
23652381
comp->error.handler(comp->error.context, "Method %s is not defined for %s", comp->lex.tok.name, typeSpelling(*type, typeBuf));
23662382
}
23672383

2368-
Field *field = typeAssertFindField(&comp->types, *type, comp->lex.tok.name);
2384+
Field *field = typeAssertFindField(&comp->types, *type, comp->lex.tok.name, NULL);
23692385
lexNext(&comp->lex);
23702386

23712387
genGetFieldPtr(&comp->gen, field->offset);

src/umka_types.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -574,22 +574,26 @@ void typeEnableForward(Types *types, bool enable)
574574
}
575575

576576

577-
Field *typeFindField(Type *structType, const char *name)
577+
Field *typeFindField(Type *structType, const char *name, int *index)
578578
{
579579
if (structType->kind == TYPE_STRUCT || structType->kind == TYPE_INTERFACE || structType->kind == TYPE_CLOSURE)
580580
{
581581
unsigned int nameHash = hash(name);
582582
for (int i = 0; i < structType->numItems; i++)
583583
if (structType->field[i]->hash == nameHash && strcmp(structType->field[i]->name, name) == 0)
584+
{
585+
if (index)
586+
*index = i;
584587
return structType->field[i];
588+
}
585589
}
586590
return NULL;
587591
}
588592

589593

590-
Field *typeAssertFindField(Types *types, Type *structType, const char *name)
594+
Field *typeAssertFindField(Types *types, Type *structType, const char *name, int *index)
591595
{
592-
Field *res = typeFindField(structType, name);
596+
Field *res = typeFindField(structType, name, index);
593597
if (!res)
594598
types->error->handler(types->error->context, "Unknown field %s", name);
595599
return res;
@@ -610,7 +614,7 @@ Field *typeAddField(Types *types, Type *structType, Type *fieldType, const char
610614
name = fieldNameBuf;
611615
}
612616

613-
Field *field = typeFindField(structType, name);
617+
Field *field = typeFindField(structType, name, NULL);
614618
if (field)
615619
types->error->handler(types->error->context, "Duplicate field %s", name);
616620

src/umka_types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ static inline bool typeOverflow(TypeKind typeKind, Const val)
283283
}
284284

285285

286-
Field *typeFindField (Type *structType, const char *name);
287-
Field *typeAssertFindField (Types *types, Type *structType, const char *name);
286+
Field *typeFindField (Type *structType, const char *name, int *index);
287+
Field *typeAssertFindField (Types *types, Type *structType, const char *name, int *index);
288288
Field *typeAddField (Types *types, Type *structType, Type *fieldType, const char *fieldName);
289289

290290
EnumConst *typeFindEnumConst (Type *enumType, const char *name);

0 commit comments

Comments
 (0)