mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-26 09:23:48 +00:00
Fix immutable rules; add some general documentation
immutable is still a little weird and not completely what you'd expect. Maybe just not having it is better.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
// This stores the information for the specify architecture of this build
|
||||
typedef struct BuildContext {
|
||||
// Constants
|
||||
String ODIN_OS; // target operating system
|
||||
String ODIN_ARCH; // target architecture
|
||||
String ODIN_ENDIAN; // target endian
|
||||
@@ -6,8 +8,10 @@ typedef struct BuildContext {
|
||||
String ODIN_VERSION; // compiler version
|
||||
String ODIN_ROOT; // Odin ROOT
|
||||
|
||||
i64 word_size;
|
||||
i64 max_align;
|
||||
// In bytes
|
||||
i64 word_size; // Size of a pointer, must be >= 4
|
||||
i64 max_align; // max alignment, must be >= 1 (and typically >= word_size)
|
||||
|
||||
String llc_flags;
|
||||
String link_flags;
|
||||
bool is_dll;
|
||||
|
||||
+8
-3
@@ -4103,7 +4103,8 @@ void check_set_mode_with_indirection(Operand *o, bool indirection) {
|
||||
if (o->mode != Addressing_Immutable) {
|
||||
if (indirection) {
|
||||
o->mode = Addressing_Variable;
|
||||
} else if (o->mode != Addressing_Variable) {
|
||||
} else if (o->mode != Addressing_Variable &&
|
||||
o->mode != Addressing_Constant) {
|
||||
o->mode = Addressing_Value;
|
||||
}
|
||||
}
|
||||
@@ -4139,7 +4140,9 @@ bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_cou
|
||||
|
||||
case Type_Slice:
|
||||
o->type = t->Slice.elem;
|
||||
o->mode = Addressing_Variable;
|
||||
if (o->mode != Addressing_Immutable) {
|
||||
o->mode = Addressing_Variable;
|
||||
}
|
||||
return true;
|
||||
|
||||
case Type_DynamicArray:
|
||||
@@ -5132,7 +5135,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
||||
goto error;
|
||||
}
|
||||
|
||||
o->mode = Addressing_Value;
|
||||
if (o->mode != Addressing_Immutable) {
|
||||
o->mode = Addressing_Value;
|
||||
}
|
||||
|
||||
i64 indices[2] = {0};
|
||||
AstNode *nodes[2] = {se->low, se->high};
|
||||
|
||||
+38
-30
@@ -6,22 +6,6 @@ typedef enum ExprKind {
|
||||
Expr_Stmt,
|
||||
} ExprKind;
|
||||
|
||||
typedef enum AddressingMode {
|
||||
Addressing_Invalid,
|
||||
|
||||
Addressing_NoValue,
|
||||
Addressing_Value,
|
||||
Addressing_Variable,
|
||||
Addressing_Immutable,
|
||||
Addressing_Constant,
|
||||
Addressing_Type,
|
||||
Addressing_Builtin,
|
||||
Addressing_Overload,
|
||||
Addressing_MapIndex,
|
||||
|
||||
Addressing_Count,
|
||||
} AddressingMode;
|
||||
|
||||
// Statements and Declarations
|
||||
typedef enum StmtFlag {
|
||||
Stmt_BreakAllowed = 1<<0,
|
||||
@@ -124,11 +108,26 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
||||
|
||||
#include "types.c"
|
||||
|
||||
#define MAP_TYPE Entity *
|
||||
#define MAP_PROC map_entity_
|
||||
#define MAP_NAME MapEntity
|
||||
#include "map.c"
|
||||
typedef enum AddressingMode {
|
||||
Addressing_Invalid, // invalid addressing mode
|
||||
Addressing_NoValue, // no value (void in C)
|
||||
Addressing_Value, // computed value (rvalue)
|
||||
Addressing_Immutable, // immutable computed value (const rvalue)
|
||||
Addressing_Variable, // addressable variable (lvalue)
|
||||
Addressing_Constant, // constant & type will be a of Type_Basic (stripping Type_Named)
|
||||
Addressing_Type, // type
|
||||
Addressing_Builtin, // built in procedure
|
||||
Addressing_Overload, // overloaded procedure
|
||||
Addressing_MapIndex, // map index expression
|
||||
// lhs: acts like a Variable
|
||||
// ths: acts like a value with an optional boolean part (for existence check)
|
||||
} AddressingMode;
|
||||
|
||||
// Operand is used as an intermediate value whilst checking
|
||||
// Operands store an addressing mode, the expression being evaluated,
|
||||
// its type and node, and other specific information for certain
|
||||
// addressing modes
|
||||
// Its zero-value is a valid "invalid operand"
|
||||
typedef struct Operand {
|
||||
AddressingMode mode;
|
||||
Type * type;
|
||||
@@ -161,7 +160,7 @@ bool is_operand_nil(Operand o) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// DeclInfo is used to store information of certain declarations to allow for "any order" usage
|
||||
typedef struct DeclInfo {
|
||||
Scope *scope;
|
||||
|
||||
@@ -175,6 +174,17 @@ typedef struct DeclInfo {
|
||||
MapBool deps; // Key: Entity *
|
||||
} DeclInfo;
|
||||
|
||||
// ProcedureInfo stores the information needed for checking a procedure
|
||||
typedef struct ProcedureInfo {
|
||||
AstFile * file;
|
||||
Token token;
|
||||
DeclInfo *decl;
|
||||
Type * type; // Type_Procedure
|
||||
AstNode * body; // AstNode_BlockStmt
|
||||
u32 tags;
|
||||
} ProcedureInfo;
|
||||
|
||||
// ExprInfo stores information used for "untyped" expressions
|
||||
typedef struct ExprInfo {
|
||||
bool is_lhs; // Debug info
|
||||
AddressingMode mode;
|
||||
@@ -187,14 +197,12 @@ ExprInfo make_expr_info(bool is_lhs, AddressingMode mode, Type *type, ExactValue
|
||||
return ei;
|
||||
}
|
||||
|
||||
typedef struct ProcedureInfo {
|
||||
AstFile * file;
|
||||
Token token;
|
||||
DeclInfo *decl;
|
||||
Type * type; // Type_Procedure
|
||||
AstNode * body; // AstNode_BlockStmt
|
||||
u32 tags;
|
||||
} ProcedureInfo;
|
||||
|
||||
|
||||
#define MAP_TYPE Entity *
|
||||
#define MAP_PROC map_entity_
|
||||
#define MAP_NAME MapEntity
|
||||
#include "map.c"
|
||||
|
||||
typedef struct Scope {
|
||||
Scope * parent;
|
||||
@@ -258,7 +266,7 @@ typedef struct CheckerContext {
|
||||
Type * type_hint;
|
||||
} CheckerContext;
|
||||
|
||||
// NOTE(bill): Symbol tables
|
||||
// CheckerInfo stores all the symbol information for a type-checked program
|
||||
typedef struct CheckerInfo {
|
||||
MapTypeAndValue types; // Key: AstNode * | Expression -> Type (and value)
|
||||
MapEntity definitions; // Key: AstNode * | Identifier -> Entity
|
||||
|
||||
@@ -131,6 +131,9 @@ i16 f32_to_f16(f32 value) {
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef Array(i32) Array_i32;
|
||||
typedef Array(isize) Array_isize;
|
||||
|
||||
|
||||
#define MAP_TYPE String
|
||||
#define MAP_PROC map_string_
|
||||
|
||||
+6
-3
@@ -40,12 +40,15 @@ typedef enum EntityFlag {
|
||||
EntityFlag_TypeField = 1<<8,
|
||||
} EntityFlag;
|
||||
|
||||
// Zero value means the overloading process is not yet done
|
||||
typedef enum OverloadKind {
|
||||
Overload_No = -1,
|
||||
Overload_Unknown = 0,
|
||||
Overload_Yes = +1,
|
||||
Overload_Unknown,
|
||||
Overload_No,
|
||||
Overload_Yes,
|
||||
} OverloadKind;
|
||||
|
||||
|
||||
// An Entity is a named "thing" in the language
|
||||
typedef struct Entity Entity;
|
||||
struct Entity {
|
||||
EntityKind kind;
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#define MAP_NAME MapString
|
||||
#include "map.c"
|
||||
*/
|
||||
// A `Map` is an unordered hash table which can allow for a key to point to multiple values
|
||||
// with the use of the `multi_*` procedures.
|
||||
// TODO(bill): I should probably allow the `multi_*` stuff to be #ifdefed out
|
||||
|
||||
#ifndef MAP_UTIL_STUFF
|
||||
#define MAP_UTIL_STUFF
|
||||
|
||||
+3
-1
@@ -111,7 +111,9 @@ AstNodeArray make_ast_node_array(AstFile *f) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// NOTE(bill): This massive define is so it is possible to create a discriminated union (and extra debug info)
|
||||
// for the AstNode. I personally prefer discriminated unions over subtype polymorphism as I can preallocate
|
||||
// all the nodes and even memcpy in a different kind of node
|
||||
#define AST_NODE_KINDS \
|
||||
AST_NODE_KIND(Ident, "identifier", Token) \
|
||||
AST_NODE_KIND(Implicit, "implicit", Token) \
|
||||
|
||||
@@ -19,6 +19,7 @@ typedef struct String {
|
||||
#define str_lit(c_str) (String){cast(u8 *)c_str, gb_size_of(c_str)-1}
|
||||
|
||||
|
||||
// NOTE(bill): String16 is only used for Windows due to its file directories
|
||||
typedef struct String16 {
|
||||
wchar_t *text;
|
||||
isize len;
|
||||
|
||||
+9
-8
@@ -178,8 +178,9 @@ typedef struct Type {
|
||||
bool failure;
|
||||
} Type;
|
||||
|
||||
typedef Array(i32) Array_i32;
|
||||
|
||||
// TODO(bill): Should I add extra information here specifying the kind of selection?
|
||||
// e.g. field, constant, vector field, type field, etc.
|
||||
typedef struct Selection {
|
||||
Entity * entity;
|
||||
Array_i32 index;
|
||||
@@ -195,6 +196,7 @@ Selection make_selection(Entity *entity, Array_i32 index, bool indirect) {
|
||||
void selection_add_index(Selection *s, isize index) {
|
||||
// IMPORTANT NOTE(bill): this requires a stretchy buffer/dynamic array so it requires some form
|
||||
// of heap allocation
|
||||
// TODO(bill): Find a way to use a backing buffer for initial use as the general case is probably .count<3
|
||||
if (s->index.e == NULL) {
|
||||
array_init(&s->index, heap_allocator());
|
||||
}
|
||||
@@ -277,6 +279,7 @@ gb_global Type *t_byte_slice = NULL;
|
||||
gb_global Type *t_string_slice = NULL;
|
||||
|
||||
|
||||
// Type generated for the "preload" file
|
||||
gb_global Type *t_type_info = NULL;
|
||||
gb_global Type *t_type_info_record = NULL;
|
||||
gb_global Type *t_type_info_enum_value = NULL;
|
||||
@@ -303,7 +306,6 @@ gb_global Type *t_type_info_raw_union = NULL;
|
||||
gb_global Type *t_type_info_enum = NULL;
|
||||
gb_global Type *t_type_info_map = NULL;
|
||||
|
||||
|
||||
gb_global Type *t_type_info_named_ptr = NULL;
|
||||
gb_global Type *t_type_info_integer_ptr = NULL;
|
||||
gb_global Type *t_type_info_float_ptr = NULL;
|
||||
@@ -323,8 +325,6 @@ gb_global Type *t_type_info_raw_union_ptr = NULL;
|
||||
gb_global Type *t_type_info_enum_ptr = NULL;
|
||||
gb_global Type *t_type_info_map_ptr = NULL;
|
||||
|
||||
|
||||
|
||||
gb_global Type *t_allocator = NULL;
|
||||
gb_global Type *t_allocator_ptr = NULL;
|
||||
gb_global Type *t_context = NULL;
|
||||
@@ -337,14 +337,15 @@ gb_global Type *t_map_header = NULL;
|
||||
|
||||
|
||||
|
||||
i64 type_size_of (gbAllocator allocator, Type *t);
|
||||
i64 type_align_of (gbAllocator allocator, Type *t);
|
||||
i64 type_offset_of(gbAllocator allocator, Type *t, i32 index);
|
||||
|
||||
|
||||
|
||||
i64 type_size_of (gbAllocator allocator, Type *t);
|
||||
i64 type_align_of (gbAllocator allocator, Type *t);
|
||||
i64 type_offset_of (gbAllocator allocator, Type *t, i32 index);
|
||||
gbString type_to_string(Type *type);
|
||||
|
||||
|
||||
|
||||
Type *base_type(Type *t) {
|
||||
for (;;) {
|
||||
if (t == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user