aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZachary Pierson <zacpiersonhehe@gmail.com>2017-02-27 23:25:47 -0600
committerZachary Pierson <zacpiersonhehe@gmail.com>2017-02-27 23:25:47 -0600
commit231ea8b0264e8b6d47278f01fb7c31b8562c2bbb (patch)
treee483189c84fcea9763e2fa0386e98ef5ca9a420b /src
parent5bbdb3a3a3ab6c821141190e052db9fdb2961734 (diff)
parent9bc37f44002d89ed35643b2bfd8c384cb5ff1f48 (diff)
Merge https://github.com/gingerBill/Odin
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.c74
-rw-r--r--src/check_stmt.c52
-rw-r--r--src/exact_value.c7
-rw-r--r--src/ir.c216
-rw-r--r--src/ir_print.c9
-rw-r--r--src/parser.c73
-rw-r--r--src/tokenizer.c58
-rw-r--r--src/types.c35
8 files changed, 352 insertions, 172 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index f075df688..0e166ef1a 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -197,11 +197,11 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
}
}
- // if (is_type_proc(dst)) {
- // if (are_types_identical(src, dst)) {
- // return 1;
- // }
- // }
+ if (is_type_proc(dst)) {
+ if (are_types_identical(src, dst)) {
+ return 3;
+ }
+ }
if (is_type_any(dst)) {
// NOTE(bill): Anything can cast to `Any`
@@ -2827,6 +2827,16 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
goto error;
}
}
+
+ if (entity == NULL &&
+ operand->type != NULL && is_type_untyped(operand->type) && is_type_string(operand->type)) {
+ String s = operand->value.value_string;
+ operand->mode = Addressing_Constant;
+ operand->value = make_exact_value_integer(s.len);
+ operand->type = t_untyped_integer;
+ return NULL;
+ }
+
if (entity == NULL) {
gbString op_str = expr_to_string(op_expr);
gbString type_str = type_to_string(operand->type);
@@ -3047,19 +3057,26 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
} break;
case BuiltinProc_append: {
- // append :: proc([dynamic]Type, item: ...Type)
+ // append :: proc([dynamic]Type, item: ..Type)
+ // append :: proc([]Type, item: ..Type)
Type *type = operand->type;
type = base_type(type);
- if (!is_type_dynamic_array(type)) {
+ if (!is_type_dynamic_array(type) && !is_type_slice(type)) {
gbString str = type_to_string(type);
- error_node(operand->expr, "Expected a dynamic array, got `%s`", str);
+ error_node(operand->expr, "Expected a slice or dynamic array, got `%s`", str);
gb_string_free(str);
return false;
}
- // TODO(bill): Semi-memory leaks
- Type *elem = type->DynamicArray.elem;
- Type *slice_elem = make_type_slice(c->allocator, elem);
+ Type *elem = NULL;
+ Type *slice_elem = NULL;
+ if (is_type_dynamic_array(type)) {
+ // TODO(bill): Semi-memory leaks
+ elem = type->DynamicArray.elem;
+ } else {
+ elem = type->Slice.elem;
+ }
+ slice_elem = make_type_slice(c->allocator, elem);
Type *proc_type_params = make_type_tuple(c->allocator);
proc_type_params->Tuple.variables = gb_alloc_array(c->allocator, Entity *, 2);
@@ -3394,7 +3411,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
} break;
case BuiltinProc_swizzle: {
- // swizzle :: proc(v: {N}T, T...) -> {M}T
+ // swizzle :: proc(v: {N}T, T..) -> {M}T
Type *vector_type = base_type(operand->type);
if (!is_type_vector(vector_type)) {
gbString type_str = type_to_string(operand->type);
@@ -5110,6 +5127,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
switch (t->kind) {
case Type_Basic:
if (is_type_string(t)) {
+ if (se->index3) {
+ error_node(node, "3-index slice on a string in not needed");
+ goto error;
+ }
valid = true;
if (o->mode == Addressing_Constant) {
max_count = o->value.value_string.len;
@@ -5150,14 +5171,20 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
o->mode = Addressing_Value;
}
+ if (se->index3 && (se->high == NULL || se->max == NULL)) {
+ error(se->close, "2nd and 3rd indices are required in a 3-index slice");
+ goto error;
+ }
+
i64 indices[2] = {0};
- AstNode *nodes[2] = {se->low, se->high};
+ AstNode *nodes[3] = {se->low, se->high, se->max};
for (isize i = 0; i < gb_count_of(nodes); i++) {
i64 index = max_count;
if (nodes[i] != NULL) {
i64 capacity = -1;
- if (max_count >= 0)
+ if (max_count >= 0) {
capacity = max_count;
+ }
i64 j = 0;
if (check_index_value(c, nodes[i], capacity, &j)) {
index = j;
@@ -5423,13 +5450,17 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = write_expr_to_string(str, se->expr);
str = gb_string_appendc(str, "[");
str = write_expr_to_string(str, se->low);
- str = gb_string_appendc(str, ":");
+ str = gb_string_appendc(str, "..");
str = write_expr_to_string(str, se->high);
+ if (se->index3) {
+ str = gb_string_appendc(str, "..");
+ str = write_expr_to_string(str, se->max);
+ }
str = gb_string_appendc(str, "]");
case_end;
case_ast_node(e, Ellipsis, node);
- str = gb_string_appendc(str, "...");
+ str = gb_string_appendc(str, "..");
case_end;
case_ast_node(fv, FieldValue, node);
@@ -5445,9 +5476,10 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
case_ast_node(at, ArrayType, node);
str = gb_string_appendc(str, "[");
- if (at->count->kind == AstNode_UnaryExpr &&
- at->count->UnaryExpr.op.kind == Token_Hash) {
- str = gb_string_appendc(str, "#");
+ if (at->count != NULL &&
+ at->count->kind == AstNode_UnaryExpr &&
+ at->count->UnaryExpr.op.kind == Token_Ellipsis) {
+ str = gb_string_appendc(str, "..");
} else {
str = write_expr_to_string(str, at->count);
}
@@ -5456,7 +5488,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
case_end;
case_ast_node(at, DynamicArrayType, node);
- str = gb_string_appendc(str, "[...]");
+ str = gb_string_appendc(str, "[..]");
str = write_expr_to_string(str, at->elem);
case_end;
@@ -5489,7 +5521,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = gb_string_appendc(str, ": ");
}
if (f->flags&FieldFlag_ellipsis) {
- str = gb_string_appendc(str, "...");
+ str = gb_string_appendc(str, "..");
}
str = write_expr_to_string(str, f->type);
case_end;
diff --git a/src/check_stmt.c b/src/check_stmt.c
index 90cb6ff61..768410803 100644
--- a/src/check_stmt.c
+++ b/src/check_stmt.c
@@ -421,6 +421,49 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_stmt(c, ts->stmt, flags);
case_end;
+ case_ast_node(s, IncDecStmt, node);
+ TokenKind op = s->op.kind;
+ switch (op) {
+ case Token_Inc: op = Token_Add; break;
+ case Token_Dec: op = Token_Sub; break;
+ default:
+ error_node(node, "Invalid inc/dec operation");
+ return;
+ }
+
+ Operand x = {0};
+ check_expr(c, &x, s->expr);
+ if (x.mode == Addressing_Invalid) {
+ return;
+ }
+ if (!is_type_integer(x.type) && !is_type_float(x.type)) {
+ gbString e = expr_to_string(s->expr);
+ gbString t = type_to_string(x.type);
+ error_node(node, "%s%.*s used on non-numeric type %s", e, LIT(s->op.string), t);
+ gb_string_free(t);
+ gb_string_free(e);
+ return;
+ }
+ AstNode *left = s->expr;
+ AstNode *right = gb_alloc_item(c->allocator, AstNode);
+ right->kind = AstNode_BasicLit;
+ right->BasicLit.pos = s->op.pos;
+ right->BasicLit.kind = Token_Integer;
+ right->BasicLit.string = str_lit("1");
+
+ AstNode *be = gb_alloc_item(c->allocator, AstNode);
+ be->kind = AstNode_BinaryExpr;
+ be->BinaryExpr.op = s->op;
+ be->BinaryExpr.op.kind = op;
+ be->BinaryExpr.left = left;
+ be->BinaryExpr.right = right;
+ check_binary_expr(c, &x, be);
+ if (x.mode == Addressing_Invalid) {
+ return;
+ }
+ check_assignment_variable(c, &x, left);
+ case_end;
+
case_ast_node(as, AssignStmt, node);
switch (as->op.kind) {
case Token_Eq: {
@@ -591,8 +634,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (fs->post != NULL) {
check_stmt(c, fs->post, 0);
- if (fs->post->kind != AstNode_AssignStmt) {
- error_node(fs->post, "`for` statement post statement must be an assignment");
+ if (fs->post->kind != AstNode_AssignStmt &&
+ fs->post->kind != AstNode_IncDecStmt) {
+ error_node(fs->post, "`for` statement post statement must be a simple statement");
}
}
check_stmt(c, fs->body, new_flags);
@@ -671,8 +715,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
TokenKind op = Token_Lt;
switch (ie->op.kind) {
- case Token_HalfOpenRange: op = Token_Lt; break;
- case Token_Ellipsis: op = Token_LtEq; break;
+ case Token_Ellipsis: op = Token_Lt; break;
default: error(ie->op, "Invalid range operator"); break;
}
bool ok = compare_exact_values(Token_Lt, a, b);
@@ -1215,6 +1258,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case Entity_Variable: {
Type *t = base_type(type_deref(e->type));
if (is_type_struct(t) || is_type_raw_union(t)) {
+ // TODO(bill): Make it work for unions too
Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
GB_ASSERT(found != NULL);
for_array(i, (*found)->elements.entries) {
diff --git a/src/exact_value.c b/src/exact_value.c
index 7c48d126b..57c8ae81d 100644
--- a/src/exact_value.c
+++ b/src/exact_value.c
@@ -274,8 +274,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
case ExactValue_Invalid:
return v;
case ExactValue_Integer:
- i = v.value_integer;
- i = ~i;
+ i = ~v.value_integer;
break;
default:
goto failure;
@@ -283,8 +282,10 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
// NOTE(bill): unsigned integers will be negative and will need to be
// limited to the types precision
- if (precision > 0)
+ // IMPORTANT NOTE(bill): Max precision is 64 bits as that's how integers are stored
+ if (0 < precision && precision < 64) {
i &= ~((~0ll)<<precision);
+ }
return make_exact_value_integer(i);
} break;
diff --git a/src/ir.c b/src/ir.c
index 388f747a3..a455c0164 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -218,6 +218,7 @@ struct irProcedure {
TokenPos pos; \
irValue *low; \
irValue *high; \
+ irValue *max; \
bool is_substring; \
}) \
IR_INSTR_KIND(DebugDeclare, struct { \
@@ -233,6 +234,7 @@ struct irProcedure {
#define IR_CONV_KINDS \
IR_CONV_KIND(trunc) \
IR_CONV_KIND(zext) \
+ IR_CONV_KIND(sext) \
IR_CONV_KIND(fptrunc) \
IR_CONV_KIND(fpext) \
IR_CONV_KIND(fptoui) \
@@ -955,11 +957,12 @@ irValue *ir_make_instr_bounds_check(irProcedure *p, TokenPos pos, irValue *index
v->Instr.BoundsCheck.len = len;
return v;
}
-irValue *ir_make_instr_slice_bounds_check(irProcedure *p, TokenPos pos, irValue *low, irValue *high, bool is_substring) {
+irValue *ir_make_instr_slice_bounds_check(irProcedure *p, TokenPos pos, irValue *low, irValue *high, irValue *max, bool is_substring) {
irValue *v = ir_alloc_instr(p, irInstr_SliceBoundsCheck);
v->Instr.SliceBoundsCheck.pos = pos;
v->Instr.SliceBoundsCheck.low = low;
v->Instr.SliceBoundsCheck.high = high;
+ v->Instr.SliceBoundsCheck.max = max;
v->Instr.SliceBoundsCheck.is_substring = is_substring;
return v;
}
@@ -1844,6 +1847,7 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
switch (index) {
case 0: result_type = make_type_pointer(a, make_type_pointer(a, t->Slice.elem)); break;
case 1: result_type = make_type_pointer(a, t_int); break;
+ case 2: result_type = make_type_pointer(a, t_int); break;
}
} else if (is_type_string(t)) {
switch (index) {
@@ -2069,6 +2073,11 @@ irValue *ir_slice_count(irProcedure *proc, irValue *slice) {
GB_ASSERT(t->kind == Type_Slice);
return ir_emit_struct_ev(proc, slice, 1);
}
+irValue *ir_slice_capacity(irProcedure *proc, irValue *slice) {
+ Type *t = base_type(ir_type(slice));
+ GB_ASSERT(t->kind == Type_Slice);
+ return ir_emit_struct_ev(proc, slice, 2);
+}
irValue *ir_dynamic_array_elem(irProcedure *proc, irValue *da) {
Type *t = ir_type(da);
@@ -2105,8 +2114,19 @@ irValue *ir_string_len(irProcedure *proc, irValue *string) {
}
+void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *count, irValue *capacity) {
+ Type *t = ir_type(slice_ptr);
+ GB_ASSERT(is_type_pointer(t));
+ t = type_deref(t);
+ GB_ASSERT(is_type_slice(t));
+ ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 0), data);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 1), count);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 2), capacity);
+}
+
+
-irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *low, irValue *high) {
+irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base, irValue *low, irValue *high, irValue *max) {
// TODO(bill): array bounds checking for slice creation
// TODO(bill): check that low < high <= max
gbAllocator a = proc->module->allocator;
@@ -2122,8 +2142,16 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base,
case Type_Pointer: high = v_one; break;
}
}
+ if (max == NULL) {
+ switch (bt->kind) {
+ case Type_Array: high = ir_array_len(proc, base); break;
+ case Type_Slice: high = ir_slice_capacity(proc, base); break;
+ case Type_Pointer: high = v_one; break;
+ }
+ }
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
+ irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
irValue *elem = NULL;
switch (bt->kind) {
@@ -2135,14 +2163,7 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base,
elem = ir_emit_ptr_offset(proc, elem, low);
irValue *slice = ir_add_local_generated(proc, slice_type);
-
- irValue *gep = NULL;
- gep = ir_emit_struct_ep(proc, slice, 0);
- ir_emit_store(proc, gep, elem);
-
- gep = ir_emit_struct_ep(proc, slice, 1);
- ir_emit_store(proc, gep, len);
-
+ ir_fill_slice(proc, slice, elem, len, cap);
return slice;
}
@@ -2240,12 +2261,23 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
i64 sz = type_size_of(proc->module->allocator, src);
i64 dz = type_size_of(proc->module->allocator, dst);
irConvKind kind = irConv_trunc;
- if (sz == dz) {
+ if (dz == sz) {
// NOTE(bill): In LLVM, all integers are signed and rely upon 2's compliment
// NOTE(bill): Copy the value just for type correctness
kind = irConv_bitcast;
} else if (dz > sz) {
kind = irConv_zext;
+
+ // TODO(bill): figure out the rules completely
+ bool ss = !is_type_unsigned(src);
+ bool ds = !is_type_unsigned(dst);
+ if (ss && ds) {
+ kind = irConv_sext;
+ } else if (ss) {
+ kind = irConv_sext;
+ } else {
+ kind = irConv_zext;
+ }
}
return ir_emit(proc, ir_make_instr_conv(proc, kind, value, src, dst));
@@ -2374,7 +2406,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
ir_emit_store(proc, elem_ptr, elem);
irValue *len = ir_string_len(proc, value);
- irValue *slice = ir_add_local_slice(proc, dst, elem_ptr, v_zero, len);
+ irValue *cap = len;
+ irValue *slice = ir_add_local_slice(proc, dst, elem_ptr, v_zero, len, cap);
return ir_emit_load(proc, slice);
}
@@ -2745,7 +2778,7 @@ void ir_emit_bounds_check(irProcedure *proc, Token token, irValue *index, irValu
ir_emit(proc, ir_make_instr_bounds_check(proc, token.pos, index, len));
}
-void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, bool is_substring) {
+void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, irValue *high, irValue *max, bool is_substring) {
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
return;
}
@@ -2753,10 +2786,11 @@ void ir_emit_slice_bounds_check(irProcedure *proc, Token token, irValue *low, ir
low = ir_emit_conv(proc, low, t_int);
high = ir_emit_conv(proc, high, t_int);
- ir_emit(proc, ir_make_instr_slice_bounds_check(proc, token.pos, low, high, is_substring));
+ ir_emit(proc, ir_make_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring));
}
+
////////////////////////////////////////////////////////////////
//
// @Build
@@ -3149,7 +3183,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
irValue *count = ir_emit_conv(proc, ir_build_expr(proc, ce->args.e[1]), t_int);
- ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, false);
+ ir_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, count, count, false);
irValue *slice_size = ir_emit_arith(proc, Token_Mul, elem_size, count, t_int);
@@ -3161,10 +3195,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
irValue *ptr = ir_emit_conv(proc, call, ptr_type);
irValue *slice = ir_add_local_generated(proc, slice_type);
- irValue *gep0 = ir_emit_struct_ep(proc, slice, 0);
- irValue *gep1 = ir_emit_struct_ep(proc, slice, 1);
- ir_emit_store(proc, gep0, ptr);
- ir_emit_store(proc, gep1, count);
+ ir_fill_slice(proc, slice, ptr, count, count);
return ir_emit_load(proc, slice);
} break;
@@ -3303,8 +3334,16 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
Type *type = ir_type(array_ptr);
GB_ASSERT(is_type_pointer(type));
type = base_type(type_deref(type));
- GB_ASSERT(is_type_dynamic_array(type));
- Type *elem_type = type->DynamicArray.elem;
+ Type *elem_type = NULL;
+ bool is_slice = false;
+ if (is_type_dynamic_array(type)) {
+ elem_type = type->DynamicArray.elem;
+ } else if (is_type_slice(type)) {
+ is_slice = true;
+ elem_type = type->Slice.elem;
+ } else {
+ GB_PANIC("Invalid type to append");
+ }
irValue *elem_size = ir_make_const_int(a, type_size_of(a, elem_type));
irValue *elem_align = ir_make_const_int(a, type_align_of(a, elem_type));
@@ -3361,10 +3400,8 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
}
irValue *base_elem = ir_emit_array_epi(proc, base_array, 0);
- irValue *slice_elem = ir_emit_struct_ep(proc, slice, 0);
- ir_emit_store(proc, slice_elem, base_elem);
irValue *len = ir_make_const_int(a, slice_len);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
+ ir_fill_slice(proc, slice, base_elem, len, len);
}
arg_count = 2;
@@ -3381,6 +3418,10 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
daa_args[2] = elem_align;
daa_args[3] = ir_emit_conv(proc, items, t_rawptr);
daa_args[4] = ir_emit_conv(proc, item_count, t_int);
+
+ if (is_slice) {
+ return ir_emit_global_call(proc, "__slice_append", daa_args, 5);
+ }
return ir_emit_global_call(proc, "__dynamic_array_append", daa_args, 5);
} break;
@@ -3526,8 +3567,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
Type *slice_type = make_type_slice(proc->module->allocator, type_deref(ir_type(ptr)));
irValue *slice = ir_add_local_generated(proc, slice_type);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), ptr);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), count);
+ ir_fill_slice(proc, slice, ptr, count, count);
return ir_emit_load(proc, slice);
} break;
@@ -3544,9 +3584,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
irValue *ptr = ir_emit_conv(proc, ir_slice_elem(proc, s), t_u8_ptr);
irValue *count = ir_slice_count(proc, s);
count = ir_emit_arith(proc, Token_Mul, count, ir_make_const_int(proc->module->allocator, elem_size), t_int);
-
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), ptr);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), count);
+ ir_fill_slice(proc, slice, ptr, count, count);
return ir_emit_load(proc, slice);
} break;
@@ -3669,11 +3707,9 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
ir_emit_store(proc, addr, args[i]);
}
- irValue *base_elem = ir_emit_array_epi(proc, base_array, 0);
- irValue *slice_elem = ir_emit_struct_ep(proc, slice, 0);
- ir_emit_store(proc, slice_elem, base_elem);
+ irValue *base_elem = ir_emit_array_epi(proc, base_array, 0);
irValue *len = ir_make_const_int(allocator, slice_len);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
+ ir_fill_slice(proc, slice, base_elem, len, len);
}
arg_count = type->param_count;
@@ -4064,9 +4100,11 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
gbAllocator a = proc->module->allocator;
irValue *low = v_zero;
irValue *high = NULL;
+ irValue *max = NULL;
if (se->low != NULL) low = ir_build_expr(proc, se->low);
if (se->high != NULL) high = ir_build_expr(proc, se->high);
+ if (se->max != NULL) max = ir_build_expr(proc, se->max);
irValue *addr = ir_build_addr(proc, se->expr).addr;
irValue *base = ir_emit_load(proc, addr);
Type *type = base_type(ir_type(base));
@@ -4084,16 +4122,15 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
Type *slice_type = type;
if (high == NULL) high = ir_slice_count(proc, base);
+ if (max == NULL) max = ir_slice_capacity(proc, base);
- ir_emit_slice_bounds_check(proc, se->open, low, high, false);
+ ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
irValue *elem = ir_emit_ptr_offset(proc, ir_slice_elem(proc, base), low);
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
+ irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
irValue *slice = ir_add_local_generated(proc, slice_type);
-
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
-
+ ir_fill_slice(proc, slice, elem, len, cap);
return ir_make_addr(slice);
}
@@ -4101,16 +4138,15 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
Type *dynamic_array = type;
if (high == NULL) high = ir_dynamic_array_count(proc, base);
+ if (max == NULL) max = ir_dynamic_array_capacity(proc, base);
- ir_emit_slice_bounds_check(proc, se->open, low, high, false);
+ ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
irValue *elem = ir_emit_ptr_offset(proc, ir_dynamic_array_elem(proc, base), low);
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
+ irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
irValue *slice = ir_add_local_generated(proc, dynamic_array);
-
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
-
+ ir_fill_slice(proc, slice, elem, len, cap);
return ir_make_addr(slice);
}
@@ -4119,38 +4155,31 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
Type *slice_type = make_type_slice(a, type->Array.elem);
if (high == NULL) high = ir_array_len(proc, base);
+ if (max == NULL) max = ir_array_len(proc, base);
- ir_emit_slice_bounds_check(proc, se->open, low, high, false);
+ ir_emit_slice_bounds_check(proc, se->open, low, high, max, false);
irValue *elem = ir_emit_ptr_offset(proc, ir_array_elem(proc, addr), low);
irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
+ irValue *cap = ir_emit_arith(proc, Token_Sub, max, low, t_int);
irValue *slice = ir_add_local_generated(proc, slice_type);
-
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 0), elem);
- ir_emit_store(proc, ir_emit_struct_ep(proc, slice, 1), len);
-
+ ir_fill_slice(proc, slice, elem, len, cap);
return ir_make_addr(slice);
}
case Type_Basic: {
GB_ASSERT(type == t_string);
- if (high == NULL) {
- high = ir_string_len(proc, base);
- }
+ if (high == NULL) high = ir_string_len(proc, base);
+ if (max == NULL) max = ir_string_len(proc, base);
- ir_emit_slice_bounds_check(proc, se->open, low, high, true);
+ ir_emit_slice_bounds_check(proc, se->open, low, high, max, true);
- irValue *elem, *len;
- len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
-
- elem = ir_string_elem(proc, base);
- elem = ir_emit_ptr_offset(proc, elem, low);
+ irValue *elem = ir_emit_ptr_offset(proc, ir_string_elem(proc, base), low);
+ irValue *len = ir_emit_arith(proc, Token_Sub, high, low, t_int);
irValue *str = ir_add_local_generated(proc, t_string);
- irValue *gep0 = ir_emit_struct_ep(proc, str, 0);
- irValue *gep1 = ir_emit_struct_ep(proc, str, 1);
- ir_emit_store(proc, gep0, elem);
- ir_emit_store(proc, gep1, len);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, str, 0), elem);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, str, 1), len);
return ir_make_addr(str);
} break;
@@ -4357,13 +4386,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
ir_emit_store(proc, offset, ev);
}
- irValue *gep0 = ir_emit_struct_ep(proc, v, 0);
- irValue *gep1 = ir_emit_struct_ep(proc, v, 1);
- irValue *gep2 = ir_emit_struct_ep(proc, v, 1);
-
- ir_emit_store(proc, gep0, data);
- ir_emit_store(proc, gep1, ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
- ir_emit_store(proc, gep2, ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
+ irValue *count = ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count);
+ ir_fill_slice(proc, v, data, count, count);
}
} break;
@@ -4730,8 +4754,7 @@ void ir_build_range_interval(irProcedure *proc, AstNodeIntervalExpr *node, Type
TokenKind op = Token_Lt;
switch (node->op.kind) {
- case Token_HalfOpenRange: op = Token_Lt; break;
- case Token_Ellipsis: op = Token_LtEq; break;
+ case Token_Ellipsis: op = Token_Lt; break;
default: GB_PANIC("Invalid interval operator"); break;
}
irValue *cond = ir_emit_comp(proc, op, ir_emit_load(proc, value), upper);
@@ -4769,6 +4792,15 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
ir_build_when_stmt(proc, ws);
case_end;
+ case_ast_node(s, IncDecStmt, node);
+ TokenKind op = Token_Add;
+ if (s->op.kind == Token_Dec) {
+ op = Token_Sub;
+ }
+ irAddr addr = ir_build_addr(proc, s->expr);
+ ir_build_assign_op(proc, addr, v_one, op);
+ case_end;
+
case_ast_node(vd, ValueDecl, node);
if (vd->is_var) {
irModule *m = proc->module;
@@ -6010,16 +6042,6 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) {
array_add(&m->foreign_library_paths, library_path);
}
-void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *count) {
- Type *t = ir_type(slice_ptr);
- GB_ASSERT(is_type_pointer(t));
- t = type_deref(t);
- GB_ASSERT(is_type_slice(t));
- irValue *elem = ir_emit_struct_ep(proc, slice_ptr, 0);
- irValue *len = ir_emit_struct_ep(proc, slice_ptr, 1);
- ir_emit_store(proc, elem, data);
- ir_emit_store(proc, len, count);
-}
void ir_gen_tree(irGen *s) {
irModule *m = &s->module;
@@ -6356,9 +6378,10 @@ void ir_gen_tree(irGen *s) {
irValue *global_type_table = ir_find_global_variable(proc, str_lit("__type_table"));
Type *type = base_type(type_deref(ir_type(ir_global_type_info_data)));
GB_ASSERT(is_type_array(type));
+ irValue *len = ir_make_const_int(proc->module->allocator, type->Array.count);
ir_fill_slice(proc, global_type_table,
ir_emit_array_epi(proc, ir_global_type_info_data, 0),
- ir_make_const_int(proc->module->allocator, type->Array.count));
+ len, len);
}
@@ -6542,8 +6565,9 @@ void ir_gen_tree(irGen *s) {
}
}
- ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Tuple.variable_count));
- ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Tuple.variable_count));
+ irValue *count = ir_make_const_int(a, t->Tuple.variable_count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
} break;
case Type_Record: {
switch (t->Record.kind) {
@@ -6589,9 +6613,10 @@ void ir_gen_tree(irGen *s) {
ir_emit_store(proc, offset, ir_make_const_int(a, foffset));
}
- ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Record.field_count));
- ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Record.field_count));
- ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, ir_make_const_int(a, t->Record.field_count));
+ irValue *count = ir_make_const_int(a, t->Record.field_count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count);
} break;
case TypeRecord_Union: {
ir_emit_comment(proc, str_lit("Type_Info_Union"));
@@ -6632,9 +6657,10 @@ void ir_gen_tree(irGen *s) {
}
- ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 0), memory_types, ir_make_const_int(a, field_count));
- ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 1), memory_names, ir_make_const_int(a, field_count));
- ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 2), memory_offsets, ir_make_const_int(a, field_count));
+ irValue *count = ir_make_const_int(a, field_count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 0), memory_types, count, count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 1), memory_names, count, count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, common_fields, 2), memory_offsets, count, count);
}
{
@@ -6661,9 +6687,8 @@ void ir_gen_tree(irGen *s) {
}
irValue *count = ir_make_const_int(a, variant_count);
-
- ir_fill_slice(proc, variant_names, memory_names, count);
- ir_fill_slice(proc, variant_types, memory_types, count);
+ ir_fill_slice(proc, variant_names, memory_names, count, count);
+ ir_fill_slice(proc, variant_types, memory_types, count, count);
}
} break;
@@ -6696,9 +6721,10 @@ void ir_gen_tree(irGen *s) {
}
}
- ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, ir_make_const_int(a, t->Record.field_count));
- ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, ir_make_const_int(a, t->Record.field_count));
- ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, ir_make_const_int(a, t->Record.field_count));
+ irValue *count = ir_make_const_int(a, t->Record.field_count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 0), memory_types, count, count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 1), memory_names, count, count);
+ ir_fill_slice(proc, ir_emit_struct_ep(proc, record, 2), memory_offsets, count, count);
} break;
case TypeRecord_Enum:
ir_emit_comment(proc, str_lit("Type_Info_Enum"));
diff --git a/src/ir_print.c b/src/ir_print.c
index 3018e2463..9bc7e5f41 100644
--- a/src/ir_print.c
+++ b/src/ir_print.c
@@ -191,7 +191,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
case Type_Slice:
ir_fprintf(f, "{");
ir_print_type(f, m, t->Slice.elem);
- ir_fprintf(f, "*, i%lld}", word_bits);
+ ir_fprintf(f, "*, i%lld, i%lld}", word_bits, word_bits);
return;
case Type_DynamicArray:
ir_fprintf(f, "{");
@@ -1249,6 +1249,13 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
ir_fprintf(f, " ");
ir_print_value(f, m, bc->high, t_int);
+ if (!bc->is_substring) {
+ ir_fprintf(f, ", ");
+ ir_print_type(f, m, t_int);
+ ir_fprintf(f, " ");
+ ir_print_value(f, m, bc->max, t_int);
+ }
+
ir_fprintf(f, ")\n");
} break;
diff --git a/src/parser.c b/src/parser.c
index f14f37599..160b72ef3 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -151,8 +151,9 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
AstNode *expr; \
- Token open, close, interval; \
- AstNode *low, *high; \
+ Token open, close; \
+ bool index3; \
+ AstNode *low, *high, *max; \
}) \
AST_NODE_KIND(CallExpr, "call expression", struct { \
AstNode * proc; \
@@ -186,6 +187,10 @@ AST_NODE_KIND(_StmtBegin, "", i32) \
Token op; \
AstNodeArray lhs, rhs; \
}) \
+ AST_NODE_KIND(IncDecStmt, "increment decrement statement", struct { \
+ Token op; \
+ AstNode *expr; \
+ }) \
AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
AST_NODE_KIND(BlockStmt, "block statement", struct { \
AstNodeArray stmts; \
@@ -467,6 +472,7 @@ Token ast_node_token(AstNode *node) {
case AstNode_ExprStmt: return ast_node_token(node->ExprStmt.expr);
case AstNode_TagStmt: return node->TagStmt.token;
case AstNode_AssignStmt: return node->AssignStmt.op;
+ case AstNode_IncDecStmt: return ast_node_token(node->IncDecStmt.expr);
case AstNode_BlockStmt: return node->BlockStmt.open;
case AstNode_IfStmt: return node->IfStmt.token;
case AstNode_WhenStmt: return node->WhenStmt.token;
@@ -662,14 +668,15 @@ AstNode *ast_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, T
}
-AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, Token interval, AstNode *low, AstNode *high) {
+AstNode *ast_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, bool index3, AstNode *low, AstNode *high, AstNode *max) {
AstNode *result = make_ast_node(f, AstNode_SliceExpr);
result->SliceExpr.expr = expr;
result->SliceExpr.open = open;
result->SliceExpr.close = close;
- result->SliceExpr.interval = interval;
+ result->SliceExpr.index3 = index3;
result->SliceExpr.low = low;
result->SliceExpr.high = high;
+ result->SliceExpr.max = max;
return result;
}
@@ -802,6 +809,16 @@ AstNode *ast_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rh
return result;
}
+
+AstNode *ast_inc_dec_stmt(AstFile *f, Token op, AstNode *expr) {
+ AstNode *result = make_ast_node(f, AstNode_IncDecStmt);
+ result->IncDecStmt.op = op;
+ result->IncDecStmt.expr = expr;
+ return result;
+}
+
+
+
AstNode *ast_block_stmt(AstFile *f, AstNodeArray stmts, Token open, Token close) {
AstNode *result = make_ast_node(f, AstNode_BlockStmt);
result->BlockStmt.stmts = stmts;
@@ -1930,37 +1947,49 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
// TODO(bill): Handle this
}
Token open = {0}, close = {0}, interval = {0};
- AstNode *indices[2] = {0};
+ AstNode *indices[3] = {0};
+ isize ellipsis_count = 0;
+ Token ellipses[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) {
+ if (f->curr_token.kind != Token_Ellipsis) {
indices[0] = parse_expr(f, false);
}
bool is_index = true;
- // 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;
+ while (f->curr_token.kind == Token_Ellipsis && ellipsis_count < gb_count_of(ellipses)) {
+ ellipses[ellipsis_count++] = f->curr_token;
next_token(f);
- if (f->curr_token.kind != Token_CloseBracket &&
+ if (f->curr_token.kind != Token_Ellipsis &&
+ f->curr_token.kind != Token_CloseBracket &&
f->curr_token.kind != Token_EOF) {
- indices[1] = parse_expr(f, false);
+ indices[ellipsis_count] = parse_expr(f, false);
}
}
+
f->expr_level--;
close = expect_token(f, Token_CloseBracket);
- if (is_index) {
- operand = ast_index_expr(f, operand, indices[0], open, close);
+ if (ellipsis_count > 0) {
+ bool index3 = false;
+ if (ellipsis_count == 2) {
+ index3 = true;
+ // 2nd and 3rd index must be present
+ if (indices[1] == NULL) {
+ error(ellipses[0], "2nd index required in 3-index slice expression");
+ indices[1] = ast_bad_expr(f, ellipses[0], ellipses[1]);
+ }
+ if (indices[2] == NULL) {
+ error(ellipses[1], "3rd index required in 3-index slice expression");
+ indices[2] = ast_bad_expr(f, ellipses[1], close);
+ }
+ }
+ operand = ast_slice_expr(f, operand, open, close, index3, indices[0], indices[1], indices[2]);
} else {
- operand = ast_slice_expr(f, operand, open, close, interval, indices[0], indices[1]);
+ operand = ast_index_expr(f, operand, indices[0], open, close);
}
} break;
@@ -2246,7 +2275,6 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
allow_token(f, Token_in);
AstNode *expr = parse_expr(f, false);
switch (f->curr_token.kind) {
- case Token_HalfOpenRange:
case Token_Ellipsis: {
Token op = f->curr_token;
next_token(f);
@@ -2272,6 +2300,13 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
return ast_bad_stmt(f, token, f->curr_token);
}
+ switch (token.kind) {
+ case Token_Inc:
+ case Token_Dec:
+ next_token(f);
+ return ast_inc_dec_stmt(f, token, lhs.e[0]);
+ }
+
return ast_expr_stmt(f, lhs.e[0]);
}
diff --git a/src/tokenizer.c b/src/tokenizer.c
index 68ab270be..cfc1423f0 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -51,8 +51,8 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
TOKEN_KIND(Token_ArrowRight, "->"), \
TOKEN_KIND(Token_ArrowLeft, "<-"), \
- TOKEN_KIND(Token_Increment, "++"), \
- TOKEN_KIND(Token_Decrement, "--"), \
+ TOKEN_KIND(Token_Inc, "++"), \
+ TOKEN_KIND(Token_Dec, "--"), \
\
TOKEN_KIND(Token__ComparisonBegin, "_ComparisonBegin"), \
TOKEN_KIND(Token_CmpEq, "=="), \
@@ -73,8 +73,8 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
TOKEN_KIND(Token_Semicolon, ";"), \
TOKEN_KIND(Token_Period, "."), \
TOKEN_KIND(Token_Comma, ","), \
- TOKEN_KIND(Token_Ellipsis, "..."), \
- TOKEN_KIND(Token_HalfOpenRange, "..<"), \
+ TOKEN_KIND(Token_Ellipsis, ".."), \
+ /* TOKEN_KIND(Token_HalfOpenRange, "..<"), */ \
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
\
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
@@ -225,6 +225,23 @@ void syntax_error_va(Token token, char *fmt, va_list va) {
gb_mutex_unlock(&global_error_collector.mutex);
}
+void syntax_warning_va(Token token, char *fmt, va_list va) {
+ gb_mutex_lock(&global_error_collector.mutex);
+ global_error_collector.warning_count++;
+ // NOTE(bill): Duplicate error, skip it
+ if (!token_pos_eq(global_error_collector.prev, token.pos)) {
+ global_error_collector.prev = token.pos;
+ gb_printf_err("%.*s(%td:%td) Syntax Warning: %s\n",
+ LIT(token.pos.file), token.pos.line, token.pos.column,
+ gb_bprintf_va(fmt, va));
+ } else if (token.pos.line == 0) {
+ gb_printf_err("Warning: %s\n", gb_bprintf_va(fmt, va));
+ }
+
+ gb_mutex_unlock(&global_error_collector.mutex);
+}
+
+
void warning(Token token, char *fmt, ...) {
va_list va;
@@ -247,6 +264,13 @@ void syntax_error(Token token, char *fmt, ...) {
va_end(va);
}
+void syntax_warning(Token token, char *fmt, ...) {
+ va_list va;
+ va_start(va, fmt);
+ syntax_warning_va(token, fmt, va);
+ va_end(va);
+}
+
void compiler_error(char *fmt, ...) {
va_list va;
@@ -834,13 +858,11 @@ Token tokenizer_get_token(Tokenizer *t) {
token.kind = Token_Period; // Default
if (t->curr_rune == '.') { // Could be an ellipsis
advance_to_next_rune(t);
- 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;
- }
+ token.kind = Token_Ellipsis;
+ // if (t->curr_rune == '<') {
+ // advance_to_next_rune(t);
+ // token.kind = Token_HalfOpenRange;
+ // }
}
break;
@@ -859,13 +881,13 @@ Token tokenizer_get_token(Tokenizer *t) {
case '{': token.kind = Token_OpenBrace; break;
case '}': token.kind = Token_CloseBrace; break;
- case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
- case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break;
- case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break;
- case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
- case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
- case '+': token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Increment); break;
- case '-': token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Decrement, '>', Token_ArrowRight); break;
+ case '*': token.kind = token_kind_variant2(t, Token_Mul, Token_MulEq); break;
+ case '%': token.kind = token_kind_variant2(t, Token_Mod, Token_ModEq); break;
+ case '=': token.kind = token_kind_variant2(t, Token_Eq, Token_CmpEq); break;
+ case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
+ case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
+ case '+': token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Inc); break;
+ case '-': token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Dec, '>', Token_ArrowRight); break;
case '/': {
if (t->curr_rune == '/') {
while (t->curr_rune != '\n' && t->curr_rune != GB_RUNE_EOF) {
diff --git a/src/types.c b/src/types.c
index a734e3c01..0142fa227 100644
--- a/src/types.c
+++ b/src/types.c
@@ -1090,6 +1090,7 @@ gb_global Entity *entity__any_data = NULL;
gb_global Entity *entity__string_data = NULL;
gb_global Entity *entity__string_count = NULL;
gb_global Entity *entity__slice_count = NULL;
+gb_global Entity *entity__slice_capacity = NULL;
gb_global Entity *entity__dynamic_array_count = NULL;
gb_global Entity *entity__dynamic_array_capacity = NULL;
@@ -1251,6 +1252,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
} else if (type->kind == Type_Slice) {
String data_str = str_lit("data");
String count_str = str_lit("count");
+ String capacity_str = str_lit("capacity");
if (str_eq(field_name, data_str)) {
selection_add_index(&sel, 0);
@@ -1265,7 +1267,16 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
sel.entity = entity__slice_count;
return sel;
+ } else if (str_eq(field_name, capacity_str)) {
+ selection_add_index(&sel, 2);
+ if (entity__slice_capacity == NULL) {
+ entity__slice_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 2);
+ }
+
+ sel.entity = entity__slice_capacity;
+ return sel;
}
+
} else if (type->kind == Type_DynamicArray) {
String data_str = str_lit("data");
String count_str = str_lit("count");
@@ -1779,7 +1790,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
case Type_Slice: // ptr + count
- return 2 * build_context.word_size;
+ return 3 * build_context.word_size;
case Type_Map: {
if (t->Map.count == 0) { // Dynamic
@@ -1875,23 +1886,24 @@ i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) {
} else if (t->kind == Type_Basic) {
if (t->Basic.kind == Basic_string) {
switch (index) {
- case 0: return 0; // data
+ case 0: return 0; // data
case 1: return build_context.word_size; // count
}
} else if (t->Basic.kind == Basic_any) {
switch (index) {
- case 0: return 0; // type_info
+ case 0: return 0; // type_info
case 1: return build_context.word_size; // data
}
}
} else if (t->kind == Type_Slice) {
switch (index) {
- case 0: return 0; // data
+ case 0: return 0; // data
case 1: return 1*build_context.word_size; // count
+ case 2: return 2*build_context.word_size; // capacity
}
} else if (t->kind == Type_DynamicArray) {
switch (index) {
- case 0: return 0; // data
+ case 0: return 0; // data
case 1: return 1*build_context.word_size; // count
case 2: return 2*build_context.word_size; // capacity
case 3: return 3*build_context.word_size; // allocator
@@ -1928,6 +1940,13 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s
}
}
break;
+ case Type_Slice:
+ switch (index) {
+ case 0: t = t_rawptr; break;
+ case 1: t = t_int; break;
+ case 2: t = t_int; break;
+ }
+ break;
case Type_DynamicArray:
switch (index) {
case 0: t = t_rawptr; break;
@@ -1936,12 +1955,6 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s
case 3: t = t_allocator; break;
}
break;
- case Type_Slice:
- switch (index) {
- case 0: t = t_rawptr; break;
- case 1: t = t_int; break;
- }
- break;
}
}
}