mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-13 14:53:34 +00:00
Fix issue #10
This commit is contained in:
134
code/demo.odin
134
code/demo.odin
@@ -1,61 +1,85 @@
|
||||
#import "atomic.odin";
|
||||
#import "fmt.odin";
|
||||
#import "hash.odin";
|
||||
#import "math.odin";
|
||||
#import "mem.odin";
|
||||
#import "opengl.odin";
|
||||
#import "os.odin";
|
||||
#import win32 "sys/windows.odin";
|
||||
#import "sync.odin";
|
||||
#import "utf8.odin";
|
||||
|
||||
T :: struct { x, y: int };
|
||||
thread_local t: T;
|
||||
fgetc :: proc(fd : os.Handle) -> ?byte
|
||||
{
|
||||
c : [1]byte;
|
||||
|
||||
main :: proc() {
|
||||
immutable using t := T{123, 321};
|
||||
fmt.println(t);
|
||||
if bytes_read, _ := os.read(fd, c[:]); bytes_read == 0
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
// foo :: proc(x: ^i32) -> (int, int) {
|
||||
// fmt.println("^int");
|
||||
// return 123, int(x^);
|
||||
// }
|
||||
// foo :: proc(x: rawptr) {
|
||||
// fmt.println("rawptr");
|
||||
// }
|
||||
|
||||
// THINGI :: 14451;
|
||||
// THINGF :: 14451.1;
|
||||
|
||||
// a: i32 = 111111;
|
||||
// b: f32;
|
||||
// c: rawptr;
|
||||
// fmt.println(foo(^a));
|
||||
// foo(^b);
|
||||
// foo(c);
|
||||
// // foo(nil);
|
||||
// atomic.store(^a, 1);
|
||||
|
||||
// foo :: proc() {
|
||||
// fmt.printf("Zero args\n");
|
||||
// }
|
||||
// foo :: proc(i: int) {
|
||||
// fmt.printf("int arg, i=%d\n", i);
|
||||
// }
|
||||
// foo :: proc(f: f64) {
|
||||
// i := int(f);
|
||||
// fmt.printf("f64 arg, f=%d\n", i);
|
||||
// }
|
||||
|
||||
// foo();
|
||||
// // foo(THINGI);
|
||||
// foo(THINGF);
|
||||
// foo(int(THINGI));
|
||||
// fmt.println(THINGI);
|
||||
// fmt.println(THINGF);
|
||||
|
||||
// f: proc();
|
||||
// f = foo;
|
||||
// f();
|
||||
return c[0];
|
||||
}
|
||||
|
||||
main :: proc ()
|
||||
{
|
||||
b := fgetc(os.stdin);
|
||||
|
||||
if bv, ok := b?; ok
|
||||
{
|
||||
fmt.println(b);
|
||||
}
|
||||
}
|
||||
// #import "atomic.odin";
|
||||
// #import "fmt.odin";
|
||||
// #import "hash.odin";
|
||||
// #import "math.odin";
|
||||
// #import "mem.odin";
|
||||
// #import "opengl.odin";
|
||||
// #import "os.odin";
|
||||
// #import win32 "sys/windows.odin";
|
||||
// #import "sync.odin";
|
||||
// #import "utf8.odin";
|
||||
|
||||
// T :: struct { x, y: int };
|
||||
// thread_local t: T;
|
||||
|
||||
// main :: proc() {
|
||||
// immutable using t := T{123, 321};
|
||||
// fmt.println(t);
|
||||
|
||||
|
||||
// // foo :: proc(x: ^i32) -> (int, int) {
|
||||
// // fmt.println("^int");
|
||||
// // return 123, int(x^);
|
||||
// // }
|
||||
// // foo :: proc(x: rawptr) {
|
||||
// // fmt.println("rawptr");
|
||||
// // }
|
||||
|
||||
// // THINGI :: 14451;
|
||||
// // THINGF :: 14451.1;
|
||||
|
||||
// // a: i32 = 111111;
|
||||
// // b: f32;
|
||||
// // c: rawptr;
|
||||
// // fmt.println(foo(^a));
|
||||
// // foo(^b);
|
||||
// // foo(c);
|
||||
// // // foo(nil);
|
||||
// // atomic.store(^a, 1);
|
||||
|
||||
// // foo :: proc() {
|
||||
// // fmt.printf("Zero args\n");
|
||||
// // }
|
||||
// // foo :: proc(i: int) {
|
||||
// // fmt.printf("int arg, i=%d\n", i);
|
||||
// // }
|
||||
// // foo :: proc(f: f64) {
|
||||
// // i := int(f);
|
||||
// // fmt.printf("f64 arg, f=%d\n", i);
|
||||
// // }
|
||||
|
||||
// // foo();
|
||||
// // // foo(THINGI);
|
||||
// // foo(THINGF);
|
||||
// // foo(int(THINGI));
|
||||
// // fmt.println(THINGI);
|
||||
// // fmt.println(THINGF);
|
||||
|
||||
// // f: proc();
|
||||
// // f = foo;
|
||||
// // f();
|
||||
// }
|
||||
|
||||
@@ -40,6 +40,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
||||
}
|
||||
t = default_type(t);
|
||||
}
|
||||
GB_ASSERT(is_type_typed(t));
|
||||
e->type = t;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,6 +252,7 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
|
||||
return;
|
||||
}
|
||||
target_type = default_type(operand->type);
|
||||
GB_ASSERT(is_type_typed(target_type));
|
||||
add_type_info_type(c, type);
|
||||
add_type_info_type(c, target_type);
|
||||
}
|
||||
|
||||
@@ -549,8 +549,17 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
if (rs->results.count == 0) {
|
||||
error_node(node, "Expected %td return values, got 0", result_count);
|
||||
} else {
|
||||
// TokenPos pos = rs->token.pos;
|
||||
// if (pos.line == 10) {
|
||||
// gb_printf_err("%s\n", type_to_string(variables[0]->type));
|
||||
// }
|
||||
check_init_variables(c, variables, result_count,
|
||||
rs->results, str_lit("return statement"));
|
||||
// if (pos.line == 10) {
|
||||
// AstNode *x = rs->results.e[0];
|
||||
// gb_printf_err("%s\n", expr_to_string(x));
|
||||
// gb_printf_err("%s\n", type_to_string(type_of_expr(&c->info, x)));
|
||||
// }
|
||||
}
|
||||
} else if (rs->results.count > 0) {
|
||||
error_node(rs->results.e[0], "No return values expected");
|
||||
|
||||
3
src/ir.c
3
src/ir.c
@@ -4411,7 +4411,8 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
// No return values
|
||||
} else if (return_count == 1) {
|
||||
Entity *e = return_type_tuple->variables[0];
|
||||
v = ir_emit_conv(proc, ir_build_expr(proc, rs->results.e[0]), e->type);
|
||||
v = ir_build_expr(proc, rs->results.e[0]);
|
||||
v = ir_emit_conv(proc, v, e->type);
|
||||
} else {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||
|
||||
|
||||
@@ -141,58 +141,59 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
i64 word_bits = 8*s.word_size;
|
||||
GB_ASSERT_NOT_NULL(t);
|
||||
t = default_type(t);
|
||||
// GB_ASSERT(is_type_typed(t));
|
||||
|
||||
switch (t->kind) {
|
||||
case Type_Basic:
|
||||
switch (t->Basic.kind) {
|
||||
case Basic_bool: ir_fprintf(f, "i1"); break;
|
||||
case Basic_i8: ir_fprintf(f, "i8"); break;
|
||||
case Basic_u8: ir_fprintf(f, "i8"); break;
|
||||
case Basic_i16: ir_fprintf(f, "i16"); break;
|
||||
case Basic_u16: ir_fprintf(f, "i16"); break;
|
||||
case Basic_i32: ir_fprintf(f, "i32"); break;
|
||||
case Basic_u32: ir_fprintf(f, "i32"); break;
|
||||
case Basic_i64: ir_fprintf(f, "i64"); break;
|
||||
case Basic_u64: ir_fprintf(f, "i64"); break;
|
||||
// case Basic_i128: ir_fprintf(f, "i128"); break;
|
||||
// case Basic_u128: ir_fprintf(f, "i128"); break;
|
||||
// case Basic_f16: ir_fprintf(f, "half"); break;
|
||||
case Basic_f32: ir_fprintf(f, "float"); break;
|
||||
case Basic_f64: ir_fprintf(f, "double"); break;
|
||||
// case Basic_f128: ir_fprintf(f, "fp128"); break;
|
||||
case Basic_rawptr: ir_fprintf(f, "%%..rawptr"); break;
|
||||
case Basic_string: ir_fprintf(f, "%%..string"); break;
|
||||
case Basic_uint: ir_fprintf(f, "i%lld", word_bits); break;
|
||||
case Basic_int: ir_fprintf(f, "i%lld", word_bits); break;
|
||||
case Basic_any: ir_fprintf(f, "%%..any"); break;
|
||||
case Basic_bool: ir_fprintf(f, "i1"); return;
|
||||
case Basic_i8: ir_fprintf(f, "i8"); return;
|
||||
case Basic_u8: ir_fprintf(f, "i8"); return;
|
||||
case Basic_i16: ir_fprintf(f, "i16"); return;
|
||||
case Basic_u16: ir_fprintf(f, "i16"); return;
|
||||
case Basic_i32: ir_fprintf(f, "i32"); return;
|
||||
case Basic_u32: ir_fprintf(f, "i32"); return;
|
||||
case Basic_i64: ir_fprintf(f, "i64"); return;
|
||||
case Basic_u64: ir_fprintf(f, "i64"); return;
|
||||
// case Basic_i128: ir_fprintf(f, "i128"); return;
|
||||
// case Basic_u128: ir_fprintf(f, "i128"); return;
|
||||
// case Basic_f16: ir_fprintf(f, "half"); return;
|
||||
case Basic_f32: ir_fprintf(f, "float"); return;
|
||||
case Basic_f64: ir_fprintf(f, "double"); return;
|
||||
// case Basic_f128: ir_fprintf(f, "fp128"); return;
|
||||
case Basic_rawptr: ir_fprintf(f, "%%..rawptr"); return;
|
||||
case Basic_string: ir_fprintf(f, "%%..string"); return;
|
||||
case Basic_uint: ir_fprintf(f, "i%lld", word_bits); return;
|
||||
case Basic_int: ir_fprintf(f, "i%lld", word_bits); return;
|
||||
case Basic_any: ir_fprintf(f, "%%..any"); return;
|
||||
}
|
||||
break;
|
||||
case Type_Pointer:
|
||||
ir_print_type(f, m, t->Pointer.elem);
|
||||
ir_fprintf(f, "*");
|
||||
break;
|
||||
return;
|
||||
case Type_Maybe:
|
||||
ir_fprintf(f, "{");
|
||||
ir_print_type(f, m, t->Maybe.elem);
|
||||
ir_fprintf(f, ", ");
|
||||
ir_print_type(f, m, t_bool);
|
||||
ir_fprintf(f, "}");
|
||||
break;
|
||||
return;
|
||||
case Type_Array:
|
||||
ir_fprintf(f, "[%lld x ", t->Array.count);
|
||||
ir_print_type(f, m, t->Array.elem);
|
||||
ir_fprintf(f, "]");
|
||||
break;
|
||||
return;
|
||||
case Type_Vector:
|
||||
ir_fprintf(f, "<%lld x ", t->Vector.count);
|
||||
ir_print_type(f, m, t->Vector.elem);
|
||||
ir_fprintf(f, ">");
|
||||
break;
|
||||
return;
|
||||
case Type_Slice:
|
||||
ir_fprintf(f, "{");
|
||||
ir_print_type(f, m, t->Slice.elem);
|
||||
ir_fprintf(f, "*, i%lld, i%lld}", word_bits, word_bits);
|
||||
break;
|
||||
return;
|
||||
case Type_Record: {
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct:
|
||||
@@ -210,24 +211,24 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
if (t->Record.struct_is_packed) {
|
||||
ir_fprintf(f, ">");
|
||||
}
|
||||
break;
|
||||
return;
|
||||
case TypeRecord_Union: {
|
||||
// NOTE(bill): The zero size array is used to fix the alignment used in a structure as
|
||||
// LLVM takes the first element's alignment as the entire alignment (like C)
|
||||
i64 size_of_union = type_size_of(s, heap_allocator(), t) - s.word_size;
|
||||
i64 align_of_union = type_align_of(s, heap_allocator(), t);
|
||||
ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8], i%lld}", align_of_union, size_of_union, word_bits);
|
||||
} break;
|
||||
} return;
|
||||
case TypeRecord_RawUnion: {
|
||||
// NOTE(bill): The zero size array is used to fix the alignment used in a structure as
|
||||
// LLVM takes the first element's alignment as the entire alignment (like C)
|
||||
i64 size_of_union = type_size_of(s, heap_allocator(), t);
|
||||
i64 align_of_union = type_align_of(s, heap_allocator(), t);
|
||||
ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8]}", align_of_union, size_of_union);
|
||||
} break;
|
||||
} return;
|
||||
case TypeRecord_Enum:
|
||||
ir_print_type(f, m, base_enum_type(t));
|
||||
break;
|
||||
return;
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -240,7 +241,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
} else {
|
||||
ir_print_type(f, m, base_type(t));
|
||||
}
|
||||
break;
|
||||
return;
|
||||
case Type_Tuple:
|
||||
if (t->Tuple.variable_count == 1) {
|
||||
ir_print_type(f, m, t->Tuple.variables[0]->type);
|
||||
@@ -254,7 +255,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
}
|
||||
ir_fprintf(f, "}");
|
||||
}
|
||||
break;
|
||||
return;
|
||||
case Type_Proc: {
|
||||
if (t->Proc.result_count == 0) {
|
||||
ir_fprintf(f, "void");
|
||||
@@ -270,7 +271,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
|
||||
ir_print_type(f, m, params->variables[i]->type);
|
||||
}
|
||||
ir_fprintf(f, ")*");
|
||||
} break;
|
||||
} return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -684,7 +685,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
} break;
|
||||
|
||||
case irInstr_Store: {
|
||||
Type *type = ir_type(instr->Store.value);
|
||||
Type *type = type_deref(ir_type(instr->Store.address));
|
||||
ir_fprintf(f, "store ");
|
||||
ir_print_type(f, m, type);
|
||||
ir_fprintf(f, " ");
|
||||
|
||||
54
src/parser.c
54
src/parser.c
@@ -1096,6 +1096,7 @@ AstNode *make_import_decl(AstFile *f, Token token, bool is_import, Token relpath
|
||||
|
||||
|
||||
bool next_token(AstFile *f) {
|
||||
Token prev = f->curr_token;
|
||||
if (f->curr_token_index+1 < f->tokens.count) {
|
||||
if (f->curr_token.kind != Token_Comment) {
|
||||
f->prev_token = f->curr_token;
|
||||
@@ -1959,8 +1960,8 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) {
|
||||
}
|
||||
|
||||
// NOTE(bill): result == priority
|
||||
i32 token_precedence(Token t) {
|
||||
switch (t.kind) {
|
||||
i32 token_precedence(TokenKind t) {
|
||||
switch (t) {
|
||||
case Token_CmpOr:
|
||||
return 1;
|
||||
case Token_CmpAnd:
|
||||
@@ -1996,11 +1997,11 @@ i32 token_precedence(Token t) {
|
||||
|
||||
AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
|
||||
AstNode *expression = parse_unary_expr(f, lhs);
|
||||
for (i32 prec = token_precedence(f->curr_token); prec >= prec_in; prec--) {
|
||||
for (i32 prec = token_precedence(f->curr_token.kind); prec >= prec_in; prec--) {
|
||||
for (;;) {
|
||||
AstNode *right;
|
||||
Token op = f->curr_token;
|
||||
i32 op_prec = token_precedence(op);
|
||||
i32 op_prec = token_precedence(op.kind);
|
||||
if (op_prec != prec) {
|
||||
break;
|
||||
}
|
||||
@@ -2293,35 +2294,22 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis) {
|
||||
|
||||
|
||||
u32 parse_field_prefixes(AstFile *f) {
|
||||
i32 using_count = 0;
|
||||
i32 no_alias_count = 0;
|
||||
i32 using_count = 0;
|
||||
i32 no_alias_count = 0;
|
||||
i32 immutable_count = 0;
|
||||
|
||||
while (f->curr_token.kind == Token_using ||
|
||||
f->curr_token.kind == Token_no_alias ||
|
||||
f->curr_token.kind == Token_immutable) {
|
||||
if (allow_token(f, Token_using)) {
|
||||
using_count += 1;
|
||||
}
|
||||
if (allow_token(f, Token_no_alias)) {
|
||||
no_alias_count += 1;
|
||||
}
|
||||
if (allow_token(f, Token_immutable)) {
|
||||
immutable_count += 1;
|
||||
bool loop = true;
|
||||
while (loop) {
|
||||
switch (f->curr_token.kind) {
|
||||
default: loop = false; break;
|
||||
case Token_using: using_count += 1; next_token(f); break;
|
||||
case Token_no_alias: no_alias_count += 1; next_token(f); break;
|
||||
case Token_immutable: immutable_count += 1; next_token(f); break;
|
||||
}
|
||||
}
|
||||
if (using_count > 1) {
|
||||
syntax_error(f->curr_token, "Multiple `using` in this field list");
|
||||
using_count = 1;
|
||||
}
|
||||
if (no_alias_count > 1) {
|
||||
syntax_error(f->curr_token, "Multiple `no_alias` in this field list");
|
||||
no_alias_count = 1;
|
||||
}
|
||||
if (immutable_count > 1) {
|
||||
syntax_error(f->curr_token, "Multiple `immutable` in this field list");
|
||||
immutable_count = 1;
|
||||
}
|
||||
if (using_count > 1) syntax_error(f->curr_token, "Multiple `using` in this field list");
|
||||
if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple `no_alias` in this field list");
|
||||
if (immutable_count > 1) syntax_error(f->curr_token, "Multiple `immutable` in this field list");
|
||||
|
||||
|
||||
u32 field_flags = 0;
|
||||
@@ -3095,16 +3083,14 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
case AstNode_ValueDecl:
|
||||
if (!node->ValueDecl.is_var) {
|
||||
syntax_error(token, "`using` may not be applied to constant declarations");
|
||||
return make_bad_stmt(f, token, f->curr_token);
|
||||
} else {
|
||||
if (f->curr_proc == NULL) {
|
||||
syntax_error(token, "`using` is not allowed at the file scope");
|
||||
} else {
|
||||
node->ValueDecl.flags |= VarDeclFlag_using;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
break;
|
||||
return node;
|
||||
case AstNode_ExprStmt: {
|
||||
AstNode *e = unparen_expr(node->ExprStmt.expr);
|
||||
while (e->kind == AstNode_SelectorExpr) {
|
||||
@@ -3127,11 +3113,10 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
if (node->kind == AstNode_ValueDecl) {
|
||||
if (!node->ValueDecl.is_var) {
|
||||
syntax_error(token, "`immutable` may not be applied to constant declarations");
|
||||
return make_bad_stmt(f, token, f->curr_token);
|
||||
} else {
|
||||
node->ValueDecl.flags |= VarDeclFlag_immutable;
|
||||
return node;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
syntax_error(token, "`immutable` may only be applied to a variable declaration");
|
||||
return make_bad_stmt(f, token, f->curr_token);
|
||||
@@ -3144,7 +3129,6 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
if (node->kind == AstNode_ValueDecl) {
|
||||
if (!node->ValueDecl.is_var) {
|
||||
syntax_error(token, "`thread_local` may not be applied to constant declarations");
|
||||
return make_bad_stmt(f, token, f->curr_token);
|
||||
}
|
||||
if (f->curr_proc != NULL) {
|
||||
syntax_error(token, "`thread_local` is only allowed at the file scope");
|
||||
|
||||
Reference in New Issue
Block a user