aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-05 18:17:55 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-05 18:17:55 +0000
commitb1562edccf9ea972ec8caf5faebea07cf27559bb (patch)
treeb6a0dfa591b33b277c583f287643deaaa213284a /src
parent2a5b674d33e4f483964da119f76038457cd9f1f2 (diff)
Add `types.odin`; Begin work on `map`
Diffstat (limited to 'src')
-rw-r--r--src/build.c3
-rw-r--r--src/check_expr.c93
-rw-r--r--src/checker.c8
-rw-r--r--src/ir.c8
-rw-r--r--src/ir_print.c12
-rw-r--r--src/types.c139
6 files changed, 225 insertions, 38 deletions
diff --git a/src/build.c b/src/build.c
index d90bcb5c3..3afc05047 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1,6 +1,7 @@
typedef struct BuildContext {
String ODIN_OS; // target operating system
String ODIN_ARCH; // target architecture
+ String ODIN_ENDIAN; // target endian
String ODIN_VENDOR; // compiler vendor
String ODIN_VERSION; // compiler version
String ODIN_ROOT; // Odin ROOT
@@ -243,9 +244,11 @@ void init_build_context(BuildContext *bc) {
#if defined(GB_SYSTEM_WINDOWS)
bc->ODIN_OS = str_lit("windows");
bc->ODIN_ARCH = str_lit("amd64");
+ bc->ODIN_ENDIAN = str_lit("little");
#elif defined(GB_SYSTEM_OSX)
bc->ODIN_OS = str_lit("osx");
bc->ODIN_ARCH = str_lit("amd64");
+ bc->ODIN_ENDIAN = str_lit("little");
#else
#error Implement system
#endif
diff --git a/src/check_expr.c b/src/check_expr.c
index c001a903f..15b5c55a7 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -910,7 +910,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
}
-void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint) {
+void check_ident (Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint) {
GB_ASSERT(n->kind == AstNode_Ident);
o->mode = Addressing_Invalid;
o->expr = n;
@@ -1051,7 +1051,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Type
o->type = type;
}
-i64 check_array_count(Checker *c, AstNode *e) {
+i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) {
if (e == NULL) {
return 0;
}
@@ -1059,7 +1059,11 @@ i64 check_array_count(Checker *c, AstNode *e) {
check_expr(c, &o, e);
if (o.mode != Addressing_Constant) {
if (o.mode != Addressing_Invalid) {
- error_node(e, "Array count must be a constant");
+ if (is_map) {
+ error_node(e, "Fixed map count must be a constant");
+ } else {
+ error_node(e, "Array count must be a constant");
+ }
}
return 0;
}
@@ -1067,18 +1071,59 @@ i64 check_array_count(Checker *c, AstNode *e) {
if (is_type_untyped(type) || is_type_integer(type)) {
if (o.value.kind == ExactValue_Integer) {
i64 count = o.value.value_integer;
- if (count >= 0) {
- return count;
+ if (is_map) {
+ if (count > 0) {
+ return count;
+ }
+ error_node(e, "Invalid fixed map count");
+ } else {
+ if (count >= 0) {
+ return count;
+ }
+ error_node(e, "Invalid array count");
}
- error_node(e, "Invalid array count");
return 0;
}
}
- error_node(e, "Array count must be an integer");
+ if (is_map) {
+ error_node(e, "Fixed map count must be an integer");
+ } else {
+ error_node(e, "Array count must be an integer");
+ }
return 0;
}
+void check_map_type(Checker *c, Type *type, AstNode *node) {
+ GB_ASSERT(type->kind == Type_Map);
+ ast_node(mt, MapType, node);
+
+ i64 count = check_array_or_map_count(c, mt->count, true);
+ Type *key = check_type_extra(c, mt->key, NULL);
+ Type *value = check_type_extra(c, mt->value, NULL);
+
+ if (!is_type_valid_for_keys(key)) {
+ if (is_type_boolean(key)) {
+ error_node(node, "A boolean cannot be used as a key for a map");
+ } else {
+ gbString str = type_to_string(key);
+ error_node(node, "Invalid type of a key for a map, got `%s`", str);
+ gb_string_free(str);
+ }
+ }
+
+ if (count > 0) {
+ count = 0;
+ error_node(node, "Fixed map types are not yet implemented");
+ }
+
+ type->Map.count = count;
+ type->Map.key = key;
+ type->Map.value = value;
+
+ // error_node(node, "`map` types are not yet implemented");
+}
+
Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
ExactValue null_value = {ExactValue_Invalid};
Type *type = NULL;
@@ -1092,7 +1137,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
switch (e->kind) {
case_ast_node(i, Ident, e);
Operand o = {0};
- check_identifier(c, &o, e, named_type, NULL);
+ check_ident(c, &o, e, named_type, NULL);
switch (o.mode) {
case Addressing_Invalid:
@@ -1169,7 +1214,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
case_ast_node(at, ArrayType, e);
if (at->count != NULL) {
Type *elem = check_type_extra(c, at->elem, NULL);
- type = make_type_array(c->allocator, elem, check_array_count(c, at->count));
+ type = make_type_array(c->allocator, elem, check_array_or_map_count(c, at->count, false));
} else {
Type *elem = check_type(c, at->elem);
type = make_type_slice(c->allocator, elem);
@@ -1188,7 +1233,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
case_ast_node(vt, VectorType, e);
Type *elem = check_type(c, vt->elem);
Type *be = base_type(elem);
- i64 count = check_array_count(c, vt->count);
+ i64 count = check_array_or_map_count(c, vt->count, false);
if (is_type_vector(be) || (!is_type_boolean(be) && !is_type_numeric(be))) {
err_str = type_to_string(elem);
error_node(vt->elem, "Vector element type must be numerical or a boolean, got `%s`", err_str);
@@ -1246,6 +1291,12 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
goto end;
case_end;
+ case_ast_node(mt, MapType, e);
+ type = alloc_type(c->allocator, Type_Map);
+ set_base_type(named_type, type);
+ check_map_type(c, type, e);
+ goto end;
+ case_end;
case_ast_node(ce, CallExpr, e);
Operand o = {0};
@@ -2750,6 +2801,26 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
operand->mode = Addressing_NoValue;
} break;
+ case BuiltinProc_clear: {
+ Type *type = operand->type;
+ if (!is_type_pointer(type)) {
+ gbString str = type_to_string(type);
+ error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str);
+ gb_string_free(str);
+ return false;
+ }
+ type = type_deref(type);
+ if (!is_type_dynamic_array(type)) {
+ gbString str = type_to_string(type);
+ error_node(operand->expr, "Expected a pointer to a dynamic array, got `%s`", str);
+ gb_string_free(str);
+ return false;
+ }
+
+ operand->type = NULL;
+ operand->mode = Addressing_NoValue;
+ } break;
+
case BuiltinProc_append: {
// append :: proc(^[dynamic]Type, item: ...Type) {
Type *type = operand->type;
@@ -4038,7 +4109,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
case_end;
case_ast_node(i, Ident, node);
- check_identifier(c, o, node, NULL, type_hint);
+ check_ident(c, o, node, NULL, type_hint);
case_end;
case_ast_node(bl, BasicLit, node);
diff --git a/src/checker.c b/src/checker.c
index cd0a9ddef..938a09f40 100644
--- a/src/checker.c
+++ b/src/checker.c
@@ -28,6 +28,7 @@ typedef enum BuiltinProcId {
BuiltinProc_free,
BuiltinProc_reserve,
+ BuiltinProc_clear,
BuiltinProc_append,
BuiltinProc_size_of,
@@ -69,6 +70,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("free"), 1, false, Expr_Stmt},
{STR_LIT("reserve"), 2, false, Expr_Stmt},
+ {STR_LIT("clear"), 1, false, Expr_Stmt},
{STR_LIT("append"), 1, true, Expr_Expr},
{STR_LIT("size_of"), 1, false, Expr_Expr},
@@ -610,6 +612,7 @@ void init_universal_scope(BuildContext *bc) {
// TODO(bill): Set through flags in the compiler
add_global_string_constant(a, str_lit("ODIN_OS"), bc->ODIN_OS);
add_global_string_constant(a, str_lit("ODIN_ARCH"), bc->ODIN_ARCH);
+ add_global_string_constant(a, str_lit("ODIN_ENDIAN"), bc->ODIN_ENDIAN);
add_global_string_constant(a, str_lit("ODIN_VENDOR"), bc->ODIN_VENDOR);
add_global_string_constant(a, str_lit("ODIN_VERSION"), bc->ODIN_VERSION);
add_global_string_constant(a, str_lit("ODIN_ROOT"), bc->ODIN_ROOT);
@@ -1141,6 +1144,11 @@ void init_preload(Checker *c) {
t_context_ptr = make_type_pointer(c->allocator, t_context);
}
+ if (t_raw_dynamic_array == NULL) {
+ Entity *e = find_core_entity(c, str_lit("Raw_Dynamic_Array"));
+ t_raw_dynamic_array = e->type;
+ }
+
c->done_preload = true;
}
diff --git a/src/ir.c b/src/ir.c
index ab948ab96..c6df0f237 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -2987,6 +2987,14 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
return ir_emit_global_call(proc, "__dynamic_array_reserve", args, 4);
} break;
+ case BuiltinProc_clear: {
+ ir_emit_comment(proc, str_lit("reserve"));
+ irValue *array_ptr = ir_build_expr(proc, ce->args.e[0]);
+ irValue *count_ptr = ir_emit_struct_ep(proc, array_ptr, 1);
+ ir_emit_store(proc, count_ptr, v_zero);
+ return NULL;
+ } break;
+
case BuiltinProc_append: {
ir_emit_comment(proc, str_lit("append"));
gbAllocator a = proc->module->allocator;
diff --git a/src/ir_print.c b/src/ir_print.c
index a2e5b147d..f3f9510c8 100644
--- a/src/ir_print.c
+++ b/src/ir_print.c
@@ -292,6 +292,18 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
}
ir_fprintf(f, ")*");
} return;
+
+ case Type_Map: {
+ if (t->Map.count > 0) {
+ // ir_fprintf(f, "void");
+ } else {
+ ir_fprintf(f, "{");
+ ir_print_type(f, m, t_raw_dynamic_array);
+ ir_fprintf(f, ", ");
+ ir_print_type(f, m, t_raw_dynamic_array);
+ ir_fprintf(f, "}");
+ }
+ } break;
}
}
diff --git a/src/types.c b/src/types.c
index 5443f85f1..bd3e5133d 100644
--- a/src/types.c
+++ b/src/types.c
@@ -95,35 +95,40 @@ typedef struct TypeRecord {
Entity * enum_max_value;
} TypeRecord;
-#define TYPE_KINDS \
- TYPE_KIND(Basic, BasicType) \
- TYPE_KIND(Pointer, struct { Type *elem; }) \
+#define TYPE_KINDS \
+ TYPE_KIND(Basic, BasicType) \
+ TYPE_KIND(Pointer, struct { Type *elem; }) \
TYPE_KIND(Array, struct { Type *elem; i64 count; }) \
- TYPE_KIND(DynamicArray, struct { Type *elem; }) \
+ TYPE_KIND(DynamicArray, struct { Type *elem; }) \
TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \
- TYPE_KIND(Slice, struct { Type *elem; }) \
- TYPE_KIND(Maybe, struct { Type *elem; }) \
- TYPE_KIND(Record, TypeRecord) \
- TYPE_KIND(Named, struct { \
- String name; \
- Type * base; \
- Entity *type_name; /* Entity_TypeName */ \
- }) \
- TYPE_KIND(Tuple, struct { \
- Entity **variables; /* Entity_Variable */ \
- i32 variable_count; \
- bool are_offsets_set; \
- i64 * offsets; \
- }) \
- TYPE_KIND(Proc, struct { \
- Scope *scope; \
- Type * params; /* Type_Tuple */ \
- Type * results; /* Type_Tuple */ \
- i32 param_count; \
- i32 result_count; \
- bool variadic; \
- ProcCallingConvention calling_convention; \
- })
+ TYPE_KIND(Slice, struct { Type *elem; }) \
+ TYPE_KIND(Maybe, struct { Type *elem; }) \
+ TYPE_KIND(Record, TypeRecord) \
+ TYPE_KIND(Named, struct { \
+ String name; \
+ Type * base; \
+ Entity *type_name; /* Entity_TypeName */ \
+ }) \
+ TYPE_KIND(Tuple, struct { \
+ Entity **variables; /* Entity_Variable */ \
+ i32 variable_count; \
+ bool are_offsets_set; \
+ i64 * offsets; \
+ }) \
+ TYPE_KIND(Proc, struct { \
+ Scope *scope; \
+ Type * params; /* Type_Tuple */ \
+ Type * results; /* Type_Tuple */ \
+ i32 param_count; \
+ i32 result_count; \
+ bool variadic; \
+ ProcCallingConvention calling_convention; \
+ }) \
+ TYPE_KIND(Map, struct { \
+ i64 count; /* 0 if dynamic */ \
+ Type *key; \
+ Type *value; \
+ }) \
@@ -319,6 +324,7 @@ gb_global Type *t_allocator_ptr = NULL;
gb_global Type *t_context = NULL;
gb_global Type *t_context_ptr = NULL;
+gb_global Type *t_raw_dynamic_array = NULL;
@@ -477,6 +483,23 @@ Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_coun
return t;
}
+bool is_type_valid_for_keys(Type *t);
+
+Type *make_type_map(gbAllocator a, i64 count, Type *key, Type *value) {
+ Type *t = alloc_type(a, Type_Map);
+ if (key != NULL) {
+ GB_ASSERT(is_type_valid_for_keys(key));
+ }
+ t->Map.count = count;
+ t->Map.key = key;
+ t->Map.value = value;
+ return t;
+}
+
+
+
+
+
Type *type_deref(Type *t) {
if (t != NULL) {
@@ -679,6 +702,21 @@ bool is_type_enum(Type *t) {
return (t->kind == Type_Record && t->Record.kind == TypeRecord_Enum);
}
+bool is_type_map(Type *t) {
+ t = base_type(t);
+ return t->kind == Type_Map;
+}
+
+bool is_type_fixed_map(Type *t) {
+ t = base_type(t);
+ return t->kind == Type_Map && t->Map.count > 0;
+}
+bool is_type_dynamic_map(Type *t) {
+ t = base_type(t); return t->kind == Type_Map && t->Map.count == 0;
+}
+
+
+
bool is_type_any(Type *t) {
t = base_type(t);
@@ -691,6 +729,28 @@ bool is_type_untyped_nil(Type *t) {
+bool is_type_valid_for_keys(Type *t) {
+ t = base_type(base_enum_type(t));
+ if (is_type_untyped(t)) {
+ return false;
+ }
+ if (is_type_integer(t)) {
+ return true;
+ }
+ if (is_type_float(t)) {
+ return true;
+ }
+ if (is_type_string(t)) {
+ return true;
+ }
+ if (is_type_pointer(t)) {
+ return true;
+ }
+
+ return false;
+}
+
+
bool is_type_indexable(Type *t) {
return is_type_array(t) || is_type_slice(t) || is_type_vector(t) || is_type_string(t);
}
@@ -1458,6 +1518,14 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
return align;
}
+ case Type_Map: {
+ if (t->Map.count == 0) { // Dynamic
+ // NOTE(bill): same as a dynamic array
+ return s.word_size;
+ }
+ GB_PANIC("TODO(bill): Fixed map alignment");
+ } break;
+
case Type_Record: {
switch (t->Record.kind) {
case TypeRecord_Struct:
@@ -1667,6 +1735,14 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP
return align_formula(size, align);
}
+ case Type_Map: {
+ if (t->Map.count == 0) { // Dynamic
+ // NOTE(bill): same as a two dynamic arrays
+ return 2 * type_size_of_internal(s, allocator, t_raw_dynamic_array, path);
+ }
+ GB_PANIC("TODO(bill): Fixed map size");
+ }
+
case Type_Tuple: {
i64 count, align, size;
count = t->Tuple.variable_count;
@@ -1924,6 +2000,15 @@ gbString write_type_to_string(gbString str, Type *type) {
}
} break;
+ case Type_Map: {
+ str = gb_string_appendc(str, "map[");
+ if (type->Map.count > 0) {
+ str = gb_string_appendc(str, gb_bprintf("%lld, ", type->Map.count));
+ }
+ str = write_type_to_string(str, type->Map.key);
+ str = gb_string_appendc(str, "]");
+ str = write_type_to_string(str, type->Map.value);
+ } break;
case Type_Named:
if (type->Named.type_name != NULL) {