Explorar el Código

v0.0.4 - `odin build_dll`, atomic.odin, sync.odin

Ginger Bill hace 8 años
padre
commit
a6f8c9d6e0
Se han modificado 11 ficheros con 125 adiciones y 62 borrados
  1. 2 2
      build.bat
  2. 1 1
      code/demo.odin
  3. 31 0
      core/win32.odin
  4. 1 1
      src/build.c
  5. 40 30
      src/checker/checker.c
  6. 21 19
      src/checker/decl.c
  7. 21 7
      src/checker/expr.c
  8. 5 0
      src/checker/stmt.c
  9. 1 1
      src/gb/gb.h
  10. 1 0
      src/parser.c
  11. 1 1
      src/tokenizer.c

+ 2 - 2
build.bat

@@ -4,7 +4,7 @@
 set exe_name=odin.exe
 
 :: Debug = 0, Release = 1
-set release_mode=0
+set release_mode=1
 
 set compiler_flags= -nologo -Oi -TC -W4 -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
 
@@ -48,8 +48,8 @@ rem pushd %build_dir%
 
 	cl %compiler_settings% "src\main.c" ^
 		/link %linker_settings% -OUT:%exe_name% ^
-	&& odin build_dll code/example.odin ^
 	&& odin run code/demo.odin
+	rem && odin build_dll code/example.odin ^
 	rem && odin run code/demo.odin
 
 

+ 1 - 1
code/demo.odin

@@ -1,5 +1,6 @@
 #import "win32.odin"
 #import "fmt.odin"
+#import "sync.odin"
 
 Dll :: struct {
 	Handle :: type rawptr
@@ -50,6 +51,5 @@ main :: proc() {
 	}
 
 	some_thing := (proc_addr as proc())
-	fmt.println(some_thing)
 	some_thing()
 }

+ 31 - 0
core/win32.odin

@@ -205,6 +205,37 @@ GetProcessHeap :: proc() -> HANDLE #foreign #dll_import
 
 HEAP_ZERO_MEMORY :: 0x00000008
 
+// Synchronization
+
+SECURITY_ATTRIBUTES :: struct #ordered {
+	length:              u32
+	security_descriptor: rawptr
+	inherit_handle:      BOOL
+}
+
+INFINITE :: 0xffffffff
+
+CreateSemaphoreA    :: proc(attributes: ^SECURITY_ATTRIBUTES, initial_count, maximum_count: i32, name: ^byte) -> HANDLE #foreign #dll_import
+ReleaseSemaphore    :: proc(semaphore: HANDLE, release_count: i32, previous_count: ^i32) -> BOOL #foreign #dll_import
+WaitForSingleObject :: proc(handle: HANDLE, milliseconds: u32) -> u32 #foreign #dll_import
+
+
+InterlockedCompareExchange :: proc(dst: ^i32, exchange, comparand: i32) -> i32 #foreign
+InterlockedExchange        :: proc(dst: ^i32, desired: i32) -> i32 #foreign
+InterlockedExchangeAdd     :: proc(dst: ^i32, desired: i32) -> i32 #foreign
+InterlockedAnd             :: proc(dst: ^i32, desired: i32) -> i32 #foreign
+InterlockedOr              :: proc(dst: ^i32, desired: i32) -> i32 #foreign
+
+InterlockedCompareExchange64 :: proc(dst: ^i64, exchange, comparand: i64) -> i64 #foreign
+InterlockedExchange64        :: proc(dst: ^i64, desired: i64) -> i64 #foreign
+InterlockedExchangeAdd64     :: proc(dst: ^i64, desired: i64) -> i64 #foreign
+InterlockedAnd64             :: proc(dst: ^i64, desired: i64) -> i64 #foreign
+InterlockedOr64              :: proc(dst: ^i64, desired: i64) -> i64 #foreign
+
+_mm_pause        :: proc() #foreign
+ReadWriteBarrier :: proc() #foreign
+WriteBarrier     :: proc() #foreign
+ReadBarrier      :: proc() #foreign
 
 
 // GDI

+ 1 - 1
src/build.c

