Table field access for .keys, .values, .default, .fallback
This commit is contained in:
parent
5344789d8a
commit
d06c63c70c
20
compile.c
20
compile.c
@ -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
31
test/tables.tm
Normal 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
13
types.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user