union_cast

This commit is contained in:
Ginger Bill
2016-10-16 21:31:06 +01:00
parent b9719df0ad
commit a675d3f94d
8 changed files with 292 additions and 53 deletions
+17 -5
View File
@@ -1,13 +1,25 @@
#import "fmt.odin" #import "fmt.odin"
main :: proc() { main :: proc() {
Thing :: struct { Entity :: union {
f: f32 Apple: int
a: any Banana: f32
Goat: struct {
x, y: int
z, w: f32
}
} }
t := Thing{1, "Hello"}
a := 123 as Entity.Apple
e: Entity = a
fmt.println(a)
fmt.printf("Here % %\n", 123, 2.0) if apple, ok := ^e union_cast ^Entity.Apple; ok {
apple^ = 321
e = apple^
}
apple, ok := e union_cast Entity.Apple
fmt.println(apple)
} }
+19 -15
View File
@@ -4,35 +4,38 @@
PRINT_BUF_SIZE :: 1<<12 PRINT_BUF_SIZE :: 1<<12
fprint :: proc(f: ^os.File, args: ..any) { fprint :: proc(f: ^os.File, args: ..any) -> int {
data: [PRINT_BUF_SIZE]byte data: [PRINT_BUF_SIZE]byte
buf := data[:0] buf := data[:0]
bprint(^buf, ..args) bprint(^buf, ..args)
os.write(f, buf) os.write(f, buf)
return buf.count
} }
fprintln :: proc(f: ^os.File, args: ..any) { fprintln :: proc(f: ^os.File, args: ..any) -> int {
data: [PRINT_BUF_SIZE]byte data: [PRINT_BUF_SIZE]byte
buf := data[:0] buf := data[:0]
bprintln(^buf, ..args) bprintln(^buf, ..args)
os.write(f, buf) os.write(f, buf)
return buf.count
} }
fprintf :: proc(f: ^os.File, fmt: string, args: ..any) { fprintf :: proc(f: ^os.File, fmt: string, args: ..any) -> int {
data: [PRINT_BUF_SIZE]byte data: [PRINT_BUF_SIZE]byte
buf := data[:0] buf := data[:0]
bprintf(^buf, fmt, ..args) bprintf(^buf, fmt, ..args)
os.write(f, buf) os.write(f, buf)
return buf.count
} }
print :: proc(args: ..any) { print :: proc(args: ..any) -> int {
fprint(os.stdout, ..args) return fprint(os.stdout, ..args)
} }
println :: proc(args: ..any) { println :: proc(args: ..any) -> int {
fprintln(os.stdout, ..args) return fprintln(os.stdout, ..args)
} }
printf :: proc(fmt: string, args: ..any) { printf :: proc(fmt: string, args: ..any) -> int {
fprintf(os.stdout, fmt, ..args) return fprintf(os.stdout, fmt, ..args)
} }
@@ -288,9 +291,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
using Type_Info using Type_Info
match type info : arg.type_info { match type info : arg.type_info {
case Named: case Named:
a: any a := make_any(info.base, arg.data)
a.type_info = info.base
a.data = arg.data
match type b : info.base { match type b : info.base {
case Struct: case Struct:
print_string_to_buffer(buf, info.name) print_string_to_buffer(buf, info.name)
@@ -491,7 +492,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
} }
bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) { bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
is_digit :: proc(r: rune) -> bool #inline { is_digit :: proc(r: rune) -> bool #inline {
return r >= #rune "0" && r <= #rune "9" return r >= #rune "0" && r <= #rune "9"
} }
@@ -552,10 +553,11 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) {
} }
print_string_to_buffer(buf, fmt[prev:]) print_string_to_buffer(buf, fmt[prev:])
return buf.count
} }
bprint :: proc(buf: ^[]byte, args: ..any) { bprint :: proc(buf: ^[]byte, args: ..any) -> int {
is_type_string :: proc(info: ^Type_Info) -> bool { is_type_string :: proc(info: ^Type_Info) -> bool {
using Type_Info using Type_Info
if info == nil { if info == nil {
@@ -580,9 +582,10 @@ bprint :: proc(buf: ^[]byte, args: ..any) {
print_any_to_buffer(buf, arg) print_any_to_buffer(buf, arg)
prev_string = is_string; prev_string = is_string;
} }
return buf.count
} }
bprintln :: proc(buf: ^[]byte, args: ..any) { bprintln :: proc(buf: ^[]byte, args: ..any) -> int {
for i := 0; i < args.count; i++ { for i := 0; i < args.count; i++ {
if i > 0 { if i > 0 {
append(buf, #rune " ") append(buf, #rune " ")
@@ -590,4 +593,5 @@ bprintln :: proc(buf: ^[]byte, args: ..any) {
print_any_to_buffer(buf, args[i]) print_any_to_buffer(buf, args[i])
} }
print_nl_to_buffer(buf) print_nl_to_buffer(buf)
return buf.count
} }
+98 -10
View File
@@ -933,11 +933,15 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
o->type = t_invalid; o->type = t_invalid;
return; return;
} }
// if (e->Variable.param) { #if 0
// o->mode = Addressing_Value; if (e->Variable.param) {
// } else { o->mode = Addressing_Value;
} else {
o->mode = Addressing_Variable; o->mode = Addressing_Variable;
// } }
#else
o->mode = Addressing_Variable;
#endif
break; break;
case Entity_TypeName: { case Entity_TypeName: {
@@ -1869,14 +1873,14 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
return; return;
} }
i64 otz = type_size_of(c->sizes, c->allocator, x->type); i64 srcz = type_size_of(c->sizes, c->allocator, x->type);
i64 ttz = type_size_of(c->sizes, c->allocator, type); i64 dstz = type_size_of(c->sizes, c->allocator, type);
if (otz != ttz) { if (srcz != dstz) {
gbString expr_str = expr_to_string(x->expr); gbString expr_str = expr_to_string(x->expr);
gbString type_str = type_to_string(type); gbString type_str = type_to_string(type);
defer (gb_string_free(expr_str)); defer (gb_string_free(expr_str));
defer (gb_string_free(type_str)); defer (gb_string_free(type_str));
error(ast_node_token(x->expr), "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, otz, ttz); error(ast_node_token(x->expr), "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz);
x->mode = Addressing_Invalid; x->mode = Addressing_Invalid;
return; return;
} }
@@ -1887,8 +1891,9 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
} else if (be->op.kind == Token_down_cast) { } else if (be->op.kind == Token_down_cast) {
check_expr(c, x, be->left); check_expr(c, x, be->left);
Type *type = check_type(c, be->right); Type *type = check_type(c, be->right);
if (x->mode == Addressing_Invalid) if (x->mode == Addressing_Invalid) {
return; return;
}
if (x->mode == Addressing_Constant) { if (x->mode == Addressing_Constant) {
gbString expr_str = expr_to_string(node); gbString expr_str = expr_to_string(node);
@@ -1927,7 +1932,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
return; return;
} }
if (!(is_type_struct(bdst) || is_type_struct(bdst))) { if (!(is_type_struct(bdst) || is_type_raw_union(bdst))) {
gbString expr_str = expr_to_string(node); gbString expr_str = expr_to_string(node);
defer (gb_string_free(expr_str)); defer (gb_string_free(expr_str));
error(ast_node_token(node), "Can only `down_cast` pointer to structs or unions: `%s`", expr_str); error(ast_node_token(node), "Can only `down_cast` pointer to structs or unions: `%s`", expr_str);
@@ -1947,6 +1952,83 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
x->mode = Addressing_Value; x->mode = Addressing_Value;
x->type = type; x->type = type;
return; return;
} else if (be->op.kind == Token_union_cast) {
check_expr(c, x, be->left);
Type *type = check_type(c, be->right);
if (x->mode == Addressing_Invalid) {
return;
}
if (x->mode == Addressing_Constant) {
gbString expr_str = expr_to_string(node);
defer (gb_string_free(expr_str));
error(ast_node_token(node), "Cannot `union_cast` a constant expression: `%s`", expr_str);
x->mode = Addressing_Invalid;
return;
}
if (is_type_untyped(x->type)) {
gbString expr_str = expr_to_string(node);
defer (gb_string_free(expr_str));
error(ast_node_token(node), "Cannot `union_cast` an untyped expression: `%s`", expr_str);
x->mode = Addressing_Invalid;
return;
}
b32 src_is_ptr = is_type_pointer(x->type);
b32 dst_is_ptr = is_type_pointer(type);
Type *src = type_deref(x->type);
Type *dst = type_deref(type);
Type *bsrc = base_type(src);
Type *bdst = base_type(dst);
if (src_is_ptr != dst_is_ptr) {
gbString src_type_str = type_to_string(x->type);
gbString dst_type_str = type_to_string(type);
defer (gb_string_free(src_type_str));
defer (gb_string_free(dst_type_str));
error(ast_node_token(node), "Invalid `union_cast` types: `%s` and `%s`", src_type_str, dst_type_str);
x->mode = Addressing_Invalid;
return;
}
if (!is_type_union(src)) {
error(ast_node_token(node), "`union_cast` can only operate on unions");
x->mode = Addressing_Invalid;
return;
}
b32 ok = false;
for (isize i = 1; i < bsrc->Record.field_count; i++) {
Entity *f = bsrc->Record.fields[i];
if (are_types_identical(f->type, dst)) {
ok = true;
break;
}
}
if (!ok) {
gbString expr_str = expr_to_string(node);
gbString dst_type_str = type_to_string(type);
defer (gb_string_free(expr_str));
defer (gb_string_free(dst_type_str));
error(ast_node_token(node), "Cannot `union_cast` `%s` to `%s`", expr_str, dst_type_str);
x->mode = Addressing_Invalid;
return;
}
Entity **variables = gb_alloc_array(c->allocator, Entity *, 2);
Token tok = make_token_ident(make_string(""));
variables[0] = make_entity_param(c->allocator, NULL, tok, type, false);
variables[1] = make_entity_param(c->allocator, NULL, tok, t_bool, false);
Type *tuple = make_type_tuple(c->allocator);
tuple->Tuple.variables = variables;
tuple->Tuple.variable_count = 2;
x->type = tuple;
x->mode = Addressing_Value;
return;
} }
check_expr(c, x, be->left); check_expr(c, x, be->left);
@@ -3723,6 +3805,12 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
o->expr = node; o->expr = node;
case_end; case_end;
case_ast_node(re, RunExpr, node);
// TODO(bill): Tag expressions
kind = check_expr_base(c, o, re->expr, type_hint);
o->expr = node;
case_end;
case_ast_node(ue, UnaryExpr, node); case_ast_node(ue, UnaryExpr, node);
check_expr(c, o, ue->expr); check_expr(c, o, ue->expr);
+117 -10
View File
@@ -840,7 +840,7 @@ ssaValue *ssa_make_instr_get_element_ptr(ssaProcedure *p, ssaValue *address,
i->GetElementPtr.indices[1] = index1; i->GetElementPtr.indices[1] = index1;
i->GetElementPtr.index_count = index_count; i->GetElementPtr.index_count = index_count;
i->GetElementPtr.elem_type = ssa_type(address); i->GetElementPtr.elem_type = ssa_type(address);
i->GetElementPtr.inbounds = inbounds;
GB_ASSERT_MSG(is_type_pointer(ssa_type(address)), GB_ASSERT_MSG(is_type_pointer(ssa_type(address)),
"%s", type_to_string(ssa_type(address))); "%s", type_to_string(ssa_type(address)));
return v; return v;
@@ -1169,8 +1169,12 @@ ssaValue *ssa_add_local_generated(ssaProcedure *proc, Type *type) {
ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) { ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) {
ssaValue *v = ssa_make_value_param(proc->module->allocator, proc, e); ssaValue *v = ssa_make_value_param(proc->module->allocator, proc, e);
#if 1
ssaValue *l = ssa_add_local(proc, e); ssaValue *l = ssa_add_local(proc, e);
ssa_emit_store(proc, l, v); ssa_emit_store(proc, l, v);
#else
ssa_module_add_value(proc->module, e, v);
#endif
return v; return v;
} }
@@ -1418,7 +1422,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
proc->curr_block = proc->decl_block; proc->curr_block = proc->decl_block;
ssa_emit_jump(proc, proc->entry_block); ssa_emit_jump(proc, proc->entry_block);
#if 0 #if 1
ssa_optimize_blocks(proc); ssa_optimize_blocks(proc);
ssa_build_referrers(proc); ssa_build_referrers(proc);
ssa_build_dom_tree(proc); ssa_build_dom_tree(proc);
@@ -1902,6 +1906,10 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
return make_string(""); return make_string("");
} }
ssaValue *ssa_emit_bitcast(ssaProcedure *proc, ssaValue *data, Type *type) {
return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, data, ssa_type(data), type));
}
ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_argument) { ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_argument) {
Type *src_type = ssa_type(value); Type *src_type = ssa_type(value);
@@ -2029,7 +2037,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
Type *tag_type = src_type; Type *tag_type = src_type;
Type *tag_type_ptr = make_type_pointer(allocator, tag_type); Type *tag_type_ptr = make_type_pointer(allocator, tag_type);
ssaValue *underlying = ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, data, t_rawptr, tag_type_ptr)); ssaValue *underlying = ssa_emit_bitcast(proc, data, tag_type_ptr);
ssa_emit_store(proc, underlying, value); ssa_emit_store(proc, underlying, value);
return ssa_emit_load(proc, parent); return ssa_emit_load(proc, parent);
@@ -2063,23 +2071,23 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
// Pointer <-> Pointer // Pointer <-> Pointer
if (is_type_pointer(src) && is_type_pointer(dst)) { if (is_type_pointer(src) && is_type_pointer(dst)) {
return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst)); return ssa_emit_bitcast(proc, value, dst);
} }
// proc <-> proc // proc <-> proc
if (is_type_proc(src) && is_type_proc(dst)) { if (is_type_proc(src) && is_type_proc(dst)) {
return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst)); return ssa_emit_bitcast(proc, value, dst);
} }
// pointer -> proc // pointer -> proc
if (is_type_pointer(src) && is_type_proc(dst)) { if (is_type_pointer(src) && is_type_proc(dst)) {
return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst)); return ssa_emit_bitcast(proc, value, dst);
} }
// proc -> pointer // proc -> pointer
if (is_type_proc(src) && is_type_pointer(dst)) { if (is_type_proc(src) && is_type_pointer(dst)) {
return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst)); return ssa_emit_bitcast(proc, value, dst);
} }
@@ -2180,7 +2188,7 @@ ssaValue *ssa_emit_transmute(ssaProcedure *proc, ssaValue *value, Type *t) {
i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst); i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
if (sz == dz) { if (sz == dz) {
return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_bitcast, value, src, dst)); return ssa_emit_bitcast(proc, value, dst);
} }
@@ -2205,6 +2213,94 @@ ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) {
return ssa_emit_conv(proc, head, t); return ssa_emit_conv(proc, head, t);
} }
ssaValue *ssa_emit_union_cast(ssaProcedure *proc, ssaValue *value, Type *tuple) {
GB_ASSERT(tuple->kind == Type_Tuple);
gbAllocator a = proc->module->allocator;
Type *src_type = ssa_type(value);
b32 is_ptr = is_type_pointer(src_type);
Type *t_bool_ptr = make_type_pointer(a, t_bool);
Type *t_int_ptr = make_type_pointer(a, t_int);
ssaValue *v = ssa_add_local_generated(proc, tuple);
if (is_ptr) {
Type *src = base_type(type_deref(src_type));
Type *src_ptr = src_type;
GB_ASSERT(is_type_union(src));
Type *dst_ptr = tuple->Tuple.variables[0]->type;
Type *dst = type_deref(dst_ptr);
ssaValue *tag = ssa_emit_load(proc, ssa_emit_struct_gep(proc, value, v_one32, t_int_ptr));
ssaValue *dst_tag = NULL;
for (isize i = 1; i < src->Record.field_count; i++) {
Entity *f = src->Record.fields[i];
if (are_types_identical(f->type, dst)) {
dst_tag = ssa_make_const_int(a, i);
break;
}
}
GB_ASSERT(dst_tag != NULL);
ssaBlock *ok_block = ssa_add_block(proc, NULL, "union_cast.ok");
ssaBlock *end_block = ssa_add_block(proc, NULL, "union_cast.end");
ssaValue *cond = ssa_emit_comp(proc, Token_CmpEq, tag, dst_tag);
ssa_emit_if(proc, cond, ok_block, end_block);
proc->curr_block = ok_block;
ssaValue *gep0 = ssa_emit_struct_gep(proc, v, v_zero32, make_type_pointer(a, dst_ptr));
ssaValue *gep1 = ssa_emit_struct_gep(proc, v, v_one32, t_bool_ptr);
ssaValue *data = ssa_emit_conv(proc, value, dst_ptr);
ssa_emit_store(proc, gep0, data);
ssa_emit_store(proc, gep1, v_true);
ssa_emit_jump(proc, end_block);
proc->curr_block = end_block;
} else {
Type *src = base_type(src_type);
GB_ASSERT(is_type_union(src));
Type *dst = tuple->Tuple.variables[0]->type;
Type *dst_ptr = make_type_pointer(a, dst);
ssaValue *tag = ssa_emit_struct_ev(proc, value, 1, t_int);
ssaValue *dst_tag = NULL;
for (isize i = 1; i < src->Record.field_count; i++) {
Entity *f = src->Record.fields[i];
if (are_types_identical(f->type, dst)) {
dst_tag = ssa_make_const_int(a, i);
break;
}
}
GB_ASSERT(dst_tag != NULL);
// HACK(bill): This is probably not very efficient
ssaValue *union_copy = ssa_add_local_generated(proc, src_type);
ssa_emit_store(proc, union_copy, value);
ssaBlock *ok_block = ssa_add_block(proc, NULL, "union_cast.ok");
ssaBlock *end_block = ssa_add_block(proc, NULL, "union_cast.end");
ssaValue *cond = ssa_emit_comp(proc, Token_CmpEq, tag, dst_tag);
ssa_emit_if(proc, cond, ok_block, end_block);
proc->curr_block = ok_block;
ssaValue *gep0 = ssa_emit_struct_gep(proc, v, v_zero32, dst_ptr);
ssaValue *gep1 = ssa_emit_struct_gep(proc, v, v_one32, t_bool_ptr);
ssaValue *data = ssa_emit_load(proc, ssa_emit_conv(proc, union_copy, dst_ptr));
ssa_emit_store(proc, gep0, data);
ssa_emit_store(proc, gep1, v_true);
ssa_emit_jump(proc, end_block);
proc->curr_block = end_block;
}
return ssa_emit_load(proc, v);
}
void ssa_build_cond(ssaProcedure *proc, AstNode *cond, ssaBlock *true_block, ssaBlock *false_block); void ssa_build_cond(ssaProcedure *proc, AstNode *cond, ssaBlock *true_block, ssaBlock *false_block);
ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) { ssaValue *ssa_emit_logical_binary_expr(ssaProcedure *proc, AstNode *expr) {
@@ -2325,6 +2421,7 @@ ssaValue *ssa_find_implicit_value_backing(ssaProcedure *proc, ImplicitValueId id
ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv) { ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv) {
expr = unparen_expr(expr);
switch (expr->kind) { switch (expr->kind) {
case_ast_node(bl, BasicLit, expr); case_ast_node(bl, BasicLit, expr);
GB_PANIC("Non-constant basic literal"); GB_PANIC("Non-constant basic literal");
@@ -2350,13 +2447,17 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
if (v->kind == ssaValue_Proc) { if (v->kind == ssaValue_Proc) {
return v; return v;
} }
// if (e->kind == Entity_Variable && e->Variable.param) {
// return v;
// }
return ssa_emit_load(proc, v); return ssa_emit_load(proc, v);
} }
return NULL; return NULL;
case_end; case_end;
case_ast_node(pe, ParenExpr, expr); case_ast_node(re, RunExpr, expr);
return ssa_build_single_expr(proc, unparen_expr(expr), tv); // TODO(bill): Run Expression
return ssa_build_single_expr(proc, re->expr, tv);
case_end; case_end;
case_ast_node(de, DerefExpr, expr); case_ast_node(de, DerefExpr, expr);
@@ -2364,6 +2465,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case_end; case_end;
case_ast_node(se, SelectorExpr, expr); case_ast_node(se, SelectorExpr, expr);
TypeAndValue *tav = map_get(&proc->module->info->types, hash_pointer(expr));
GB_ASSERT(tav != NULL);
return ssa_lvalue_load(proc, ssa_build_addr(proc, expr)); return ssa_lvalue_load(proc, ssa_build_addr(proc, expr));
case_end; case_end;
@@ -2441,6 +2544,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssa_emit_comment(proc, make_string("cast - down_cast")); ssa_emit_comment(proc, make_string("cast - down_cast"));
return ssa_emit_down_cast(proc, ssa_build_expr(proc, be->left), tv->type); return ssa_emit_down_cast(proc, ssa_build_expr(proc, be->left), tv->type);
case Token_union_cast:
ssa_emit_comment(proc, make_string("cast - union_cast"));
return ssa_emit_union_cast(proc, ssa_build_expr(proc, be->left), tv->type);
default: default:
GB_PANIC("Invalid binary expression"); GB_PANIC("Invalid binary expression");
break; break;
+2 -1
View File
@@ -1,4 +1,4 @@
/* gb.h - v0.26c - Ginger Bill's C Helper Library - public domain /* gb.h - v0.26d - Ginger Bill's C Helper Library - public domain
- no warranty implied; use at your own risk - no warranty implied; use at your own risk
This is a single header file with a bunch of useful stuff This is a single header file with a bunch of useful stuff
@@ -58,6 +58,7 @@ TODOS
- More date & time functions - More date & time functions
VERSION HISTORY VERSION HISTORY
0.26d - Minor changes to how gbFile works
0.26c - gb_str_to_f* fix 0.26c - gb_str_to_f* fix
0.26b - Minor fixes 0.26b - Minor fixes
0.26a - gbString Fix 0.26a - gbString Fix
+3 -1
View File
@@ -26,6 +26,7 @@ i32 win32_exec_command_line_app(char *name, char *fmt, ...) {
va_start(va, fmt); va_start(va, fmt);
cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va); cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va);
va_end(va); va_end(va);
// gb_printf("%.*s\n", cast(int)cmd_len, cmd_line);
tmp = gb_temp_arena_memory_begin(&string_buffer_arena); tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
defer (gb_temp_arena_memory_end(tmp)); defer (gb_temp_arena_memory_end(tmp));
@@ -173,7 +174,7 @@ int main(int argc, char **argv) {
return exit_code; return exit_code;
} }
#if 1
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html // For more arguments: http://llvm.org/docs/CommandGuide/llc.html
exit_code = win32_exec_command_line_app("llvm-llc", exit_code = win32_exec_command_line_app("llvm-llc",
"%.*sbin/llc %.*s.bc -filetype=obj -O%d " "%.*sbin/llc %.*s.bc -filetype=obj -O%d "
@@ -214,6 +215,7 @@ int main(int argc, char **argv) {
if (run_output) { if (run_output) {
win32_exec_command_line_app("odin run", "%.*s.exe", cast(int)base_name_len, output_name); win32_exec_command_line_app("odin run", "%.*s.exe", cast(int)base_name_len, output_name);
} }
#endif
#endif #endif
#endif #endif
#endif #endif
+30 -8
View File
@@ -122,6 +122,7 @@ AstNodeArray make_ast_node_array(AstFile *f) {
AST_NODE_KIND(_ExprBegin, "", struct{}) \ AST_NODE_KIND(_ExprBegin, "", struct{}) \
AST_NODE_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \ AST_NODE_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \
AST_NODE_KIND(TagExpr, "tag expression", struct { Token token, name; AstNode *expr; }) \ AST_NODE_KIND(TagExpr, "tag expression", struct { Token token, name; AstNode *expr; }) \
AST_NODE_KIND(RunExpr, "run expression", struct { Token token, name; AstNode *expr; }) \
AST_NODE_KIND(UnaryExpr, "unary expression", struct { Token op; AstNode *expr; }) \ AST_NODE_KIND(UnaryExpr, "unary expression", struct { Token op; AstNode *expr; }) \
AST_NODE_KIND(BinaryExpr, "binary expression", struct { Token op; AstNode *left, *right; } ) \ AST_NODE_KIND(BinaryExpr, "binary expression", struct { Token op; AstNode *left, *right; } ) \
AST_NODE_KIND(ParenExpr, "parentheses expression", struct { AstNode *expr; Token open, close; }) \ AST_NODE_KIND(ParenExpr, "parentheses expression", struct { AstNode *expr; Token open, close; }) \
@@ -376,6 +377,8 @@ Token ast_node_token(AstNode *node) {
return node->CompoundLit.open; return node->CompoundLit.open;
case AstNode_TagExpr: case AstNode_TagExpr:
return node->TagExpr.token; return node->TagExpr.token;
case AstNode_RunExpr:
return node->RunExpr.token;
case AstNode_BadExpr: case AstNode_BadExpr:
return node->BadExpr.begin; return node->BadExpr.begin;
case AstNode_UnaryExpr: case AstNode_UnaryExpr:
@@ -512,6 +515,15 @@ AstNode *make_tag_expr(AstFile *f, Token token, Token name, AstNode *expr) {
return result; return result;
} }
AstNode *make_run_expr(AstFile *f, Token token, Token name, AstNode *expr) {
AstNode *result = make_node(f, AstNode_RunExpr);
result->RunExpr.token = token;
result->RunExpr.name = name;
result->RunExpr.expr = expr;
return result;
}
AstNode *make_tag_stmt(AstFile *f, Token token, Token name, AstNode *stmt) { AstNode *make_tag_stmt(AstFile *f, Token token, Token name, AstNode *stmt) {
AstNode *result = make_node(f, AstNode_TagStmt); AstNode *result = make_node(f, AstNode_TagStmt);
result->TagStmt.token = token; result->TagStmt.token = token;
@@ -1352,9 +1364,9 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
} }
case Token_Hash: { case Token_Hash: {
operand = parse_tag_expr(f, NULL); Token token = expect_token(f, Token_Hash);
String name = operand->TagExpr.name.string; Token name = expect_token(f, Token_Identifier);
if (name == "rune") { if (name.string == "rune") {
if (f->curr_token.kind == Token_String) { if (f->curr_token.kind == Token_String) {
Token *s = &f->curr_token; Token *s = &f->curr_token;
@@ -1366,20 +1378,28 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
expect_token(f, Token_String); expect_token(f, Token_String);
} }
operand = parse_operand(f, lhs); operand = parse_operand(f, lhs);
} else if (name == "file") { } else if (name.string == "file") {
Token token = operand->TagExpr.name; Token token = name;
token.kind = Token_String; token.kind = Token_String;
token.string = token.pos.file; token.string = token.pos.file;
return make_basic_lit(f, token); return make_basic_lit(f, token);
} else if (name == "line") { } else if (name.string == "line") {
Token token = operand->TagExpr.name; Token token = name;
token.kind = Token_Integer; token.kind = Token_Integer;
char *str = gb_alloc_array(gb_arena_allocator(&f->arena), char, 20); char *str = gb_alloc_array(gb_arena_allocator(&f->arena), char, 20);
gb_i64_to_str(token.pos.line, str, 10); gb_i64_to_str(token.pos.line, str, 10);
token.string = make_string(str); token.string = make_string(str);
return make_basic_lit(f, token); return make_basic_lit(f, token);
} else if (name.string == "run") {
AstNode *expr = parse_expr(f, false);
operand = make_run_expr(f, token, name, expr);
if (unparen_expr(expr)->kind != AstNode_CallExpr) {
error(ast_node_token(expr), "#run can only be applied to procedure calls");
operand = make_bad_expr(f, token, f->curr_token);
}
warning(token, "#run is not yet implemented");
} else { } else {
operand->TagExpr.expr = parse_expr(f, false); operand = make_tag_expr(f, token, name, parse_expr(f, false));
} }
return operand; return operand;
} }
@@ -1658,6 +1678,7 @@ i32 token_precedence(Token t) {
case Token_as: case Token_as:
case Token_transmute: case Token_transmute:
case Token_down_cast: case Token_down_cast:
case Token_union_cast:
return 7; return 7;
} }
@@ -1705,6 +1726,7 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
case Token_as: case Token_as:
case Token_transmute: case Token_transmute:
case Token_down_cast: case Token_down_cast:
case Token_union_cast:
right = parse_type(f); right = parse_type(f);
break; break;
+6 -3
View File
@@ -30,9 +30,10 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
TOKEN_KIND(Token_Shl, "<<"), \ TOKEN_KIND(Token_Shl, "<<"), \
TOKEN_KIND(Token_Shr, ">>"), \ TOKEN_KIND(Token_Shr, ">>"), \
\ \
TOKEN_KIND(Token_as, "as"), \ TOKEN_KIND(Token_as, "as"), \
TOKEN_KIND(Token_transmute, "transmute"), \ TOKEN_KIND(Token_transmute, "transmute"), \
TOKEN_KIND(Token_down_cast, "down_cast"), \ TOKEN_KIND(Token_down_cast, "down_cast"), \
TOKEN_KIND(Token_union_cast, "union_cast"), \
\ \
TOKEN_KIND(Token_Prime, "'"), \ TOKEN_KIND(Token_Prime, "'"), \
TOKEN_KIND(Token_DoublePrime, "''"), \ TOKEN_KIND(Token_DoublePrime, "''"), \
@@ -635,6 +636,8 @@ Token tokenizer_get_token(Tokenizer *t) {
token.kind = Token_transmute; token.kind = Token_transmute;
} else if (token.string == token_strings[Token_down_cast]) { } else if (token.string == token_strings[Token_down_cast]) {
token.kind = Token_down_cast; token.kind = Token_down_cast;
} else if (token.string == token_strings[Token_union_cast]) {
token.kind = Token_union_cast;
} else { } else {
for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) { for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
if (token.string == token_strings[k]) { if (token.string == token_strings[k]) {