mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 21:10:30 +00:00
v0.0.4 - odin build_dll, atomic.odin, sync.odin
This commit is contained in:
@@ -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,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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr) {
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 (;;) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"), \
|
||||
|
||||
Reference in New Issue
Block a user