Map :: struct ($K, $V) {
hashes : [..] i32;
entries : [..] MapEntry(K, V);
+
+ // The value provided by `map.get`, if nothing was found.
+ default_value : V;
}
MapEntry :: struct ($K, $T) {
value : T;
}
-init :: proc (use map: ^Map($K, $V), hash_count: i32 = 16) {
+init :: proc (use map: ^Map($K, $V), dv: V, hash_count: i32 = 16) {
array.init(^hashes, hash_count);
array.init(^entries, 4);
+ default_value = dv;
+
for i: 0 .. hash_count do array.push(^hashes, -1);
}
return lr.entry_index >= 0;
}
-get :: proc (use map: ^Map($K, $V), key: K, default := cast(V) 0) -> V {
+get :: proc (use map: ^Map($K, $V), key: K) -> V {
lr := lookup(map, key);
if lr.entry_index >= 0 do return entries[lr.entry_index].value;
- return default;
+ return default_value;
}
delete :: proc (use map: ^Map($K, $V), key: K) {
b32 convert_numlit_to_type(AstNumLit* num, Type* type);
b32 type_check_or_auto_cast(AstTyped** pnode, Type* type);
Type* resolve_expression_type(AstTyped* node);
+b32 cast_is_legal(Type* from_, Type* to_, char** err_msg);
char* get_function_name(AstFunction* func);
typedef enum PolyProcLookupMethod {
CHECK(expression, &unaryop->expr);
resolve_expression_type(unaryop->expr);
- if (unaryop->operation != Unary_Op_Cast) {
+ if (unaryop->operation == Unary_Op_Cast) {
+ char* err;
+ if (!cast_is_legal(unaryop->expr->type, unaryop->type, &err)) {
+ onyx_report_error(unaryop->token->pos, "Cast Error: %s", err);
+ return Check_Error;
+ }
+
+ } else {
unaryop->type = unaryop->expr->type;
}
if (types_are_compatible(node->type, type)) return 1;
if (node_is_auto_cast((AstNode *) node)) {
- // HACK: Check that this cast is legal!
- ((AstUnaryOp *) node)->type = type;
- return 1;
+ char* dummy;
+ if (!cast_is_legal(((AstUnaryOp *) node)->expr->type, type, &dummy)) {
+ return 0;
+
+ } else {
+ ((AstUnaryOp *) node)->type = type;
+ return 1;
+ }
}
else if (node->kind == Ast_Kind_NumLit) {
if (convert_numlit_to_type((AstNumLit *) node, type)) return 1;
return node->type;
}
+static const b32 cast_legality[][11] = {
+ /* I8 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ /* U8 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ /* I16 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ /* U16 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ /* I32 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* U32 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* I64 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* U64 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* F32 */ { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
+ /* F64 */ { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
+ /* PTR */ { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1 },
+};
+
+b32 cast_is_legal(Type* from_, Type* to_, char** err_msg) {
+ Type* from = from_;
+ Type* to = to_;
+
+ if (from->kind == Type_Kind_Enum) from = from->Enum.backing;
+ if (to->kind == Type_Kind_Enum) to = to->Enum.backing;
+
+ if (from->kind == Type_Kind_Struct || to->kind == Type_Kind_Struct) {
+ *err_msg = "Cannot cast to or from a struct.";
+ return 0;
+ }
+
+ if (from->kind == Type_Kind_Slice || to->kind == Type_Kind_Slice) {
+ *err_msg = "Cannot cast to or from a slice.";
+ return 0;
+ }
+
+ if (from->kind == Type_Kind_DynArray || to->kind == Type_Kind_DynArray) {
+ *err_msg = "Cannot cast to or from a dynamic array.";
+ return 0;
+ }
+
+ if (to->kind == Type_Kind_Function) {
+ *err_msg = "Cannot cast to a function.";
+ return 0;
+ }
+
+ if ( (type_is_simd(to) && !type_is_simd(from))
+ || (!type_is_simd(to) && type_is_simd(from))) {
+ *err_msg = "Can only perform a SIMD cast between SIMD types.";
+ return 0;
+ }
+
+ if (from->kind == Type_Kind_Basic && from->Basic.kind == Basic_Kind_Void) {
+ *err_msg = "Cannot cast from void.";
+ return 0;
+ }
+ i32 fromidx = -1, toidx = -1;
+ if (from->Basic.flags & Basic_Flag_Pointer || from->kind == Type_Kind_Array) {
+ fromidx = 10;
+ }
+ else if (from->Basic.flags & Basic_Flag_Integer) {
+ b32 unsign = (from->Basic.flags & Basic_Flag_Unsigned) != 0;
+
+ fromidx = log2_dumb(from->Basic.size) * 2 + unsign;
+ }
+ else if (from->Basic.flags & Basic_Flag_Float) {
+ if (from->Basic.size == 4) fromidx = 8;
+ else if (from->Basic.size == 8) fromidx = 9;
+ }
+
+ if (to->Basic.flags & Basic_Flag_Pointer || to->kind == Type_Kind_Array) {
+ toidx = 10;
+ }
+ else if (to->Basic.flags & Basic_Flag_Integer) {
+ b32 unsign = (to->Basic.flags & Basic_Flag_Unsigned) != 0;
+
+ toidx = log2_dumb(to->Basic.size) * 2 + unsign;
+ }
+ else if (to->Basic.flags & Basic_Flag_Float) {
+ if (to->Basic.size == 4) toidx = 8;
+ else if (to->Basic.size == 8) toidx = 9;
+ }
+
+ if (fromidx != -1 && toidx != -1) {
+ if (!cast_legality[fromidx][toidx]) {
+ *err_msg = bh_aprintf(global_heap_allocator, "Cast from '%s' to '%s' is not allowed.", type_get_name(from_), type_get_name(to_));
+ return 0;
+ }
+ }
+
+ *err_msg = NULL;
+ return 1;
+}
+
char* get_function_name(AstFunction* func) {
if (func->name != NULL) {
return bh_aprintf(global_scratch_allocator, "%b", func->name->text, func->name->length);
Type* from = cast->expr->type;
Type* to = cast->type;
-
- if (from->kind == Type_Kind_Struct || to->kind == Type_Kind_Struct) {
- onyx_report_error(cast->token->pos, "Cannot cast to or from a struct.");
- WI(WI_DROP);
- *pcode = code;
- return;
- }
-
- if (from->kind == Type_Kind_Slice || to->kind == Type_Kind_Slice) {
- onyx_report_error(cast->token->pos, "Cannot cast to or from a slice.");
- WI(WI_DROP);
- *pcode = code;
- return;
- }
-
- if (from->kind == Type_Kind_DynArray || to->kind == Type_Kind_DynArray) {
- onyx_report_error(cast->token->pos, "Cannot cast to or from a dynamic array.");
- WI(WI_DROP);
- *pcode = code;
- return;
- }
-
- if (to->kind == Type_Kind_Function) {
- onyx_report_error(cast->token->pos, "Cannot cast to a function.");
- WI(WI_DROP);
- *pcode = code;
- return;
- }
-
- if (type_is_simd(to) && !type_is_simd(from)) {
- onyx_report_error(cast->token->pos, "Can only perform a SIMD cast between SIMD types.");
- return;
- }
-
- if (type_is_simd(from) && !type_is_simd(to)) {
- onyx_report_error(cast->token->pos, "Can only perform a SIMD cast between SIMD types.");
- return;
- }
-
- if (type_is_simd(from) && type_is_simd(to)) {
- *pcode = code;
- return;
- }
-
if (from->kind == Type_Kind_Enum) from = from->Enum.backing;
if (to->kind == Type_Kind_Enum) to = to->Enum.backing;
- if (from->kind == Type_Kind_Basic && from->Basic.kind == Basic_Kind_Void) {
- onyx_report_error(cast->token->pos, "Cannot cast from void.");
- WI(WI_DROP);
+ if (type_is_simd(from) && type_is_simd(to)) {
*pcode = code;
return;
}
if (fromidx != -1 && toidx != -1) {
WasmInstructionType cast_op = cast_map[fromidx][toidx];
- if (cast_op == WI_UNREACHABLE) {
- bh_printf("%d %d\n", fromidx, toidx);
- onyx_report_error(cast->token->pos, "Bad cast.");
- }
- else if (cast_op != WI_NOP) {
+ assert(cast_op != WI_UNREACHABLE);
+
+ if (cast_op != WI_NOP) {
WI(cast_op);
}
}
done = true;
}
+ printf("val is %l\n", val);
return val;
}
file := reader.make(contents);
mem : map.Map(u64, u64);
- map.init(^mem, 257);
+ map.init(^mem, 0, 257);
defer map.free(^mem);
mask : Bitmask;
// Any changes to the implementation of Map should be tested on this
// file to validate if they 1) work and 2) are faster.
nums : map.Map(u32, spoken_times);
- map.init(^nums, 32767);
+ map.init(^nums, spoken_times.{}, 32767);
defer map.free(^nums);
turn := 1;
}
while turn != 2021 {
- st := map.get(^nums, last_num, spoken_times.{});
+ st := map.get(^nums, last_num);
if st.previous == 0 do last_num = 0;
else do last_num = st.recent - st.previous;
- st = map.get(^nums, last_num, spoken_times.{});
+ st = map.get(^nums, last_num);
st.previous = st.recent;
st.recent = turn;
map.put(^nums, last_num, st);
for x: -1 .. 2 do for y: -1 .. 2 do for z: -1 .. 2 do for w: -1 .. 2 {
if x == 0 && y == 0 && z == 0 && w == 0 do continue;
key := CubePos.{ pos.x + x, pos.y + y, pos.z + z, pos.w + w };
- state := map.get(cubes, key, CubeState.{});
+ state := map.get(cubes, key);
if state.alive do count += 1;
}
file := reader.make(contents);
cubes : map.Map(CubePos, CubeState);
- map.init(^cubes, 1021);
+ map.init(^cubes, CubeState.{}, 1021);
defer map.free(^cubes);
z := 0;
}
for ^cube: cubes_to_consider {
- state := map.get(^cubes, *cube, CubeState.{});
+ state := map.get(^cubes, *cube);
ncount := get_neighbor_count(^cubes, *cube);
if state.alive {
}
for ^cube: cubes_to_consider {
- state := map.get(^cubes, *cube, CubeState.{});
+ state := map.get(^cubes, *cube);
state.alive = state.next;
map.put(^cubes, *cube, state);
}
defer array.free(^tiles);
tile_map : map.Map(u32, ^Tile);
- map.init(^tile_map, 67);
+ map.init(^tile_map, null, 67);
defer map.free(^tile_map);
tile_data := calloc(200 * sizeof TileData);
file := reader.make(contents);
- map.init(^ingredient_map, 127);
- map.init(^allergen_map);
+ map.init(^ingredient_map, Ingredient.{}, 127);
+ map.init(^allergen_map, Allergen.{});
defer {
map.free(^ingredient_map);
map.free(^allergen_map);
array.push(^food.ingredients, ingredient_name);
- ingredient := map.get(^ingredient_map, ingredient_name, Ingredient.{});
+ ingredient := map.get(^ingredient_map, ingredient_name);
if ingredient.name.data == null {
ingredient.name = ingredient_name;
array.init(^ingredient.appears_on, 4);
array.push(^food.allergens, allergen_name);
- allergen := map.get(^allergen_map, allergen_name, Allergen.{});
+ allergen := map.get(^allergen_map, allergen_name);
if allergen.name.data == null {
allergen.name = allergen_name;
array.init(^allergen.appears_on, 4);
potential_allergen_count := 0;
for ^allergen_name: potential_allergens {
c := array_count_contains(^potential_allergens, *allergen_name, string.equal);
- allergen := map.get(^allergen_map, *allergen_name, Allergen.{});
+ allergen := map.get(^allergen_map, *allergen_name);
if c == allergen.appears_on.count {
potential_allergen_count += 1;
}
total_safe := 0;
for safe: definitely_safe {
- ingredient := map.get(^ingredient_map, safe, Ingredient.{});
+ ingredient := map.get(^ingredient_map, safe);
total_safe += ingredient.appears_on.count;
map.delete(^ingredient_map, safe);
}
if match_count == 1 {
- ingredient := map.get(^ingredient_map, matching_ingredient_name, Ingredient.{});
+ ingredient := map.get(^ingredient_map, matching_ingredient_name);
map.delete(^ingredient_map, matching_ingredient_name);
ingredient.allergen = allergen_entry.key;
recursive_combat :: proc (player1: ^[..] u32, player2: ^[..] u32) -> u32 {
hand_seen : map.Map(str, bool);
- map.init(^hand_seen, 31);
+ map.init(^hand_seen, false, 31);
defer map.free(^hand_seen);
while player1.count > 0 && player2.count > 0 {
file := reader.make(contents);
grid : map.Map(Vec2, Cell); // `true` is black
- map.init(^grid, 1021);
+ map.init(^grid, Cell.{}, 1021);
defer map.free(^grid);
while !reader.empty(^file) {
}
- curr := map.get(^grid, loc, Cell.{});
+ curr := map.get(^grid, loc);
map.put(^grid, loc, Cell.{ alive = !curr.alive });
}
}
for ^cell: cells_to_consider {
- state := map.get(^grid, *cell, Cell.{});
+ state := map.get(^grid, *cell);
ncount := get_neighbor_count(^grid, *cell);
if state.alive {
count := 0;
for ^dir: Hex_Directions {
- cell := map.get(grid, Vec2.{ x = pos.x + dir.x, y = pos.y + dir.y }, Cell.{});
+ cell := map.get(grid, Vec2.{ x = pos.x + dir.x, y = pos.y + dir.y });
if cell.alive do count += 1;
}
m := cast(u32) ceil_f64(sqrt_f64(~~n));
t : map.Map(u32, u32);
- map.init(^t, m / 2);
+ map.init(^t, 0, m / 2);
defer map.free(^t);
tmp: u64 = 1;
tmp = ~~b;
for i: 0 .. m {
if map.has(^t, cast(u32) tmp) {
- v := map.get(^t, cast(u32) tmp, 0);
+ v := map.get(^t, cast(u32) tmp);
return i * m + v;
}
bg_init :: proc (use graph: ^BagGraph) {
array.init(^nodes, 16);
- map.init(^node_map);
+ map.init(^node_map, null);
}
bg_free :: proc (use graph: ^BagGraph) {
// Returns if the program successfully exited.
get_acc_value :: proc (instrs: [..] Instruction, ret_acc: ^i32) -> bool {
already_been: map.Map(i32, bool);
- map.init(^already_been);
+ map.init(^already_been, false);
defer map.free(^already_been);
ip := 0;
print("\n");
pmap : map.Map(rawptr, rawptr);
- map.init(^pmap, 50);
+ map.init(^pmap, null, 50);
defer map.free(^pmap);
for i: 0 .. 100 do map.put(^pmap, ^s.a[i], ^s.b[i]);
main :: proc (args: [] cstr) {
imap : map.Map(i32, str);
- map.init(^imap);
+ map.init(^imap, "");
defer {
print("Freeing map\n");
map.free(^imap);
println(map.has(^imap, 50));
println(map.has(^imap, 51));
- printf("%s%s\n", map.get(^imap, 50, ""), map.get(^imap, 1234, ""));
+ printf("%s%s\n", map.get(^imap, 50), map.get(^imap, 1234));
map.delete(^imap, 50);
println(map.has(^imap, 50));
use package core
overloaded :: proc {
+ proc (x: str, y: i32) do println("Called str, i32"); ,
proc (x: f32, y: str) do println("Called f32, str"); ,
proc (x: i32, y: i32) do println("Called i32, i32"); ,
}