Allow number indexing of struct fields.

Better error messages on failed struct access.
This commit is contained in:
Sage Vaillancourt 2022-04-13 16:57:06 -04:00 committed by Sage Vaillancourt
parent 80255af52e
commit e326af38f8
2 changed files with 14 additions and 5 deletions

View File

@ -307,13 +307,22 @@ Object structAccess(Object* params, unused int length, unused struct Environment
Object field = params[1]; Object field = params[1];
struct StructDef* structDef = getStructAt(structo.structObject->definition); struct StructDef* structDef = getStructAt(structo.structObject->definition);
if (isStringy(field)) {
for (int i = 0; i < structDef->fieldCount; i++) { for (int i = 0; i < structDef->fieldCount; i++) {
if (strcmp(field.string, structDef->names[i]) == 0) { if (strcmp(field.string, structDef->names[i]) == 0) {
return cloneObject(structo.structObject->fields[i]); return cloneObject(structo.structObject->fields[i]);
} }
} }
throw(NULL_PARSE, "Could not find struct field named `%s`", field.string);
}
if (isNumber(field)) {
if (structDef->fieldCount < field.number || field.number < 0) {
throw(NULL_PARSE, "Could not find struct field at index %ld. Struct `%s` has %d fields.", field.number, structDef->name, structDef->fieldCount);
}
return cloneObject(structo.structObject->fields[field.number]);
}
throw(NULL_PARSE, "Could not find field named `%s`", field.string); throw(BAD_PARAMS, "Struct fields should be indexed with a string or a number, but received a %s", getTypeName(&field));
} }
Result parse(struct Slice* slices) Result parse(struct Slice* slices)

View File

@ -122,7 +122,7 @@ fn(def, "def",
); );
tfn(structAccess, "poss", tfn(structAccess, "poss",
({ expect(isStruct), expect(isStringy), anyType }), ({ expect(isStruct), anyType, anyType }),
"Get the value of a struct's field", "Get the value of a struct's field",
"(struct Post (title body))\n " "(struct Post (title body))\n "
"(def p (Post \"This is a title\" \"This is the body\"))\n " "(def p (Post \"This is a title\" \"This is the body\"))\n "