code / tomo

Lines41.3K C23.7K Markdown9.7K YAML5.0K Tomo2.3K
7 others 763
Python231 Shell230 make212 INI47 Text21 SVG16 Lua6
(80 lines)
1 // This file defines how to compile field accessing like `foo.x`
3 #include "../ast.h"
4 #include "../config.h"
5 #include "../environment.h"
6 #include "../stdlib/tables.h"
7 #include "../stdlib/text.h"
8 #include "../stdlib/util.h"
9 #include "../typecheck.h"
10 #include "compilation.h"
12 Text_t compile_field_access(env_t *env, ast_t *ast) {
13 DeclareMatch(f, ast, FieldAccess);
14 type_t *fielded_t = get_type(env, f->fielded);
15 type_t *value_t = value_type(fielded_t);
16 switch (value_t->tag) {
17 case TypeInfoType: {
18 DeclareMatch(info, value_t, TypeInfoType);
19 if (f->field[0] == '_') {
20 if (!type_eq(env->current_type, info->type))
21 code_err(ast, "Fields that start with underscores are not "
22 "accessible on outside of the type definition.");
24 binding_t *b = get_binding(info->env, f->field);
25 if (!b) code_err(ast, "I couldn't find the field '", f->field, "' on this type");
26 if (b->code.length == 0) code_err(ast, "I couldn't figure out how to compile this field");
27 return b->code;
29 case TextType: {
30 const char *lang = Match(value_t, TextType)->lang;
31 if (lang && streq(f->field, "text")) {
32 Text_t text = compile_to_pointer_depth(env, f->fielded, 0, false);
33 return Texts("((Text_t)", text, ")");
34 } else if (streq(f->field, "length")) {
35 return Texts("Int$from_int64((", compile_to_pointer_depth(env, f->fielded, 0, false), ").length)");
37 code_err(ast, "There is no '", f->field, "' field on ", type_to_text(value_t), " values");
39 case StructType: {
40 return compile_struct_field_access(env, ast);
42 case EnumType: {
43 return compile_enum_field_access(env, ast);
45 case ListType: {
46 if (streq(f->field, "length"))
47 return Texts("Int$from_int64((", compile_to_pointer_depth(env, f->fielded, 0, false), ").length)");
48 code_err(ast, "There is no ", f->field, " field on lists");
50 case TableType: {
51 if (streq(f->field, "length")) {
52 return Texts("Int$from_int64((", compile_to_pointer_depth(env, f->fielded, 0, false), ").entries.length)");
53 } else if (streq(f->field, "keys")) {
54 return Texts("LIST_COPY((", compile_to_pointer_depth(env, f->fielded, 0, false), ").entries)");
55 } else if (streq(f->field, "values")) {
56 DeclareMatch(table, value_t, TableType);
57 Text_t offset = Texts("offsetof(struct { ", compile_declaration(table->key_type, Text("k")), "; ",
58 compile_declaration(table->value_type, Text("v")), "; }, v)");
59 return Texts("({ List_t *entries = &(", compile_to_pointer_depth(env, f->fielded, 0, false),
60 ").entries;\n"
61 "LIST_INCREF(*entries);\n"
62 "List_t values = *entries;\n"
63 "values.data += ",
64 offset,
65 ";\n"
66 "values; })");
67 } else if (streq(f->field, "fallback")) {
68 return Texts("({ Table_t *_fallback = (", compile_to_pointer_depth(env, f->fielded, 0, false),
69 ").fallback; _fallback ? *_fallback : NONE_TABLE; })");
71 code_err(ast, "There is no '", f->field, "' field on tables");
73 case ModuleType: {
74 const char *name = Match(value_t, ModuleType)->name;
75 env_t *module_env = Table$str_get(*env->imports, name);
76 return compile(module_env, WrapAST(ast, Var, f->field));
78 default: code_err(ast, "Field accesses are not supported on ", type_to_text(fielded_t), " values");