aboutsummaryrefslogtreecommitdiff
path: root/src/entity.cpp
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-06-08 12:03:40 +0100
committerGinger Bill <bill@gingerbill.org>2017-06-08 12:03:40 +0100
commit9b61adb97dd78e1cf04ad410e72166f684f97925 (patch)
treeccb50b757f31c36dcd2bac161d191e2d23dcb6d1 /src/entity.cpp
parent333924cce15e10e941ee63d6fcdc19d5cb95bb3c (diff)
Build as C++
Diffstat (limited to 'src/entity.cpp')
-rw-r--r--src/entity.cpp282
1 files changed, 282 insertions, 0 deletions
diff --git a/src/entity.cpp b/src/entity.cpp
new file mode 100644
index 000000000..f029685c3
--- /dev/null
+++ b/src/entity.cpp
@@ -0,0 +1,282 @@
+typedef struct Scope Scope;
+typedef struct Checker Checker;
+typedef struct Type Type;
+typedef struct DeclInfo DeclInfo;
+// typedef enum BuiltinProcId BuiltinProcId;
+
+
+#define ENTITY_KINDS \
+ ENTITY_KIND(Invalid) \
+ ENTITY_KIND(Constant) \
+ ENTITY_KIND(Variable) \
+ ENTITY_KIND(TypeName) \
+ ENTITY_KIND(Procedure) \
+ ENTITY_KIND(Builtin) \
+ ENTITY_KIND(ImportName) \
+ ENTITY_KIND(LibraryName) \
+ ENTITY_KIND(TypeAlias) \
+ ENTITY_KIND(ProcedureAlias) \
+ ENTITY_KIND(Nil) \
+ ENTITY_KIND(Label)
+
+typedef enum EntityKind {
+#define ENTITY_KIND(k) GB_JOIN2(Entity_, k),
+ ENTITY_KINDS
+#undef ENTITY_KIND
+ Entity_Count,
+} EntityKind;
+
+String const entity_strings[] = {
+#define ENTITY_KIND(k) {cast(u8 *)#k, gb_size_of(#k)-1},
+ ENTITY_KINDS
+#undef ENTITY_KIND
+};
+
+typedef enum EntityFlag {
+ EntityFlag_Visited = 1<<0,
+ EntityFlag_Used = 1<<1,
+ EntityFlag_Using = 1<<2,
+ EntityFlag_Field = 1<<3,
+ EntityFlag_Param = 1<<4,
+ EntityFlag_VectorElem = 1<<5,
+ EntityFlag_Ellipsis = 1<<6,
+ EntityFlag_NoAlias = 1<<7,
+ EntityFlag_TypeField = 1<<8,
+ EntityFlag_Value = 1<<9,
+ EntityFlag_Sret = 1<<10,
+ EntityFlag_BitFieldValue = 1<<11,
+} EntityFlag;
+
+// Zero value means the overloading process is not yet done
+typedef enum OverloadKind {
+ Overload_Unknown,
+ Overload_No,
+ Overload_Yes,
+} OverloadKind;
+
+typedef enum EntityAliasKind {
+ EntityAlias_Invalid,
+ EntityAlias_Type,
+ EntityAlias_Entity,
+} EntityAliasKind;
+
+
+// An Entity is a named "thing" in the language
+typedef struct Entity Entity;
+struct Entity {
+ EntityKind kind;
+ u64 id;
+ u32 flags;
+ Token token;
+ Scope * scope;
+ Type * type;
+ AstNode * identifier; // Can be NULL
+ DeclInfo * parent_proc_decl; // NULL if in file/global scope
+
+ // TODO(bill): Cleanup how `using` works for entities
+ Entity * using_parent;
+ AstNode * using_expr;
+
+ union {
+ struct {
+ ExactValue value;
+ } Constant;
+ struct {
+ i32 field_index;
+ i32 field_src_index;
+ bool is_immutable;
+ bool is_thread_local;
+ } Variable;
+ struct {
+ bool is_type_alias;
+ } TypeName;
+ struct {
+ bool is_foreign;
+ String foreign_name;
+ Entity * foreign_library;
+ String link_name;
+ u64 tags;
+ OverloadKind overload_kind;
+ } Procedure;
+ struct {
+ i32 id;
+ } Builtin;
+ struct {
+ String path;
+ String name;
+ Scope *scope;
+ bool used;
+ } ImportName;
+ struct {
+ String path;
+ String name;
+ bool used;
+ } LibraryName;
+ i32 TypeAlias;
+ struct {
+ Entity *original;
+ } ProcedureAlias;
+ i32 Nil;
+ struct {
+ String name;
+ AstNode *node;
+ } Label;
+ };
+};
+
+gb_global Entity *e_context = NULL;
+
+bool is_entity_kind_exported(EntityKind kind) {
+ switch (kind) {
+ case Entity_Builtin:
+ case Entity_ImportName:
+ case Entity_LibraryName:
+ case Entity_Nil:
+ return false;
+ }
+ return true;
+}
+
+bool is_entity_exported(Entity *e) {
+ // TODO(bill): Determine the actual exportation rules for imports of entities
+ GB_ASSERT(e != NULL);
+ if (!is_entity_kind_exported(e->kind)) {
+ return false;
+ }
+
+ String name = e->token.string;
+ if (name.len == 0) {
+ return false;
+ }
+ return name.text[0] != '_';
+}
+
+gb_global u64 global_entity_id = 0;
+
+Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) {
+ Entity *entity = gb_alloc_item(a, Entity);
+ entity->kind = kind;
+ entity->scope = scope;
+ entity->token = token;
+ entity->type = type;
+ entity->id = ++global_entity_id;
+ return entity;
+}
+
+Entity *make_entity_variable(gbAllocator a, Scope *scope, Token token, Type *type, bool is_immutable) {
+ Entity *entity = alloc_entity(a, Entity_Variable, scope, token, type);
+ entity->Variable.is_immutable = is_immutable;
+ return entity;
+}
+
+Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, Type *type) {
+ GB_ASSERT(parent != NULL);
+ token.pos = parent->token.pos;
+ Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type);
+ entity->using_parent = parent;
+ entity->parent_proc_decl = parent->parent_proc_decl;
+ entity->flags |= EntityFlag_Using;
+ return entity;
+}
+
+
+Entity *make_entity_constant(gbAllocator a, Scope *scope, Token token, Type *type, ExactValue value) {
+ Entity *entity = alloc_entity(a, Entity_Constant, scope, token, type);
+ entity->Constant.value = value;
+ return entity;
+}
+
+Entity *make_entity_type_name(gbAllocator a, Scope *scope, Token token, Type *type) {
+ Entity *entity = alloc_entity(a, Entity_TypeName, scope, token, type);
+ return entity;
+}
+
+Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, bool is_using, bool is_immutable) {
+ Entity *entity = make_entity_variable(a, scope, token, type, is_immutable);
+ entity->flags |= EntityFlag_Used;
+ if (is_using) entity->flags |= EntityFlag_Using;
+ entity->flags |= EntityFlag_Param;
+ return entity;
+}
+
+Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index) {
+ Entity *entity = make_entity_variable(a, scope, token, type, false);
+ entity->Variable.field_src_index = field_src_index;
+ entity->Variable.field_index = field_src_index;
+ if (is_using) entity->flags |= EntityFlag_Using;
+ entity->flags |= EntityFlag_Field;
+ return entity;
+}
+
+Entity *make_entity_vector_elem(gbAllocator a, Scope *scope, Token token, Type *type, i32 field_src_index) {
+ Entity *entity = make_entity_variable(a, scope, token, type, false);
+ entity->Variable.field_src_index = field_src_index;
+ entity->Variable.field_index = field_src_index;
+ entity->flags |= EntityFlag_Field;
+ entity->flags |= EntityFlag_VectorElem;
+ return entity;
+}
+
+Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *signature_type, u64 tags) {
+ Entity *entity = alloc_entity(a, Entity_Procedure, scope, token, signature_type);
+ entity->Procedure.tags = tags;
+ return entity;
+}
+
+Entity *make_entity_builtin(gbAllocator a, Scope *scope, Token token, Type *type, i32 id) {
+ Entity *entity = alloc_entity(a, Entity_Builtin, scope, token, type);
+ entity->Builtin.id = id;
+ return entity;
+}
+
+Entity *make_entity_import_name(gbAllocator a, Scope *scope, Token token, Type *type,
+ String path, String name, Scope *import_scope) {
+ Entity *entity = alloc_entity(a, Entity_ImportName, scope, token, type);
+ entity->ImportName.path = path;
+ entity->ImportName.name = name;
+ entity->ImportName.scope = import_scope;
+ return entity;
+}
+
+Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type *type,
+ String path, String name) {
+ Entity *entity = alloc_entity(a, Entity_LibraryName, scope, token, type);
+ entity->LibraryName.path = path;
+ entity->LibraryName.name = name;
+ return entity;
+}
+
+Entity *make_entity_type_alias(gbAllocator a, Scope *scope, Token token, Type *type) {
+ Entity *entity = alloc_entity(a, Entity_TypeAlias, scope, token, type);
+ return entity;
+}
+Entity *make_entity_procedure_alias(gbAllocator a, Scope *scope, Token token, Entity *original) {
+ GB_ASSERT(original != NULL);
+ Entity *entity = alloc_entity(a, Entity_ProcedureAlias, scope, token, original->type);
+ entity->ProcedureAlias.original = original;
+ return entity;
+}
+
+
+
+
+Entity *make_entity_nil(gbAllocator a, String name, Type *type) {
+ Token token = make_token_ident(name);
+ Entity *entity = alloc_entity(a, Entity_Nil, NULL, token, type);
+ return entity;
+}
+
+Entity *make_entity_label(gbAllocator a, Scope *scope, Token token, Type *type,
+ AstNode *node) {
+ Entity *entity = alloc_entity(a, Entity_Label, scope, token, type);
+ entity->Label.node = node;
+ return entity;
+}
+
+
+
+Entity *make_entity_dummy_variable(gbAllocator a, Scope *scope, Token token) {
+ token.string = str_lit("_");
+ return make_entity_variable(a, scope, token, NULL, false);
+}
+