Table field access for .keys, .values, .default, .fallback

This commit is contained in:
Bruce Hill 2024-02-25 14:35:25 -05:00
parent 5344789d8a
commit d06c63c70c
3 changed files with 56 additions and 8 deletions

View File

@ -886,6 +886,26 @@ CORD compile(env_t *env, ast_t *ast)
}
code_err(ast, "The field '%s' is not a valid field name of %T", f->field, value_t);
}
case TableType: {
if (streq(f->field, "keys")) {
return CORD_all("({ table_t $t = ", compile_to_pointer_depth(env, f->fielded, 0, false), ";\n"
"(array_t){.data = $t.entries.data,\n .length=$t.entries.length,\n .stride=$t.entries.stride,\n .copy_on_write=yes};})");
} else if (streq(f->field, "values")) {
auto table = Match(value_t, TableType);
size_t offset = type_size(table->key_type);
size_t align = type_align(table->value_type);
if (align > 1 && offset % align > 0)
offset += align - (offset % align);
return CORD_all("({ table_t $t = ", compile_to_pointer_depth(env, f->fielded, 0, false), ";\n"
"(array_t){.data = $t.entries.data + ", CORD_asprintf("%zu", offset),
",\n .length=$t.entries.length,\n .stride=$t.entries.stride,\n .copy_on_write=yes};})");
} else if (streq(f->field, "fallback")) {
return CORD_all("(", compile_to_pointer_depth(env, f->fielded, 0, false), ").fallback");
} else if (streq(f->field, "default")) {
return CORD_all("(", compile_to_pointer_depth(env, f->fielded, 0, false), ").default_value");
}
code_err(ast, "There is no '%s' field on tables", f->field);
}
default:
code_err(ast, "Field accesses are only supported on struct and enum values");
}

31
test/tables.tm Normal file
View File

@ -0,0 +1,31 @@
>> t := {"one"=>1, "two"=>2; default=999}
= {"one"=>1, "two"=>2; default=999}
>> t["one"]
= 1
>> t["two"]
= 2
>> t["???"]
= 999
>> t.default
= ?(readonly)999
>> t.fallback
= !{Str=>Int64}
>> t.keys
= ["one", "two"]
>> t.values
= [1, 2]
>> t2 := {"three"=>3; fallback=t}
= {"three"=>3; fallback={"one"=>1, "two"=>2; default=999}}
>> t2["one"]
= 1
>> t2["three"]
= 3
>> t2["???"]
= 999
>> t2.default
= !Int64
>> t2.fallback
= ?(readonly){"one"=>1, "two"=>2; default=999}

13
types.c
View File

@ -524,18 +524,15 @@ type_t *get_field_type(type_t *t, const char *field_name)
}
return NULL;
}
case ArrayType: {
if (streq(field_name, "length"))
return Type(IntType, .bits=64);
return NULL;
}
case TableType: {
if (streq(field_name, "length"))
return Type(IntType, .bits=64);
else if (streq(field_name, "keys"))
if (streq(field_name, "keys"))
return Type(ArrayType, Match(t, TableType)->key_type);
else if (streq(field_name, "values"))
return Type(ArrayType, Match(t, TableType)->value_type);
else if (streq(field_name, "default"))
return Type(PointerType, .pointed=Match(t, TableType)->value_type, .is_readonly=true, .is_optional=true);
else if (streq(field_name, "fallback"))
return Type(PointerType, .pointed=t, .is_readonly=true, .is_optional=true);
return NULL;
}
default: return NULL;