diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.c | 34 | ||||
| -rw-r--r-- | src/checker.c | 8 | ||||
| -rw-r--r-- | src/gb/gb.h | 10 | ||||
| -rw-r--r-- | src/ir.c | 31 | ||||
| -rw-r--r-- | src/parser.c | 17 | ||||
| -rw-r--r-- | src/tokenizer.c | 6 |
6 files changed, 83 insertions, 23 deletions
diff --git a/src/check_expr.c b/src/check_expr.c index 18c75ac9d..e8318a071 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1519,12 +1519,7 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { return; } - bool is_value = - o->mode == Addressing_Variable || - o->mode == Addressing_Value || - o->mode == Addressing_Constant; - - if (!is_value || is_type_untyped(t)) { + if (!is_operand_value(*o) || is_type_untyped(t)) { if (ast_node_expect(node, AstNode_UnaryExpr)) { ast_node(ue, UnaryExpr, node); gbString str = expr_to_string(ue->expr); @@ -2536,6 +2531,8 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h // TODO(bill): This is the rule I need? if (sel.indirect || operand->mode != Addressing_Value) { operand->mode = Addressing_Variable; + } else { + operand->mode = Addressing_Value; } break; case Entity_TypeName: @@ -2645,6 +2642,31 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id operand->type = make_type_slice(c->allocator, type); } break; + case BuiltinProc_free: { + // free :: proc(^Type) + // free :: proc([]Type) + // free :: proc(string) + Type *type = operand->type; + bool ok = false; + if (is_type_pointer(type)) { + ok = true; + } else if (is_type_slice(type)) { + ok = true; + } else if (is_type_string(type)) { + ok = true; + } + + if (!ok) { + gbString type_str = type_to_string(type); + error_node(operand->expr, "You can only free pointers, slices, and strings, got `%s`", type_str); + gb_string_free(type_str); + return false; + } + + + operand->mode = Addressing_NoValue; + } break; + case BuiltinProc_size_of: { // size_of :: proc(Type) -> untyped int Type *type = check_type(c, ce->args.e[0]); diff --git a/src/checker.c b/src/checker.c index aecaf66d9..4c9b58ce1 100644 --- a/src/checker.c +++ b/src/checker.c @@ -5,8 +5,8 @@ typedef enum AddressingMode { Addressing_Invalid, Addressing_NoValue, - Addressing_Value, // R-value - Addressing_Variable, // L-value + Addressing_Value, + Addressing_Variable, Addressing_Constant, Addressing_Type, Addressing_Builtin, @@ -123,6 +123,7 @@ typedef enum BuiltinProcId { BuiltinProc_new, BuiltinProc_new_slice, + BuiltinProc_free, BuiltinProc_size_of, BuiltinProc_size_of_val, @@ -165,7 +166,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { {STR_LIT(""), 0, false, Expr_Stmt}, {STR_LIT("new"), 1, false, Expr_Expr}, - {STR_LIT("new_slice"), 2, false, Expr_Expr}, + {STR_LIT("new_slice"), 2, false, Expr_Expr}, + {STR_LIT("free"), 1, false, Expr_Stmt}, {STR_LIT("size_of"), 1, false, Expr_Expr}, {STR_LIT("size_of_val"), 1, false, Expr_Expr}, diff --git a/src/gb/gb.h b/src/gb/gb.h index 4c7498aa7..304f782b2 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -4819,14 +4819,10 @@ GB_ALLOCATOR_PROC(gb_heap_allocator_proc) { #else // TODO(bill): *nix version that's decent case gbAllocation_Alloc: { - gbAllocationHeader *header; - isize total_size = size + alignment + gb_size_of(gbAllocationHeader); - ptr = malloc(total_size); - header = cast(gbAllocationHeader *)ptr; - ptr = gb_align_forward(header+1, alignment); - gb_allocation_header_fill(header, ptr, size); - if (flags & gbAllocatorFlag_ClearToZero) + ptr = aligned_alloc(alignment, size); + if (flags & gbAllocatorFlag_ClearToZero) { gb_zero_size(ptr, size); + } } break; case gbAllocation_Free: { @@ -2909,6 +2909,37 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv return ir_emit_load(proc, slice); } break; + case BuiltinProc_free: { + ir_emit_comment(proc, str_lit("free")); + + gbAllocator allocator = proc->module->allocator; + + AstNode *node = ce->args.e[0]; + TypeAndValue tav = *type_and_value_of_expression(proc->module->info, node); + Type *type = base_type(tav.type); + irValue *val = ir_build_expr(proc, node); + irValue *ptr = NULL; + if (is_type_pointer(type)) { + ptr = val; + } else if (is_type_slice(type)) { + ptr = ir_slice_elem(proc, val); + } else if (is_type_string(type)) { + ptr = ir_string_elem(proc, val); + } else { + GB_PANIC("Invalid type to `free`"); + } + + if (ptr == NULL) { + return NULL; + } + + ptr = ir_emit_conv(proc, ptr, t_rawptr); + + irValue **args = gb_alloc_array(allocator, irValue *, 1); + args[0] = ptr; + return ir_emit_global_call(proc, "free_ptr", args, 1); + } break; + case BuiltinProc_assert: { ir_emit_comment(proc, str_lit("assert")); irValue *cond = ir_build_expr(proc, ce->args.e[0]); diff --git a/src/parser.c b/src/parser.c index eac6fbd68..e5d6205e7 100644 --- a/src/parser.c +++ b/src/parser.c @@ -149,7 +149,7 @@ AST_NODE_KIND(_ExprBegin, "", i32) \ AST_NODE_KIND(DemaybeExpr, "demaybe expression", struct { Token op; AstNode *expr; }) \ AST_NODE_KIND(SliceExpr, "slice expression", struct { \ AstNode *expr; \ - Token open, close; \ + Token open, close, interval; \ AstNode *low, *high; \ }) \ AST_NODE_KIND(CallExpr, "call expression", struct { \ @@ -716,11 +716,12 @@ AstNode *make_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, } -AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, AstNode *low, AstNode *high) { +AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, Token interval, AstNode *low, AstNode *high) { AstNode *result = make_node(f, AstNode_SliceExpr); result->SliceExpr.expr = expr; result->SliceExpr.open = open; result->SliceExpr.close = close; + result->SliceExpr.interval = interval; result->SliceExpr.low = low; result->SliceExpr.high = high; return result; @@ -1970,19 +1971,25 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { if (lhs) { // TODO(bill): Handle this } - Token open, close; + Token open = {0}, close = {0}, interval = {0}; AstNode *indices[2] = {0}; f->expr_level++; open = expect_token(f, Token_OpenBracket); + // if (f->curr_token.kind != Token_Ellipsis && + // f->curr_token.kind != Token_HalfOpenRange) { if (f->curr_token.kind != Token_Colon) { indices[0] = parse_expr(f, false); } bool is_index = true; - if (allow_token(f, Token_Colon)) { + // if (f->curr_token.kind == Token_Ellipsis || + // f->curr_token.kind == Token_HalfOpenRange) { + if (f->curr_token.kind == Token_Colon) { is_index = false; + interval = f->curr_token; + next_token(f); if (f->curr_token.kind != Token_CloseBracket && f->curr_token.kind != Token_EOF) { indices[1] = parse_expr(f, false); @@ -1995,7 +2002,7 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { if (is_index) { operand = make_index_expr(f, operand, indices[0], open, close); } else { - operand = make_slice_expr(f, operand, open, close, indices[0], indices[1]); + operand = make_slice_expr(f, operand, open, close, interval, indices[0], indices[1]); } } break; diff --git a/src/tokenizer.c b/src/tokenizer.c index 8fa836941..800107466 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -75,7 +75,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \ TOKEN_KIND(Token_Semicolon, ";"), \ TOKEN_KIND(Token_Period, "."), \ TOKEN_KIND(Token_Comma, ","), \ - TOKEN_KIND(Token_Ellipsis, ".."), \ + TOKEN_KIND(Token_Ellipsis, "..."), \ TOKEN_KIND(Token_HalfOpenRange, "..<"), \ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \ \ @@ -847,10 +847,12 @@ Token tokenizer_get_token(Tokenizer *t) { token.kind = Token_Period; // Default if (t->curr_rune == '.') { // Could be an ellipsis advance_to_next_rune(t); - token.kind = Token_Ellipsis; if (t->curr_rune == '<') { advance_to_next_rune(t); token.kind = Token_HalfOpenRange; + } else if (t->curr_rune == '.') { + advance_to_next_rune(t); + token.kind = Token_Ellipsis; } } break; |