@@ -149,7 +149,7 @@ String get_filepath_extension(String path) {
 
 void init_build_context(BuildContext *bc) {
 	bc->ODIN_VENDOR  = str_lit("odin");
-	bc->ODIN_VERSION = str_lit("0.0.3d");
+	bc->ODIN_VERSION = str_lit("0.0.4");
 	bc->ODIN_ROOT    = odin_root_dir();
 
 #if defined(GB_SYSTEM_WINDOWS)

+ 40 - 30
src/checker/checker.c

@@ -1120,31 +1120,6 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
 			DelayedDecl di = {parent_scope, decl};
 			array_add(&c->delayed_foreign_libraries, di);
 		case_end;
-		case_ast_node(cd, ConstDecl, decl);
-			for_array(i, cd->values) {
-				AstNode *name = cd->names.e[i];
-				AstNode *value = cd->values.e[i];
-				ExactValue v = {ExactValue_Invalid};
-				if (name->kind != AstNode_Ident) {
-					error_node(name, "A declaration's name but be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
-				}
-				Entity *e = make_entity_constant(c->allocator, parent_scope, name->Ident, NULL, v);
-				e->identifier = name;
-				DeclInfo *di = make_declaration_info(c->allocator, parent_scope);
-				di->type_expr = cd->type;
-				di->init_expr = value;
-				add_entity_and_decl_info(c, name, e, di);
-			}
-
-			isize lhs_count = cd->names.count;
-			isize rhs_count = cd->values.count;
-
-			if (rhs_count == 0 && cd->type == NULL) {
-				error_node(decl, "Missing type or initial expression");
-			} else if (lhs_count < rhs_count) {
-				error_node(decl, "Extra initial expression");
-			}
-		case_end;
 		case_ast_node(vd, VarDecl, decl);
 			if (!parent_scope->is_file) {
 				// NOTE(bill): Within a procedure, variables must be in order
@@ -1171,7 +1146,8 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
 					value = vd->values.e[i];
 				}
 				if (name->kind != AstNode_Ident) {
-					error_node(name, "A declaration's name but be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
+					error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
+					continue;
 				}
 				Entity *e = make_entity_variable(c->allocator, parent_scope, name->Ident, NULL);
 				e->identifier = name;
@@ -1180,7 +1156,7 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
 				DeclInfo *d = di;
 				if (d == NULL) {
 					AstNode *init_expr = value;
-					d = make_declaration_info(heap_allocator(), parent_scope);
+					d = make_declaration_info(heap_allocator(), e->scope);
 					d->type_expr = vd->type;
 					d->init_expr = init_expr;
 					d->var_decl_tags = vd->tags;
@@ -1189,15 +1165,52 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
 				add_entity_and_decl_info(c, name, e, d);
 			}
 		case_end;
+		case_ast_node(cd, ConstDecl, decl);
+			for_array(i, cd->values) {
+				AstNode *name = cd->names.e[i];
+				AstNode *value = unparen_expr(cd->values.e[i]);
+				if (name->kind != AstNode_Ident) {
+					error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
+					continue;
+				}
+
+				ExactValue v = {ExactValue_Invalid};
+				Entity *e = make_entity_constant(c->allocator, parent_scope, name->Ident, NULL, v);
+				e->identifier = name;
+				DeclInfo *di = make_declaration_info(c->allocator, e->scope);
+				di->type_expr = cd->type;
+				di->init_expr = value;
+				add_entity_and_decl_info(c, name, e, di);
+			}
+
+			isize lhs_count = cd->names.count;
+			isize rhs_count = cd->values.count;
+
+			if (rhs_count == 0 && cd->type == NULL) {
+				error_node(decl, "Missing type or initial expression");
+			} else if (lhs_count < rhs_count) {
+				error_node(decl, "Extra initial expression");
+			}
+		case_end;
 		case_ast_node(td, TypeDecl, decl);
+			if (td->name->kind != AstNode_Ident) {
+				error_node(td->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[td->name->kind]));
+				continue;
+			}
 			ast_node(n, Ident, td->name);
+
 			Entity *e = make_entity_type_name(c->allocator, parent_scope, *n, NULL);
 			e->identifier = td->name;
 			DeclInfo *d = make_declaration_info(c->allocator, e->scope);
 			d->type_expr = td->type;
+			d->init_expr = td->type;
 			add_entity_and_decl_info(c, td->name, e, d);
 		case_end;
 		case_ast_node(pd, ProcDecl, decl);
+			if (pd->name->kind != AstNode_Ident) {
+				error_node(pd->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[pd->name->kind]));
+				continue;
+			}
 			ast_node(n, Ident, pd->name);
 			Token token = *n;
 			Entity *e = make_entity_procedure(c->allocator, parent_scope, token, NULL, pd->tags);
@@ -1275,9 +1288,6 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 				if (e->scope == parent_scope) {
 					continue;
 				}
-
-
-
 				// NOTE(bill): Do not add other imported entities
 				add_entity(c, parent_scope, NULL, e);
 				if (!id->is_load) { // `#import`ed entities don't get exported

+ 21 - 19
src/checker/decl.c

@@ -211,8 +211,25 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
 	e->Constant.value = operand->value;
 }
 
+void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
+	GB_ASSERT(e->type == NULL);
+	Type *named = make_type_named(c->allocator, e->token.string, NULL, e);
+	named->Named.type_name = e;
+	if (def != NULL && def->kind == Type_Named) {
+		def->Named.base = named;
+	}
+	e->type = named;
+
+	// gb_printf_err("%.*s %p\n", LIT(e->token.string), e);
 
-void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr) {
+	Type *bt = check_type_extra(c, type_expr, named);
+	named->Named.base = base_type(bt);
+	if (named->Named.base == t_invalid) {
+		// gb_printf("check_type_decl: %s\n", type_to_string(named));
+	}
+}
+
+void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr, Type *named_type) {
 	GB_ASSERT(e->type == NULL);
 
 	if (e->flags & EntityFlag_Visited) {
@@ -238,26 +255,10 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_e
 		// check_expr_or_type(c, &operand, init_expr);
 		check_expr(c, &operand, init_expr);
 	}
+
 	check_init_constant(c, e, &operand);
 }
 
-void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
-	GB_ASSERT(e->type == NULL);
-	Type *named = make_type_named(c->allocator, e->token.string, NULL, e);
-	named->Named.type_name = e;
-	if (def != NULL && def->kind == Type_Named) {
-		def->Named.base = named;
-	}
-	e->type = named;
-
-	// gb_printf_err("%.*s %p\n", LIT(e->token.string), e);
-
-	Type *bt = check_type_extra(c, type_expr, named);
-	named->Named.base = base_type(bt);
-	if (named->Named.base == t_invalid) {
-		// gb_printf("check_type_decl: %s\n", type_to_string(named));
-	}
-}
 
 
 bool are_signatures_similar_enough(Type *a_, Type *b_) {
@@ -458,6 +459,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 		if (found) {
 			d = *found;
 		} else {
+			// TODO(bill): Err here?
 			e->type = t_invalid;
 			set_base_type(named_type, t_invalid);
 			return;
@@ -471,7 +473,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 
 	switch (e->kind) {
 	case Entity_Constant:
-		check_const_decl(c, e, d->type_expr, d->init_expr);
+		check_const_decl(c, e, d->type_expr, d->init_expr, named_type);
 		break;
 	case Entity_Variable:
 		check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr);

+ 21 - 7
src/checker/expr.c

@@ -11,9 +11,11 @@ bool     check_value_is_expressible(Checker *c, ExactValue in_value, Type *type,
 void     convert_to_typed          (Checker *c, Operand *operand, Type *target_type, i32 level);
 gbString expr_to_string            (AstNode *expression);
 void     check_entity_decl         (Checker *c, Entity *e, DeclInfo *decl, Type *named_type);
+void     check_const_decl          (Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr, Type *named_type);
 void     check_proc_body           (Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body);
 void     update_expr_type          (Checker *c, AstNode *e, Type *type, bool final);
 
+
 gb_inline Type *check_type(Checker *c, AstNode *expression) {
 	return check_type_extra(c, expression, NULL);
 }
@@ -87,22 +89,20 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
 
 			for_array(i, cd->values) {
 				AstNode *name = cd->names.e[i];
-				AstNode *value = cd->values.e[i];
-				ExactValue v = {ExactValue_Invalid};
-
-				if (!ast_node_expect(name, AstNode_Ident)) {
+				AstNode *value = unparen_expr(cd->values.e[i]);
+				if (name->kind != AstNode_Ident) {
+					error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
 					entities[entity_index++] = NULL;
 					continue;
 				}
 
+				ExactValue v = {ExactValue_Invalid};
 				Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
 				e->identifier = name;
 				entities[entity_index++] = e;
-
 				DeclInfo *d = make_declaration_info(c->allocator, e->scope);
 				d->type_expr = cd->type;
 				d->init_expr = value;
-
 				add_entity_and_decl_info(c, name, e, d);
 
 				DelayedEntity delay = {name, e, d};
@@ -171,6 +171,10 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
 			if (!ast_node_expect(td->name, AstNode_Ident)) {
 				break;
 			}
+			if (td->name->kind != AstNode_Ident) {
+				error_node(td->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[td->name->kind]));
+				continue;
+			}
 
 			Token name_token = td->name->Ident;
 
@@ -457,7 +461,6 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, MapEntity *en
 	gb_string_free(str);
 }
 
-void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr);
 
 void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
                   Entity **fields, isize field_count,
@@ -1581,6 +1584,11 @@ bool check_is_vector_elem(Checker *c, AstNode *expr) {
 void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 	switch (op.kind) {
 	case Token_Pointer: { // Pointer address
+		if (o->mode == Addressing_Type) {
+			o->type = make_type_pointer(c->allocator, o->type);
+			return;
+		}
+
 		if (o->mode != Addressing_Variable ||
 		    check_is_expr_vector_index(c, o->expr) ||
 		    check_is_vector_elem(c, o->expr)) {
@@ -1600,6 +1608,12 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 
 	case Token_Maybe: { // Make maybe
 		Type *t = default_type(o->type);
+
+		if (o->mode == Addressing_Type) {
+			o->type = make_type_pointer(c->allocator, t);
+			return;
+		}
+
 		bool is_value =
 			o->mode == Addressing_Variable ||
 			o->mode == Addressing_Value ||

+ 5 - 0
src/checker/stmt.c

@@ -1095,6 +1095,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 	#if 1
 		// NOTE(bill): This must be handled here so it has access to the parent scope stuff
 		// e.g. using
+		if (pd->name->kind != AstNode_Ident) {
+			error_node(pd->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[pd->name->kind]));
+			break;
+		}
+
 		Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL, pd->tags);
 		e->identifier = pd->name;
 

+ 1 - 1
src/gb/gb.h

@@ -4112,7 +4112,7 @@ gb_inline i64 gb_atomic64_fetch_and(gbAtomic64 volatile *a, i64 operand) {
 
 gb_inline i64 gb_atomic64_fetch_or(gbAtomic64 volatile *a, i64 operand) {
 #if defined(GB_ARCH_64_BIT)
-	return _InterlockedAnd64(cast(i64 volatile *)a, operand);
+	return _InterlockedOr64(cast(i64 volatile *)a, operand);
 #elif GB_CPU_X86
 	i64 expected = a->value;
 	for (;;) {

+ 1 - 0
src/parser.c

@@ -1936,6 +1936,7 @@ AstNode *parse_simple_stmt(AstFile *f) {
 		    f->curr_token.kind == Token_enum ||
 		    f->curr_token.kind == Token_union ||
 		    f->curr_token.kind == Token_raw_union) {
+		// if (f->curr_token.kind == Token_type) {
 			Token token = f->curr_token;
 			if (token.kind == Token_type) {
 				next_token(f);

+ 1 - 1
src/tokenizer.c

@@ -109,7 +109,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_using,          "using"), \
 	TOKEN_KIND(Token_asm,            "asm"), \
 	TOKEN_KIND(Token_volatile,       "volatile"), \
-	TOKEN_KIND(Token_atomic,         "atomic"), \
+/* 	TOKEN_KIND(Token_atomic,         "atomic"),  */\
 	TOKEN_KIND(Token_push_allocator, "push_allocator"), \
 	TOKEN_KIND(Token_push_context,   "push_context"), \
 TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \