diff --git a/source/ast/renderer/renderer.hon b/source/ast/renderer/renderer.hon index 3c0f995..dfed97b 100644 --- a/source/ast/renderer/renderer.hon +++ b/source/ast/renderer/renderer.hon @@ -105,18 +105,12 @@ render_block proc(renderer @mut Renderer, tree @ast.Tree, block ast.NodeId, dept try append_text(renderer, ast.source_text(tree, ast.node_span(tree, loop.iterable))) try append_text(renderer, " |") if (loop.pointer_capture) try append_text(renderer, "@") - if (loop.capture) |capture| { - try append_text(renderer, ast.source_text(tree, ast.node_span(tree, capture))) - } else { - try append_text(renderer, "_") - } + if (loop.capture) |capture| try append_text(renderer, ast.source_text(tree, ast.node_span(tree, capture))) + else try append_text(renderer, "_") if (loop.index_capture) { try append_text(renderer, ", ") - if (loop.index) |index| { - try append_text(renderer, ast.source_text(tree, ast.node_span(tree, index))) - } else { - try append_text(renderer, "_") - } + if (loop.index) |index| try append_text(renderer, ast.source_text(tree, ast.node_span(tree, index))) + else try append_text(renderer, "_") } try append_text(renderer, "|\n") try render_block(renderer, tree, loop.body, depth + 1) diff --git a/source/compilation/compilation.hon b/source/compilation/compilation.hon index c313e92..6e17a7f 100644 --- a/source/compilation/compilation.hon +++ b/source/compilation/compilation.hon @@ -347,9 +347,7 @@ compile proc( for (0..ast.package_decl_count(&tree)) |i| try arraylist.append(&declarations, ast.package_decl(&tree, i)) } } - if (compilation.module_root == null) { - compilation.module_root = try ast.add_package(&compilation.builder, diagnostics.Span{ start = 0, end = 0 }, declarations.items) - } + if (compilation.module_root == null) compilation.module_root = try ast.add_package(&compilation.builder, diagnostics.Span{ start = 0, end = 0 }, declarations.items) imports := arraylist.init(sema.Import, compilation.allocator) defer arraylist.deinit(&imports) tree := ast.view(&compilation.builder, compilation.module_root?) @@ -362,11 +360,9 @@ compile proc( diagnostic.span.source == imported.path.source and diagnostic.span.start == imported.path.start and diagnostic.span.end == imported.path.end - and ( - diagnostic.code == .package_unavailable + and (diagnostic.code == .package_unavailable or diagnostic.code == .invalid_import_path - or diagnostic.code == .import_cycle - ) + or diagnostic.code == .import_cycle) ) { failure = diagnostics.DiagnosticId(index) break diff --git a/source/interpreter/interpreter.hon b/source/interpreter/interpreter.hon index 67b5e7c..3148fba 100644 --- a/source/interpreter/interpreter.hon +++ b/source/interpreter/interpreter.hon @@ -170,9 +170,7 @@ execute proc( for (frames.items) |frame| free_frame(allocator, frame) arraylist.deinit(&frames) } - if (module.functions.items[usize(entry)].external_name.len != 0) { - return try runtime_trap(diagnostic_store, .unsupported_foreign_call, module.functions.items[usize(entry)].span) - } + if (module.functions.items[usize(entry)].external_name.len != 0) return try runtime_trap(diagnostic_store, .unsupported_foreign_call, module.functions.items[usize(entry)].span) try push_frame(allocator, module, &frames, entry, ir.no_value, null) while frames.items.len != 0 { @@ -204,9 +202,7 @@ execute proc( continue } value := ir.Value{} - if terminator.value != ir.no_value { - value = frames.items[frame_index].values[usize(terminator.value)] - } + if (terminator.value != ir.no_value) value = frames.items[frame_index].values[usize(terminator.value)] completed :: frames.items[frame_index] # transfer leaves while the completed frame still owns its backing. if completed.global |global_index| { @@ -222,9 +218,7 @@ execute proc( } return Outcome{ value = value } } - if completed.destination != ir.no_value { - copy_value(module, &frames.items[frame_index - 1].values[usize(completed.destination)], value) - } + if (completed.destination != ir.no_value) copy_value(module, &frames.items[frame_index - 1].values[usize(completed.destination)], value) _ = arraylist.pop(&frames) free_frame(allocator, completed) continue @@ -237,9 +231,7 @@ execute proc( .constant: value = instruction.constant .load_local: { local :: &frames.items[frame_index].locals[usize(instruction.slot)] - if !local.initialized { - return try runtime_trap(diagnostic_store, .read_before_initialization, instruction.span) - } + if (!local.initialized) return try runtime_trap(diagnostic_store, .read_before_initialization, instruction.span) value = local.value } .store_local: { @@ -250,9 +242,7 @@ execute proc( } .assign_local: { local :: &frames.items[frame_index].locals[usize(instruction.slot)] - if (!local.initialized) { - return try runtime_trap(diagnostic_store, .write_before_initialization, instruction.span) - } + if (!local.initialized) return try runtime_trap(diagnostic_store, .write_before_initialization, instruction.span) copy_value(module, &local.value, frames.items[frame_index].values[usize(instruction.left)]) continue } @@ -283,13 +273,9 @@ execute proc( } .call: { callable :: frames.items[frame_index].values[usize(instruction.left)] - if (callable.data.function == maxval!(ir.FunctionId)) { - return try runtime_trap(diagnostic_store, .null_unwrap, instruction.span) - } + if (callable.data.function == maxval!(ir.FunctionId)) return try runtime_trap(diagnostic_store, .null_unwrap, instruction.span) callee :: callable.data.function - if (module.functions.items[usize(callee)].external_name.len != 0) { - return try runtime_trap(diagnostic_store, .unsupported_foreign_call, instruction.span) - } + if (module.functions.items[usize(callee)].external_name.len != 0) return try runtime_trap(diagnostic_store, .unsupported_foreign_call, instruction.span) try push_frame(allocator, module, &frames, callee, instruction.destination, null) # frame indices survive stack growth; pointers into frames.items do not. for (0..instruction.arguments_count) |argument_index| { @@ -346,9 +332,7 @@ execute proc( start :: frames.items[frame_index].values[usize(instruction.left)].data.unsigned end :: frames.items[frame_index].values[usize(instruction.right)].data.unsigned if (start > end) return try runtime_trap(diagnostic_store, .invalid_slice_bounds, instruction.span) - if (instruction.extra != ir.no_value and end > frames.items[frame_index].values[usize(instruction.extra)].data.unsigned) { - return try runtime_trap(diagnostic_store, .invalid_slice_bounds, instruction.span) - } + if (instruction.extra != ir.no_value and end > frames.items[frame_index].values[usize(instruction.extra)].data.unsigned) return try runtime_trap(diagnostic_store, .invalid_slice_bounds, instruction.span) continue } .optional_check: { @@ -423,17 +407,13 @@ execute proc( base :: frames.items[frame_index].values[usize(instruction.left)] index :: frames.items[frame_index].values[usize(instruction.right)].data.unsigned shape :: module.arrays.items[usize(base.array_type)] - if (index >= u64(shape.len)) { - return try runtime_trap(diagnostic_store, .index_out_of_bounds, instruction.span) - } + if (index >= u64(shape.len)) return try runtime_trap(diagnostic_store, .index_out_of_bounds, instruction.span) value = ir.aggregate_item(module, base, usize(index)) } .field: { base :: frames.items[frame_index].values[usize(instruction.left)] shape :: module.arrays.items[usize(base.array_type)] - if (shape.is_union and !ir.union_active(module, base, usize(instruction.slot))) { - return try runtime_trap(diagnostic_store, .inactive_union_field, instruction.span) - } + if (shape.is_union and !ir.union_active(module, base, usize(instruction.slot))) return try runtime_trap(diagnostic_store, .inactive_union_field, instruction.span) value = ir.aggregate_item(module, base, usize(instruction.slot)) } .address_local: { @@ -489,9 +469,7 @@ execute proc( base :: frames.items[frame_index].addresses[usize(base_id)] index :: frames.items[frame_index].values[usize(instruction.right)].data.unsigned shape :: module.arrays.items[usize(base.array_type)] - if (index >= u64(shape.len)) { - return try runtime_trap(diagnostic_store, .index_out_of_bounds, instruction.span) - } + if (index >= u64(shape.len)) return try runtime_trap(diagnostic_store, .index_out_of_bounds, instruction.span) width :: if (base.raw or base.byte_view) ir.storage_size(module, shape.element, shape.element_array) else element_cells(module, shape) start :: usize(index) * width address := base @@ -513,9 +491,7 @@ execute proc( if base.initialized |initialized| { if (!initialized^) return try runtime_trap(diagnostic_store, .read_before_initialization, instruction.span) } - if (!ir.union_active(module, read_address(module, base, scratch), usize(instruction.slot))) { - return try runtime_trap(diagnostic_store, .inactive_union_field, instruction.span) - } + if (!ir.union_active(module, read_address(module, base, scratch), usize(instruction.slot))) return try runtime_trap(diagnostic_store, .inactive_union_field, instruction.span) } raw :: base.raw or shape.is_union width :: if (raw or base.byte_view) ir.storage_size(module, field.type, field.array_type) else if (ir.aggregate(field.type)) module.arrays.items[usize(field.array_type)].cells else 1 @@ -548,9 +524,7 @@ execute proc( } .pointer_address: { handle :: frames.items[frame_index].values[usize(instruction.left)].data.unsigned - if (handle >= u64(pointers.items.len)) { - return try runtime_trap(diagnostic_store, .invalid_pointer_access, instruction.span) - } + if (handle >= u64(pointers.items.len)) return try runtime_trap(diagnostic_store, .invalid_pointer_access, instruction.span) location :: pointers.items[usize(handle)] if (pointer_address(module, location, instruction.pointee, instruction.array_type)) |address| { frames.items[frame_index].addresses[usize(instruction.destination)] = address @@ -561,19 +535,13 @@ execute proc( } .pointer_offset: { handle :: frames.items[frame_index].values[usize(instruction.left)].data.unsigned - if (handle >= u64(pointers.items.len)) { - return try runtime_trap(diagnostic_store, .invalid_pointer_access, instruction.span) - } + if (handle >= u64(pointers.items.len)) return try runtime_trap(diagnostic_store, .invalid_pointer_access, instruction.span) address := pointers.items[usize(handle)] index :: frames.items[frame_index].values[usize(instruction.right)].data.unsigned stride :: ir.storage_size(module, instruction.pointee, instruction.array_type) - if (stride != 0 and index > u64(divtrunc!(maxval!(usize) - address.byte_offset, stride))) { - return try runtime_trap(diagnostic_store, .invalid_pointer_access, instruction.span) - } + if (stride != 0 and index > u64(divtrunc!(maxval!(usize) - address.byte_offset, stride))) return try runtime_trap(diagnostic_store, .invalid_pointer_access, instruction.span) address.byte_offset += usize(index) * stride - if (address.byte_offset > pointer_size(module, address)) { - return try runtime_trap(diagnostic_store, .invalid_pointer_access, instruction.span) - } + if (address.byte_offset > pointer_size(module, address)) return try runtime_trap(diagnostic_store, .invalid_pointer_access, instruction.span) value = try pointer_value(&pointers, address) } .load_address, .store_address: { @@ -604,9 +572,7 @@ execute proc( if instruction.type == .float { value = ir.Value{ type = .float, data = ir.ValueData{ real = -operand.data.real } } } else { - if operand.data.integer == ir.integer_min(instruction.type) { - return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span) - } + if (operand.data.integer == ir.integer_min(instruction.type)) return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span) value = ir.Value{ type = instruction.type, data = ir.ValueData{ integer = -operand.data.integer } } } } @@ -638,9 +604,7 @@ execute proc( } else { result :: checked_integer(instruction.op, left.data.integer, right.data.integer) if result |result_integer| { - if (result_integer < ir.integer_min(instruction.type) or result_integer > i64(ir.integer_max(instruction.type))) { - return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span) - } + if (result_integer < ir.integer_min(instruction.type) or result_integer > i64(ir.integer_max(instruction.type))) return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span) value = ir.Value{ type = instruction.type, data = ir.ValueData{ integer = result_integer } } } else { return try runtime_trap(diagnostic_store, .integer_overflow, instruction.span) @@ -699,9 +663,7 @@ execute proc( value = ir.Value{ type = .bool, data = ir.ValueData{ boolean = result } } } } - if instruction.destination != ir.no_value { - copy_value(module, &frames.items[frame_index].values[usize(instruction.destination)], value) - } + if (instruction.destination != ir.no_value) copy_value(module, &frames.items[frame_index].values[usize(instruction.destination)], value) } unreachable } diff --git a/source/ir/ir.hon b/source/ir/ir.hon index 558d729..ff78456 100644 --- a/source/ir/ir.hon +++ b/source/ir/ir.hon @@ -434,9 +434,7 @@ storage_size proc(module @Module, type Type, shape ArrayId) usize { #! loads a scalar or borrows an aggregate from byte cells without allocating. read_storage proc(module @Module, type Type, shape ArrayId, cells []mut Value, raw bool) Value { - if (aggregate(type)) { - return Value{ type = type, array_type = shape, raw = raw, data = ValueData{ elements = cells[..storage_size(module, type, shape)] } } - } + if (aggregate(type)) return Value{ type = type, array_type = shape, raw = raw, data = ValueData{ elements = cells[..storage_size(module, type, shape)] } } bits u64 := 0 size :: storage_size(module, type, shape) count :: if (size > 8) usize(8) else size diff --git a/source/lexer/scan.hon b/source/lexer/scan.hon index a210b53..2f5dee4 100644 --- a/source/lexer/scan.hon +++ b/source/lexer/scan.hon @@ -358,14 +358,10 @@ scan_ident proc( cursor := start + 1 while ( cursor < program.len - and ( - is_alpha(program[cursor]) + and (is_alpha(program[cursor]) or is_digit(program[cursor]) - or program[cursor] == '_' - ) - ) { - cursor += 1 - } + or program[cursor] == '_') + ) cursor += 1 kind :: strmap.get(&keywords, program[start..cursor]) orelse .ident # member contexts accept keywords and therefore need their interned spelling too. diff --git a/source/llvm/instructions.hon b/source/llvm/instructions.hon index 59460ca..295ec08 100644 --- a/source/llvm/instructions.hon +++ b/source/llvm/instructions.hon @@ -201,9 +201,8 @@ emit_instruction proc(state @mut State, block @ir.Block, instruction ir.Instruct .optional_check: { operand :: try load(state, instruction.left) failed :: fresh(state) - if (state.values[usize(instruction.left)].kind == .bool) { - try io.print(" %r{} = xor i1 %r{}, true\n", output, {failed, operand}) - } else try io.print(" %r{} = icmp eq ptr %r{}, null\n", output, {failed, operand}) + if (state.values[usize(instruction.left)].kind == .bool) try io.print(" %r{} = xor i1 %r{}, true\n", output, {failed, operand}) + else try io.print(" %r{} = icmp eq ptr %r{}, null\n", output, {failed, operand}) try check_failure(state, failed, .null_unwrap, instruction.span) return } diff --git a/source/llvm/llvm.hon b/source/llvm/llvm.hon index adfc5aa..0caa50b 100644 --- a/source/llvm/llvm.hon +++ b/source/llvm/llvm.hon @@ -104,9 +104,7 @@ emit proc( mem.set(values, Type{}) for (function.blocks.items) |block| { for (block.instructions.items) |instruction| { - if (instruction.destination != ir.no_value) { - values[usize(instruction.destination)] = Type{ kind = instruction.type, shape = instruction.array_type } - } + if (instruction.destination != ir.no_value) values[usize(instruction.destination)] = Type{ kind = instruction.type, shape = instruction.array_type } } } state := State{ output = output, module = module, line_starts = line_starts.items, values = values } diff --git a/source/lower/lower.hon b/source/lower/lower.hon index a847db4..fd8565a 100644 --- a/source/lower/lower.hon +++ b/source/lower/lower.hon @@ -170,9 +170,7 @@ lower_module proc( @hide:file lower_type proc(state @State, type typecheck.Type) ir.Type { - if (type.kind == .enumeration) { - return lower_type(state, typecheck.Type{ kind = typecheck.enum_type(state.checked, type.enum_type).backing }) - } + if (type.kind == .enumeration) return lower_type(state, typecheck.Type{ kind = typecheck.enum_type(state.checked, type.enum_type).backing }) if (type.kind == .slice) return .record if (type.kind == .fallible) return .record if (type.kind == .optional) return lower_optional_type(state, typecheck.array_type(state.checked, type.array_type).element) @@ -562,11 +560,9 @@ lower_cleanups proc(state @mut State, depth usize, error_value ir.ValueId) void id :: state.cleanups.items[index] if (ast.stmt_kind(state.tree, id) == .errdefer_stmt and error_value == ir.no_value) continue cleanup :: ast.cleanup_stmt(state.tree, id) - if (cleanup.capture) |capture| { - _ = try emit(state, ir.Instruction{ - op = .store_local, left = error_value, slot = state.storage[usize(capture)].index, span = cleanup.span, - }) - } + if (cleanup.capture) |capture| _ = try emit(state, ir.Instruction{ + op = .store_local, left = error_value, slot = state.storage[usize(capture)].index, span = cleanup.span, + }) try lower_block(state, cleanup.body, true) if (state.terminated) return } @@ -800,10 +796,8 @@ lower_statement proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | d if ( ast.expr_kind(tree, assignment.target) == .index or ast.expr_kind(tree, assignment.target) == .unary - or ( - ast.expr_kind(tree, assignment.target) == .selection - and sema.binding(state.resolution, assignment.target).kind == .none - ) + or (ast.expr_kind(tree, assignment.target) == .selection + and sema.binding(state.resolution, assignment.target).kind == .none) ) { value :: try lower_as(state, assignment.value, typecheck.type_of(state.checked, assignment.target)) if (state.terminated) return @@ -865,9 +859,7 @@ lower_statement proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | d value := ir.no_value if (statement.value) |expression| value = try lower_as(state, expression, state.return_type) if (state.terminated or trap_type(state, id)) return - if (statement.value == null and state.return_type.kind == .fallible) { - value = try wrap_fallible(state, value, state.return_type, false, statement.span) - } + if (statement.value == null and state.return_type.kind == .fallible) value = try wrap_fallible(state, value, state.return_type, false, statement.span) try lower_return(state, value, statement.span) } } @@ -1080,11 +1072,8 @@ lower_union proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError | count :: ast.record_field_count(tree, id) contextual := false if (view.type) |annotation| contextual = ast.expr_kind(tree, annotation) == .enum_literal - if (contextual and field.type == .record and (count != 1 or ast.field(tree, ast.record_field(tree, id, 0)).name != null)) { - payload = try lower_record_as(state, id, typecheck.union_payload_type(state.checked, id)) - } else if (count != 0) { - payload = try lower_as(state, ast.field(tree, ast.record_field(tree, id, 0)).value?, typecheck.union_payload_type(state.checked, id)) - } + if (contextual and field.type == .record and (count != 1 or ast.field(tree, ast.record_field(tree, id, 0)).name != null)) payload = try lower_record_as(state, id, typecheck.union_payload_type(state.checked, id)) + else if (count != 0) payload = try lower_as(state, ast.field(tree, ast.record_field(tree, id, 0)).value?, typecheck.union_payload_type(state.checked, id)) } if (state.terminated) return ir.no_value return try emit(state, ir.Instruction{ @@ -1826,9 +1815,7 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr if (!trap_type(state, id)) unreachable } .array_type, .pointer_type, .function_type, .record_type, .enum_type, .union_type, .distinct_type, .slice_type, .optional_type, .fallible_type, .sum_type: { - if (!trap_type(state, id)) { - trap(state, try diagnostics.add(state.diagnostics, .type_not_value, span), span) - } + if (!trap_type(state, id)) trap(state, try diagnostics.add(state.diagnostics, .type_not_value, span), span) } .alias_expr: return try lower_expression(state, ast.type_operand(tree, id)) .enum_literal: { @@ -1843,9 +1830,7 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr .builtin_call: return try lower_builtin(state, id) .record_literal: { checked :: typecheck.type_of(state.checked, id) - if (checked.kind == .record and typecheck.record_type(state.checked, checked.record_type).is_union) { - return try lower_union(state, id) - } + if (checked.kind == .record and typecheck.record_type(state.checked, checked.record_type).is_union) return try lower_union(state, id) return try lower_record_as(state, id, checked) } .array_literal: { @@ -2014,9 +1999,7 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr text :: ast.literal_text(tree, expression.operand) magnitude_limit :: ir.integer_max(type) + 1 if (integer_magnitude(text, magnitude_limit)) |magnitude| { - if (magnitude == magnitude_limit) { - return try constant(state, ir.Value{ type = type, data = ir.ValueData{ integer = ir.integer_min(type) } }, span) - } + if (magnitude == magnitude_limit) return try constant(state, ir.Value{ type = type, data = ir.ValueData{ integer = ir.integer_min(type) } }, span) } } operand :: try lower_expression(state, expression.operand) @@ -2030,9 +2013,7 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr } .binary: { expression :: ast.binary_expr(tree, id) - if (expression.operator == .logical_and or expression.operator == .logical_or) { - return try lower_logical(state, id) - } + if (expression.operator == .logical_and or expression.operator == .logical_or) return try lower_logical(state, id) left_type :: typecheck.type_of(state.checked, expression.left) right_type :: typecheck.type_of(state.checked, expression.right) if ( @@ -2100,9 +2081,7 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr for (0..count) |i| { signature :: typecheck.type_of(state.checked, ast.call_expr(tree, id).callee).function expected := typecheck.Type{} - if (signature != ast.NodeId(maxval!(u32)) and i < ast.function_param_count(tree, signature)) { - expected = typecheck.type_of(state.checked, ast.param(tree, ast.function_param(tree, signature, i)).type) - } + if (signature != ast.NodeId(maxval!(u32)) and i < ast.function_param_count(tree, signature)) expected = typecheck.type_of(state.checked, ast.param(tree, ast.function_param(tree, signature, i)).type) argument :: try lower_as(state, ast.call_arg(tree, id, i), expected) if (state.terminated) return ir.no_value state.arguments.items[scratch_start + i] = argument @@ -2162,13 +2141,9 @@ lower_number proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError text :: ast.literal_text(state.tree, id) type :: lower_type(state, typecheck.type_of(state.checked, id)) if (ir.integer_bits(type) != 0 and !ir.unsigned_integer(type)) { - if (integer_magnitude(text, ir.integer_max(type))) |magnitude| { - return try constant(state, ir.Value{ type = type, data = ir.ValueData{ integer = i64(magnitude) } }, span) - } + if (integer_magnitude(text, ir.integer_max(type))) |magnitude| return try constant(state, ir.Value{ type = type, data = ir.ValueData{ integer = i64(magnitude) } }, span) } else if (ir.unsigned_integer(type)) { - if (integer_magnitude(text, ir.integer_max(type))) |magnitude| { - return try constant(state, ir.Value{ type = type, data = ir.ValueData{ unsigned = magnitude } }, span) - } + if (integer_magnitude(text, ir.integer_max(type))) |magnitude| return try constant(state, ir.Value{ type = type, data = ir.ValueData{ unsigned = magnitude } }, span) } else { value :: strconv.parse_float(state.module.allocator, text) catch |err| { match err { diff --git a/source/lower/lower.test.hon b/source/lower/lower.test.hon index 0ef1173..0faa78d 100644 --- a/source/lower/lower.test.hon +++ b/source/lower/lower.test.hon @@ -1695,11 +1695,8 @@ array_context_inference_empty_shapes_and_scalar_leaf_families test { outcome := try interpreter.run(mem.c_allocator, &module, &diagnostic_store) defer interpreter.deinit(&outcome) try testing.expect(outcome.trap == null) - if (outcome.value.type == .string) { - try testing.expect(mem.eql(ir.string_bytes(&module, outcome.value.data.string), "two")) - } else { - try testing.expect(outcome.value.data.boolean) - } + if (outcome.value.type == .string) try testing.expect(mem.eql(ir.string_bytes(&module, outcome.value.data.string), "two")) + else try testing.expect(outcome.value.data.boolean) } } diff --git a/source/parser/parse.hon b/source/parser/parse.hon index 209ce59..d7f6d11 100644 --- a/source/parser/parse.hon +++ b/source/parser/parse.hon @@ -277,8 +277,7 @@ parse_block proc(state @mut State) ast.NodeId ! ParseError { parse_statement proc(state @mut State, allow_else bool) ast.NodeId ! ParseError { if ( next_is(state, .ident) - and ( - next_n_is(state, 1, .ident) + and (next_n_is(state, 1, .ident) or next_n_is(state, 1, .struct) or next_n_is(state, 1, .enum) or next_n_is(state, 1, .union) or next_n_is(state, 1, .distinct) @@ -289,11 +288,8 @@ parse_statement proc(state @mut State, allow_else bool) ast.NodeId ! ParseError or (next_n_is(state, 1, .star) and pointer_binding_starts(state)) or (next_n_is(state, 1, .open_bracket) and array_starts_type(state)) or next_n_is(state, 1, .double_colon) - or next_n_is(state, 1, .colon_equal) - ) - ) { - return try parse_statement_decl(state) - } + or next_n_is(state, 1, .colon_equal)) + ) return try parse_statement_decl(state) match current(state).kind { .if: return try parse_if(state) .while: return try parse_while(state, allow_else) @@ -343,17 +339,13 @@ parse_return proc(state @mut State, allow_else bool) ast.NodeId ! ParseError { next_is(state, .newline) or next_is(state, .close_curly) or next_is(state, .eof) or (state.match_arm_body and next_is(state, .comma)) or (allow_else and next_is(state, .else)) - ) { - return try ast.add_return_stmt(state.builder, keyword.span, null) - } + ) return try ast.add_return_stmt(state.builder, keyword.span, null) value :: try parse_expr(state) if ( !next_is(state, .newline) and !next_is(state, .close_curly) and !next_is(state, .eof) and !(allow_else and next_is(state, .else)) and !(state.match_arm_body and next_is(state, .comma)) - ) { - return .unexpected_token - } + ) return .unexpected_token # include consumed grouping punctuation, which has no separate expression node. end :: state.tokens[state.next_token - 1].span.end return try ast.add_return_stmt( @@ -395,9 +387,7 @@ parse_assignment proc(state @mut State, target ast.NodeId, allow_else bool) ast. and !next_is(state, .eof) and !(allow_else and next_is(state, .else)) and !(state.match_arm_body and next_is(state, .comma)) - ) { - return .unexpected_token - } + ) return .unexpected_token end :: state.tokens[state.next_token - 1].span.end return try ast.add_assignment_stmt( state.builder, @@ -1176,10 +1166,8 @@ parse_record_field proc(state @mut State, declaration bool) ast.NodeId ! ParseEr value ?ast.NodeId := null named :: ( member_name(current(state).kind) - and ( - (!declaration and next_n_is(state, 1, .equal)) - or (declaration and starts_type(state.tokens[state.next_token + 1].kind)) - ) + and ((!declaration and next_n_is(state, 1, .equal)) + or (declaration and starts_type(state.tokens[state.next_token + 1].kind))) ) if (named) { token :: if (declaration) try consume(state, .ident) else try consume_member(state, false) @@ -1596,14 +1584,12 @@ pointer_binding_starts proc(state @State) bool { named_binding_starts proc(state @State) bool { return ( next_is(state, .ident) - and ( - next_n_is(state, 1, .double_colon) or next_n_is(state, 1, .colon_equal) + and (next_n_is(state, 1, .double_colon) or next_n_is(state, 1, .colon_equal) or next_n_is(state, 1, .ident) or next_n_is(state, 1, .proc) or next_n_is(state, 1, .match) or next_n_is(state, 1, .at) or next_n_is(state, 1, .question) or (next_n_is(state, 1, .open_paren) and pointer_binding_starts(state)) - or (next_n_is(state, 1, .star) and pointer_binding_starts(state)) - ) + or (next_n_is(state, 1, .star) and pointer_binding_starts(state))) ) } @@ -1699,9 +1685,7 @@ parse_primary proc(state @mut State) ast.NodeId ! ParseError { else: { diagnostic :: try unexpected_diagnostic(state) - if !is_expression_recovery_boundary(token.kind) { - state.next_token += 1 - } + if (!is_expression_recovery_boundary(token.kind)) state.next_token += 1 return try ast.add_invalid_expr(state.builder, token.span, diagnostic) } @@ -1846,9 +1830,7 @@ recovery_closes_delimiters proc(state @State, paren_depth, square_depth usize) b .ident: { if (i + 1 < state.tokens.len) { next :: state.tokens[i + 1].kind - if (next == .double_colon or next == .colon_equal or next == .ident or next == .proc) { - return false - } + if (next == .double_colon or next == .colon_equal or next == .ident or next == .proc) return false } } else: {} @@ -1865,9 +1847,7 @@ recovery_closes_delimiters proc(state @State, paren_depth, square_depth usize) b @hide:file unexpected_diagnostic proc(state @mut State) diagnostics.DiagnosticId ! (mem.AllocError | diagnostics.CapacityError) { token :: current(state) - if (token.kind == .invalid and token.data.diagnostic != diagnostics.no_diagnostic) { - return token.data.diagnostic - } + if (token.kind == .invalid and token.data.diagnostic != diagnostics.no_diagnostic) return token.data.diagnostic return try diagnostics.add(state.diagnostics, .unexpected_token, token.span) } diff --git a/source/parser/parse.test.hon b/source/parser/parse.test.hon index 0bcffa4..3fa1ba2 100644 --- a/source/parser/parse.test.hon +++ b/source/parser/parse.test.hon @@ -442,11 +442,8 @@ parses_return_boundaries_and_recovers_trailing_tokens test { try testing.expect_equal(ast.StmtKind.expression, ast.stmt_kind(&tree, ast.block_statement(&tree, body, 1))) grouped :: ast.return_stmt(&tree, ast.block_statement(&tree, body, 2)) try testing.expect_equal("return (3 + 4)", ast.source_text(&tree, grouped.span)) - if (grouped.value) |value| { - try testing.expect_equal(ast.ExprKind.binary, ast.expr_kind(&tree, value)) - } else { - return .expectation_failed - } + if (grouped.value) |value| try testing.expect_equal(ast.ExprKind.binary, ast.expr_kind(&tree, value)) + else return .expectation_failed try testing.expect_equal(ast.StmtKind.invalid, ast.stmt_kind(&tree, ast.block_statement(&tree, body, 3))) after :: ast.statement_decl(&tree, ast.block_statement(&tree, body, 4)) try testing.expect_equal("after", ast.source_text(&tree, after.name)) @@ -1146,9 +1143,8 @@ rejects_control_tails_and_preserves_following_declarations test { } conditional :: ast.if_stmt(&tree, ast.block_statement(&tree, loop.body, 4)) try testing.expect_equal(ast.StmtKind.invalid, ast.stmt_kind(&tree, ast.block_statement(&tree, conditional.then_block, 0))) - if (conditional.else_block) |other| { - try testing.expect_equal(ast.StmtKind.continue_stmt, ast.stmt_kind(&tree, ast.block_statement(&tree, other, 0))) - } else return .expectation_failed + if (conditional.else_block) |other| try testing.expect_equal(ast.StmtKind.continue_stmt, ast.stmt_kind(&tree, ast.block_statement(&tree, other, 0))) + else return .expectation_failed try testing.expect_equal(ast.StmtKind.declaration, ast.stmt_kind(&tree, ast.block_statement(&tree, body, 1))) try testing.expect_equal(ast.DeclKind.statement, ast.decl_kind(&tree, ast.package_decl(&tree, 5))) } diff --git a/source/sema/check/check.hon b/source/sema/check/check.hon index 78e1ee1..640fc3e 100644 --- a/source/sema/check/check.hon +++ b/source/sema/check/check.hon @@ -360,9 +360,7 @@ check_elaborated proc( if ( binding.kind == .declaration and !cells[i].assignment_value and !cells[usize(binding.data.declaration)].fixed and !has_narrowing(&state, id) - ) { - join(&state, id, binding.data.declaration) - } + ) join(&state, id, binding.data.declaration) } # assignment inputs observe established declaration types, never contribute @@ -844,10 +842,8 @@ check_annotation proc(state @mut State, id ast.NodeId, allow_void bool) Type ! ( element := try check_annotation(state, view.element, true) element_binding :: sema.binding(state.resolution, view.element) if ( - ( - element_binding.kind == .builtin - and (element_binding.data.builtin == .int or element_binding.data.builtin == .float) - ) + (element_binding.kind == .builtin + and (element_binding.data.builtin == .int or element_binding.data.builtin == .float)) or element.kind == .void or element.kind == .range ) { element = invalid_type(try diagnostics.add(state.diagnostics, .invalid_array_element_type, ast.node_span(state.tree, view.element))) @@ -1233,9 +1229,7 @@ collect_expression proc(state @mut State, id ast.NodeId) void ! (mem.AllocError if ( role != .parameter and role != .loop_capture and ast.decl_kind(tree, target) == .statement and type_syntax(ast.expr_kind(tree, ast.statement_decl(tree, target).initializer)) - ) { - state.cells[usize(id)].type = invalid_type(try diagnostics.add(state.diagnostics, .type_not_value, ast.node_span(tree, id))) - } + ) state.cells[usize(id)].type = invalid_type(try diagnostics.add(state.diagnostics, .type_not_value, ast.node_span(tree, id))) } match binding.kind { .invalid: state.cells[usize(id)].type = invalid_type(binding.data.diagnostic) @@ -1464,13 +1458,11 @@ bool_equality proc(state @mut State, id ast.NodeId) bool { right :: group_type(state, expression.right) return ( (expression.operator == .equal or expression.operator == .not_equal) - and ( - (left.kind == .bool and right.kind == .bool) + and ((left.kind == .bool and right.kind == .bool) or left.kind == .enumeration or right.kind == .enumeration or left.kind == .pointer or right.kind == .pointer or left.kind == .optional or right.kind == .optional - or left.kind == .null or right.kind == .null - ) + or left.kind == .null or right.kind == .null) ) } @@ -1739,10 +1731,8 @@ mutable_target proc(state @mut State, id ast.NodeId, allow_global bool) bool { pointer :: state.pointers.items[usize(base.pointer_type)] return ( pointer.mutable - and ( - pointer.many - or (pointer.element.kind == .array and state.arrays.items[usize(pointer.element.array_type)].mutable) - ) + and (pointer.many + or (pointer.element.kind == .array and state.arrays.items[usize(pointer.element.array_type)].mutable)) ) } if (base.kind == .slice) return state.arrays.items[usize(base.array_type)].mutable @@ -1950,9 +1940,7 @@ validate proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagnost } else if ( expected.kind != .void and !(expected.kind == .fallible and state.arrays.items[usize(expected.array_type)].element.kind == .void) - ) { - try fail(state, id, .return_type_mismatch, statement.span) - } + ) try fail(state, id, .return_type_mismatch, statement.span) } .expression: { match ast.expr_kind(tree, id) { @@ -1975,24 +1963,18 @@ validate proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagnost return } if (expression.operator == .unwrap) { - if (state.types[usize(expression.operand)].kind != .optional and state.types[usize(expression.operand)].kind != .invalid) { - try fail(state, id, .invalid_operand, expression.span) - } + if (state.types[usize(expression.operand)].kind != .optional and state.types[usize(expression.operand)].kind != .invalid) try fail(state, id, .invalid_operand, expression.span) return } if (expression.operator == .dereference) { if ( state.types[usize(expression.operand)].kind != .invalid and state.types[usize(expression.operand)].kind != .pointer - ) { - try fail(state, id, .invalid_dereference, expression.span) - } + ) try fail(state, id, .invalid_dereference, expression.span) return } operand :: state.types[usize(expression.operand)] - if (operand.kind != .invalid and (!numeric_kind(operand.kind) or unsigned_kind(operand.kind))) { - try fail(state, id, .invalid_operand, ast.node_span(tree, id)) - } + if (operand.kind != .invalid and (!numeric_kind(operand.kind) or unsigned_kind(operand.kind))) try fail(state, id, .invalid_operand, ast.node_span(tree, id)) } .binary: { expression :: ast.binary_expr(tree, id) @@ -2005,9 +1987,7 @@ validate proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagnost right :: state.types[usize(expression.right)] if (left.kind == .invalid or right.kind == .invalid) return if (pointer_addition(state, id)) { - if (right.kind != .usize or right.nominal != ast.NodeId(maxval!(u32))) { - try fail(state, id, .invalid_operand, expression.span) - } + if (right.kind != .usize or right.nominal != ast.NodeId(maxval!(u32))) try fail(state, id, .invalid_operand, expression.span) return } if ( @@ -2019,11 +1999,8 @@ validate proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagnost and (left.kind == .bool or left.kind == .enumeration or left.kind == .pointer) and (assignable_type(state, left, right) or assignable_type(state, right, left)) ) return - if (!numeric_kind(left.kind) or !numeric_kind(right.kind) or !same_type(state, left, right)) { - try fail(state, id, .invalid_operand, expression.span) - } else if (expression.operator == .divide and left.kind != .float) { - try fail(state, id, .integer_division, expression.span) - } + if (!numeric_kind(left.kind) or !numeric_kind(right.kind) or !same_type(state, left, right)) try fail(state, id, .invalid_operand, expression.span) + else if (expression.operator == .divide and left.kind != .float) try fail(state, id, .integer_division, expression.span) } .range: { if (state.cells[usize(id)].match_pattern) return @@ -2032,12 +2009,8 @@ validate proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagnost end_type :: state.types[usize(expression.end)] family TypeKind :: if (integer_kind(start_type.kind)) start_type.kind else if (integer_kind(end_type.kind)) end_type.kind else .int - if (start_type.kind != .invalid and (!integer_kind(start_type.kind) or start_type.kind != family)) { - try fail(state, expression.start, .invalid_range_bound, ast.node_span(tree, expression.start)) - } - if (end_type.kind != .invalid and (!integer_kind(end_type.kind) or end_type.kind != family)) { - try fail(state, expression.end, .invalid_range_bound, ast.node_span(tree, expression.end)) - } + if (start_type.kind != .invalid and (!integer_kind(start_type.kind) or start_type.kind != family)) try fail(state, expression.start, .invalid_range_bound, ast.node_span(tree, expression.start)) + if (end_type.kind != .invalid and (!integer_kind(end_type.kind) or end_type.kind != family)) try fail(state, expression.end, .invalid_range_bound, ast.node_span(tree, expression.end)) } .array_literal: { actual :: state.types[usize(id)] @@ -2045,11 +2018,8 @@ validate proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagnost element :: state.arrays.items[usize(actual.array_type)].element for 0..ast.array_element_count(tree, id) |i| { child :: ast.array_element(tree, id, i) - if (element.kind == .void or element.kind == .range) { - try fail(state, child, .invalid_array_element_type, ast.node_span(tree, child)) - } else { - try compatible(state, child, element) - } + if (element.kind == .void or element.kind == .range) try fail(state, child, .invalid_array_element_type, ast.node_span(tree, child)) + else try compatible(state, child, element) } if (array_cells(state, actual) == null) try fail(state, id, .array_size_overflow, ast.node_span(tree, id)) } @@ -2057,9 +2027,7 @@ validate proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagnost actual :: state.types[usize(id)] if (actual.kind != .record) return descriptor := state.records.items[usize(actual.record_type)] - if (state.variant_slots[usize(id)] != no_index and state.backings[usize(id)].kind == .record) { - descriptor = state.records.items[usize(state.backings[usize(id)].record_type)] - } + if (state.variant_slots[usize(id)] != no_index and state.backings[usize(id)].kind == .record) descriptor = state.records.items[usize(state.backings[usize(id)].record_type)] fields :: descriptor.fields slot :: state.slots[usize(id)] if (slot == no_index) return @@ -2073,12 +2041,8 @@ validate proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | diagnost view :: ast.index_expr(tree, id) base :: state.types[usize(view.base)] index :: state.types[usize(view.index)] - if (index.kind != .invalid and (index.kind != .usize or index.nominal != ast.NodeId(maxval!(u32)))) { - try fail(state, view.index, .invalid_index_type, ast.node_span(tree, view.index)) - } - if (base.kind != .invalid and !indexable_type(state, base)) { - try fail(state, id, .not_indexable, ast.node_span(tree, view.base)) - } + if (index.kind != .invalid and (index.kind != .usize or index.nominal != ast.NodeId(maxval!(u32)))) try fail(state, view.index, .invalid_index_type, ast.node_span(tree, view.index)) + if (base.kind != .invalid and !indexable_type(state, base)) try fail(state, id, .not_indexable, ast.node_span(tree, view.base)) } .call: try validate_call(state, id) .builtin_call: _ = try infer_builtin(state, id, true) @@ -2116,13 +2080,9 @@ validate_call proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | dia backing :: immediate_backing(state, actual) if ( actual.kind != .invalid - and ( - !numeric_kind(backing.kind) and !allowed_enum - or backing.nominal != ast.NodeId(maxval!(u32)) - ) - ) { - try fail(state, argument, .invalid_operand, ast.node_span(tree, argument)) - } + and (!numeric_kind(backing.kind) and !allowed_enum + or backing.nominal != ast.NodeId(maxval!(u32))) + ) try fail(state, argument, .invalid_operand, ast.node_span(tree, argument)) } return } @@ -2283,9 +2243,7 @@ intern_pointer proc(state @mut State, descriptor PointerType) Type ! mem.AllocEr if ( existing.mutable == descriptor.mutable and existing.many == descriptor.many and same_type(state, existing.element, descriptor.element) - ) { - return Type{ kind = .pointer, pointer_type = PointerId(i) } - } + ) return Type{ kind = .pointer, pointer_type = PointerId(i) } } try arraylist.append(&state.pointers, descriptor) return Type{ kind = .pointer, pointer_type = PointerId(state.pointers.items.len - 1) } @@ -2304,9 +2262,7 @@ check_pointer_type proc(state @mut State, id ast.NodeId) Type ! (mem.AllocError or element.kind == .type_value or has_inferred_count(state, element) or (binding.kind == .builtin and (binding.data.builtin == .int or binding.data.builtin == .float)) - ) { - return invalid_type(try diagnostics.add(state.diagnostics, .invalid_pointer_type, ast.node_span(state.tree, id))) - } + ) return invalid_type(try diagnostics.add(state.diagnostics, .invalid_pointer_type, ast.node_span(state.tree, id))) return try intern_pointer(state, PointerType{ element = element, mutable = view.mutable, many = view.many }) } @@ -2346,9 +2302,7 @@ intern_array proc(state @mut State, descriptor ArrayType) Type ! mem.AllocError existing.kind == descriptor.kind and existing.len == descriptor.len and existing.mutable == descriptor.mutable and same_sentinel(existing.sentinel, descriptor.sentinel) and same_type(state, existing.element, descriptor.element) and same_type(state, existing.error_type, descriptor.error_type) - ) { - return Type{ kind = descriptor.kind, array_type = ArrayId(i) } - } + ) return Type{ kind = descriptor.kind, array_type = ArrayId(i) } } try arraylist.append(&state.arrays, descriptor) return Type{ kind = descriptor.kind, array_type = ArrayId(state.arrays.items.len - 1) } @@ -3074,9 +3028,7 @@ apply_contexts proc(state @mut State, assignment_values, early bool) void ! (mem if ( ast.call_arg_count(tree, id) == 1 and (backing.nominal != ast.NodeId(maxval!(u32)) or !numeric_kind(backing.kind)) - ) { - try context_demand(state, ast.call_arg(tree, id, 0), backing, .type_mismatch, early) - } + ) try context_demand(state, ast.call_arg(tree, id, 0), backing, .type_mismatch, early) continue } if (conversion_kind(state, id) != .none) { @@ -3165,9 +3117,7 @@ prepare_ranges proc(state @mut State, assignment_values, constrain bool) void ! if ( binding.kind == .declaration and state.cells[usize(binding.data.declaration)].role == .loop_capture and !has_narrowing(state, id) - ) { - seed(state, id, group_type(state, binding.data.declaration)) - } + ) seed(state, id, group_type(state, binding.data.declaration)) } } @@ -3230,9 +3180,7 @@ specialize_annotations proc(state @mut State) void ! (mem.AllocError | diagnosti if ( binding.kind == .declaration and state.cells[usize(binding.data.declaration)].fixed and !has_narrowing(state, id) - ) { - seed(state, id, state.cells[usize(binding.data.declaration)].type) - } + ) seed(state, id, state.cells[usize(binding.data.declaration)].type) } } @@ -3742,9 +3690,7 @@ check_union proc(state @mut State, id ast.NodeId, nominal bool) Type ! (mem.Allo if ( type.kind == .none or type.kind == .range or type.kind == .type_value or field.value != null or (type.kind == .void and tag.kind == .none and !view.auto_tag) - ) { - return invalid_type(try diagnostics.add(state.diagnostics, .invalid_record_field_type, field.span)) - } + ) return invalid_type(try diagnostics.add(state.diagnostics, .invalid_record_field_type, field.span)) if (field.name == null or named_field(state.tree, fields[0..i], field.name?) != no_index) { return invalid_type(try diagnostics.add(state.diagnostics, .duplicate_field, field.span)) } @@ -4201,21 +4147,13 @@ validate_match proc(state @mut State, id ast.NodeId) void ! (mem.AllocError | di current :: try pattern_interval(state, pattern, key) if (current) |interval| { if ( - ( - interval.real and ( - interval.real_low > interval.real_high - or (!interval.inclusive and interval.real_low == interval.real_high) - ) - ) - or ( - !interval.real and ( - constant_order(interval.low, interval.high) > 0 - or (!interval.inclusive and constant_order(interval.low, interval.high) == 0) - ) - ) - ) { - try fail(state, id, .invalid_match_pattern, ast.node_span(state.tree, pattern)) - } + (interval.real and ( + interval.real_low > interval.real_high + or (!interval.inclusive and interval.real_low == interval.real_high))) + or (!interval.real and ( + constant_order(interval.low, interval.high) > 0 + or (!interval.inclusive and constant_order(interval.low, interval.high) == 0))) + ) try fail(state, id, .invalid_match_pattern, ast.node_span(state.tree, pattern)) if (key.kind == .bool) { if (interval.low.magnitude == 0) seen_false = true else seen_true = true } @@ -4348,20 +4286,14 @@ check_fallible_type proc(state @mut State, id ast.NodeId) Type ! (mem.AllocError if (failure.kind == .invalid) return failure valid_error :: ( failure.kind == .enumeration - or ( - failure.kind == .record - and ( - !state.records.items[usize(failure.record_type)].is_union - or state.records.items[usize(failure.record_type)].tag_type.kind == .enumeration - ) - ) + or (failure.kind == .record + and (!state.records.items[usize(failure.record_type)].is_union + or state.records.items[usize(failure.record_type)].tag_type.kind == .enumeration)) ) if ( !valid_error or success.kind == .none or success.kind == .range or success.kind == .type_value or success.kind == .anyopaque or has_inferred_count(state, success) - ) { - return invalid_type(try diagnostics.add(state.diagnostics, .invalid_fallible_type, ast.node_span(state.tree, id))) - } + ) return invalid_type(try diagnostics.add(state.diagnostics, .invalid_fallible_type, ast.node_span(state.tree, id))) type :: try intern_array(state, ArrayType{ kind = .fallible, element = success, error_type = failure }) state.cells[usize(id)].type = type return type @@ -4536,14 +4468,10 @@ validate_fallible_expression proc(state @mut State, id ast.NodeId) void ! (mem.A if (catching) { expression :: ast.catch_expr(state.tree, id) if (expression.handler_is_block) { - if (descriptor.element.kind != .void and block_falls_through(state, expression.handler)) { - try fail(state, expression.handler, .catch_type_mismatch, ast.node_span(state.tree, expression.handler)) - } + if (descriptor.element.kind != .void and block_falls_through(state, expression.handler)) try fail(state, expression.handler, .catch_type_mismatch, ast.node_span(state.tree, expression.handler)) } else { actual :: state.types[usize(expression.handler)] - if (actual.kind != .invalid and !assignable_value(state, expression.handler, actual, descriptor.element)) { - try fail(state, expression.handler, .catch_type_mismatch, ast.node_span(state.tree, expression.handler)) - } + if (actual.kind != .invalid and !assignable_value(state, expression.handler, actual, descriptor.element)) try fail(state, expression.handler, .catch_type_mismatch, ast.node_span(state.tree, expression.handler)) } return } @@ -4558,18 +4486,15 @@ validate_fallible_expression proc(state @mut State, id ast.NodeId) void ! (mem.A } result :: state.types[usize(annotation)] if (result.kind == .invalid) return - if (result.kind != .fallible) { - try fail(state, id, .try_outside_fallible, ast.node_span(state.tree, id)) - } else if ( + if (result.kind != .fallible) try fail(state, id, .try_outside_fallible, ast.node_span(state.tree, id)) + else if ( !error_subset( state.records.items, state.enums.items, descriptor.error_type, state.arrays.items[usize(result.array_type)].error_type, ) - ) { - try fail(state, id, .incompatible_propagated_error, ast.node_span(state.tree, id)) - } + ) try fail(state, id, .incompatible_propagated_error, ast.node_span(state.tree, id)) } @hide:file diff --git a/source/sema/check/check.test.hon b/source/sema/check/check.test.hon index 3d162d8..7d99cdb 100644 --- a/source/sema/check/check.test.hon +++ b/source/sema/check/check.test.hon @@ -168,11 +168,8 @@ rejects_fixed_family_conversion_integer_division_and_conflicting_demands test { for conflicts |declaration| { try testing.expect_equal(TypeKind.invalid, type_of(&result, declaration).kind) diagnostic :: type_of(&result, declaration).diagnostic - if (diagnostics.get(&diagnostic_store, diagnostic)) |error| { - try testing.expect_equal(diagnostics.Code.type_mismatch, error.code) - } else { - return .expectation_failed - } + if (diagnostics.get(&diagnostic_store, diagnostic)) |error| try testing.expect_equal(diagnostics.Code.type_mismatch, error.code) + else return .expectation_failed try testing.expect_equal(diagnostic, type_of(&result, ast.statement_decl(&tree, declaration).initializer).diagnostic) } conflict_uses [4]usize :: [8, 9, 11, 12] @@ -294,11 +291,8 @@ separates_type_annotations_from_values_and_restricts_void_storage test { defer deinit(&result) bad :: ast.statement_decl(&tree, ast.package_decl(&tree, 1)) - if (bad.type) |annotation| { - _ = try expect_error(&result, &diagnostic_store, annotation, .expected_type, ast.node_span(&tree, annotation)) - } else { - return .expectation_failed - } + if (bad.type) |annotation| _ = try expect_error(&result, &diagnostic_store, annotation, .expected_type, ast.node_span(&tree, annotation)) + else return .expectation_failed _ = try expect_error(&result, &diagnostic_store, bad.initializer, .invalid_operand, ast.node_span(&tree, bad.initializer)) builtin :: ast.statement_decl(&tree, ast.package_decl(&tree, 2)).initializer _ = try expect_error(&result, &diagnostic_store, builtin, .type_not_value, ast.node_span(&tree, builtin)) @@ -322,11 +316,8 @@ separates_type_annotations_from_values_and_restricts_void_storage test { try testing.expect_equal(void_error, type_of(&result, void_b).diagnostic) try expect_kind(&result, ast.function_decl(&tree, void_function).return_type, .void) storage :: ast.statement_decl(&tree, ast.package_decl(&tree, 5)) - if (storage.type) |annotation| { - _ = try expect_error(&result, &diagnostic_store, annotation, .invalid_void_type, ast.node_span(&tree, annotation)) - } else { - return .expectation_failed - } + if (storage.type) |annotation| _ = try expect_error(&result, &diagnostic_store, annotation, .invalid_void_type, ast.node_span(&tree, annotation)) + else return .expectation_failed holder :: ast.statement_decl(&tree, ast.package_decl(&tree, 8)).initializer _ = try expect_error(&result, &diagnostic_store, holder, .type_mismatch, ast.node_span(&tree, holder)) operand :: ast.statement_decl(&tree, ast.package_decl(&tree, 9)).initializer @@ -677,11 +668,8 @@ returns_supply_numeric_context_and_resolve_forward_local_and_parameter_names tes } identity :: ast.package_decl(&tree, 1) identity_body :: ast.function_decl(&tree, identity).body - if (ast.return_stmt(&tree, ast.block_statement(&tree, identity_body, 0)).value) |value| { - try testing.expect_equal(ast.function_param(&tree, identity, 0), sema.binding(&resolution, value).data.declaration) - } else { - return .expectation_failed - } + if (ast.return_stmt(&tree, ast.block_statement(&tree, identity_body, 0)).value) |value| try testing.expect_equal(ast.function_param(&tree, identity, 0), sema.binding(&resolution, value).data.declaration) + else return .expectation_failed try testing.expect_equal(0, diagnostics.count(&diagnostic_store)) } @@ -1429,11 +1417,8 @@ logical_operand_errors_are_independent_and_skipped_rhs_preserves_bool test { try expect_kind(&result, loop.condition, .bool) returned :: ast.block_statement(&tree, body, 6) try expect_kind(&result, returned, .void) - if (ast.return_stmt(&tree, returned).value) |value| { - try expect_kind(&result, value, .bool) - } else { - return .expectation_failed - } + if (ast.return_stmt(&tree, returned).value) |value| try expect_kind(&result, value, .bool) + else return .expectation_failed try testing.expect_equal(7, code_count(&diagnostic_store, .unknown_name)) try testing.expect_equal(8, code_count(&diagnostic_store, .invalid_operand)) try testing.expect_equal(15, diagnostics.count(&diagnostic_store)) @@ -2271,9 +2256,7 @@ nested_array_numeric_context_flows_through_index_children_before_defaults test { for usize(1)..usize(4) |i| { element_kind TypeKind :: if (i == 2) .float else .array type :: try expect_array(result, ast.package_decl(tree, i), 2, false, element_kind) - if (type.element.kind == .array) { - try testing.expect_equal(TypeKind.float, array_type(result, type.element.array_type).element.kind) - } + if (type.element.kind == .array) try testing.expect_equal(TypeKind.float, array_type(result, type.element.array_type).element.kind) } matrix :: ast.statement_decl(tree, ast.package_decl(tree, 1)).initializer for 0..ast.array_element_count(tree, matrix) |i| { diff --git a/source/sema/resolve.hon b/source/sema/resolve.hon index 0dc3a60..4334cc4 100644 --- a/source/sema/resolve.hon +++ b/source/sema/resolve.hon @@ -349,9 +349,7 @@ resolve_function proc( for (0..ast.function_param_count(tree, id)) |i| { parameter :: ast.function_param(tree, id, i) try resolve_expr(state, &signature, ast.param(tree, parameter).type) - if (ast.param(tree, parameter).comptime) { - try predeclare(state, &signature, parameter, ast.param(tree, parameter).name) - } + if (ast.param(tree, parameter).comptime) try predeclare(state, &signature, parameter, ast.param(tree, parameter).name) } try resolve_expr(state, &signature, function.return_type) scope := Scope{ @@ -381,9 +379,7 @@ resolve_block proc(state @mut State, scope @mut Scope, id ast.NodeId) void ! (me tree :: state.tree for (0..ast.block_statement_count(tree, id)) |i| { statement :: ast.block_statement(tree, id, i) - if ast.stmt_kind(tree, statement) == .declaration { - try predeclare(state, scope, statement, ast.statement_decl(tree, statement).name) - } + if (ast.stmt_kind(tree, statement) == .declaration) try predeclare(state, scope, statement, ast.statement_decl(tree, statement).name) } for (0..ast.block_statement_count(tree, id)) |i| { statement :: ast.block_statement(tree, id, i) @@ -423,12 +419,8 @@ resolve_block proc(state @mut State, scope @mut Scope, id ast.NodeId) void ! (me parent = scope, } defer hashmap.deinit(&body_scope.names) - if (loop.capture) |capture| { - try predeclare(state, &body_scope, capture, ast.node_span(tree, capture)) - } - if (loop.index) |index| { - try predeclare(state, &body_scope, index, ast.node_span(tree, index)) - } + if (loop.capture) |capture| try predeclare(state, &body_scope, capture, ast.node_span(tree, capture)) + if (loop.index) |index| try predeclare(state, &body_scope, index, ast.node_span(tree, index)) try resolve_block(state, &body_scope, loop.body) } .invalid: resolve_invalid(state, statement) @@ -451,9 +443,7 @@ resolve_statement_decl proc( id ast.NodeId, ) void ! (mem.AllocError | diagnostics.CapacityError) { declaration :: ast.statement_decl(state.tree, id) - if (ast.expr_kind(state.tree, declaration.initializer) == .alias_expr) { - state.aliases[usize(id)] = ast.type_operand(state.tree, declaration.initializer) - } + if (ast.expr_kind(state.tree, declaration.initializer) == .alias_expr) state.aliases[usize(id)] = ast.type_operand(state.tree, declaration.initializer) if (declaration.type) |type| try resolve_expr(state, scope, type) try resolve_expr(state, scope, declaration.initializer) } @@ -562,9 +552,7 @@ resolve_expr proc( try resolve_expr(state, scope, expression.operand) handler_scope := Scope{ names = hashmap.init(state.allocator), parent = scope } defer hashmap.deinit(&handler_scope.names) - if (expression.capture) |capture| { - try predeclare(state, &handler_scope, capture, ast.node_span(tree, capture)) - } + if (expression.capture) |capture| try predeclare(state, &handler_scope, capture, ast.node_span(tree, capture)) if (expression.handler_is_block) try resolve_block(state, &handler_scope, expression.handler) else try resolve_expr(state, &handler_scope, expression.handler) } diff --git a/source/sema/resolve.test.hon b/source/sema/resolve.test.hon index 80ce979..60b9183 100644 --- a/source/sema/resolve.test.hon +++ b/source/sema/resolve.test.hon @@ -581,9 +581,8 @@ range_captures_preserve_duplicate_builtin_and_discard_errors test { } else return .expectation_failed } indexed :: ast.for_stmt(&tree, ast.block_statement(&tree, body, 3)) - if (indexed.index) |index| { - try testing.expect_equal(BindingKind.invalid, binding(&resolution, index).kind) - } else return .expectation_failed + if (indexed.index) |index| try testing.expect_equal(BindingKind.invalid, binding(&resolution, index).kind) + else return .expectation_failed if (indexed.capture) |capture| { reference :: ast.statement_expr(&tree, ast.block_statement(&tree, indexed.body, 0)) try testing.expect_equal(capture, binding(&resolution, reference).data.declaration) diff --git a/source/sema/specialize/specialize.hon b/source/sema/specialize/specialize.hon index a92f0cc..3c56a1e 100644 --- a/source/sema/specialize/specialize.hon +++ b/source/sema/specialize/specialize.hon @@ -528,11 +528,8 @@ specialize_call proc(state @mut State, call, function ast.NodeId) void ! Error { } callee :: try reference(state, call, target) replacement := no_node - if (state.instances.items[instance].type != no_node) { - replacement = try ast.add_type_operand(state.builder, ast.node_span(&state.tree, call), callee, true) - } else { - replacement = try ast.add_call(state.builder, ast.node_span(&state.tree, call), callee, runtime_arguments.items) - } + if (state.instances.items[instance].type != no_node) replacement = try ast.add_type_operand(state.builder, ast.node_span(&state.tree, call), callee, true) + else replacement = try ast.add_call(state.builder, ast.node_span(&state.tree, call), callee, runtime_arguments.items) try replace(state, call, replacement) try refresh(state) } @@ -1554,13 +1551,10 @@ evaluate proc(state @mut State, id ast.NodeId) Value ! Error { .unary: { view :: ast.unary_expr(&state.tree, id) value := try evaluate(state, view.operand) - if (view.operator == .negate and value.kind == .integer) { - value.negative = value.magnitude != 0 and !value.negative - } else if (view.operator == .negate and value.kind == .real) { - value.magnitude = value.magnitude xor (u64(1) << 63) - } else if (view.operator == .logical_not and value.kind == .boolean) { - value.boolean = !value.boolean - } else return Value{} + if (view.operator == .negate and value.kind == .integer) value.negative = value.magnitude != 0 and !value.negative + else if (view.operator == .negate and value.kind == .real) value.magnitude = value.magnitude xor (u64(1) << 63) + else if (view.operator == .logical_not and value.kind == .boolean) value.boolean = !value.boolean + else return Value{} value.node = id return value } @@ -1642,9 +1636,7 @@ evaluate_binary proc(state @mut State, id ast.NodeId) Value ! Error { if (left.magnitude > maxval!(u64) - right.magnitude) return Value{} return try integer_value(state, id, left.magnitude + right.magnitude, left.negative, annotation) } - if (left.magnitude < right.magnitude) { - return try integer_value(state, id, right.magnitude - left.magnitude, right.negative, annotation) - } + if (left.magnitude < right.magnitude) return try integer_value(state, id, right.magnitude - left.magnitude, right.negative, annotation) return try integer_value(state, id, left.magnitude - right.magnitude, left.magnitude != right.magnitude and left.negative, annotation) } @@ -1666,9 +1658,7 @@ same_type proc(state @mut State, left, right ast.NodeId) bool ! Error { if (a == b) return true x :: binding(state, a) y :: binding(state, b) - if (x.kind == .builtin or y.kind == .builtin) { - return x.kind == .builtin and y.kind == .builtin and builtin_identity(x.data.builtin) == builtin_identity(y.data.builtin) - } + if (x.kind == .builtin or y.kind == .builtin) return x.kind == .builtin and y.kind == .builtin and builtin_identity(x.data.builtin) == builtin_identity(y.data.builtin) kind :: ast.expr_kind(&state.tree, a) if (kind == .sum_type or ast.expr_kind(&state.tree, b) == .sum_type) return try type_subset(state, a, b) and try type_subset(state, b, a) @@ -1908,9 +1898,7 @@ expression_type proc(state @mut State, id ast.NodeId, depth usize) ast.NodeId ! callee :: ast.call_expr(&state.tree, id).callee destination :: binding(state, callee) if (destination.kind == .builtin) return callee - if (destination.kind == .declaration and ast.node_class(&state.tree, destination.data.declaration) == .function) { - return try canonical_type(state, ast.function_decl(&state.tree, destination.data.declaration).return_type) - } + if (destination.kind == .declaration and ast.node_class(&state.tree, destination.data.declaration) == .function) return try canonical_type(state, ast.function_decl(&state.tree, destination.data.declaration).return_type) signature :: try expression_type(state, callee, depth + 1) if (signature != no_node and ast.expr_kind(&state.tree, signature) == .function_type) return try canonical_type(state, ast.callable_result(&state.tree, signature)) diff --git a/std/arraylist/arraylist.hon b/std/arraylist/arraylist.hon index efb5b56..e44d53d 100644 --- a/std/arraylist/arraylist.hon +++ b/std/arraylist/arraylist.hon @@ -38,15 +38,10 @@ reserve proc( new_capacity := 8 if list.capacity >= 8 { half :: divtrunc!(list.capacity, 2) - if list.capacity > maxval!(usize) - half { - new_capacity = min_capacity - } else { - new_capacity = list.capacity + half - } - } - if new_capacity < min_capacity { - new_capacity = min_capacity + if (list.capacity > maxval!(usize) - half) new_capacity = min_capacity + else new_capacity = list.capacity + half } + if (new_capacity < min_capacity) new_capacity = min_capacity length :: list.items.len allocation :: list.items.ptr[..list.capacity] @@ -60,9 +55,7 @@ reserve proc( append proc($T type, list @mut ArrayList(T), value T) void ! mem.AllocError { length :: list.items.len - if length == maxval!(usize) { - return .out_of_memory - } + if (length == maxval!(usize)) return .out_of_memory try reserve(list, length + 1) list.items = list.items.ptr[..length + 1] list.items[length] = value diff --git a/std/hashmap/hashmap.hon b/std/hashmap/hashmap.hon index 89e7d1b..16a3fc6 100644 --- a/std/hashmap/hashmap.hon +++ b/std/hashmap/hashmap.hon @@ -71,11 +71,8 @@ get proc( if (map.count == 0) return null hash usize := 0 - if $(hash_key == null) { - hash = normalize(auto_hash(K, key)) - } else { - hash = normalize(call_hash(K, hash_key?, key)) - } + if ($(hash_key == null)) hash = normalize(auto_hash(K, key)) + else hash = normalize(call_hash(K, hash_key?, key)) idx := hash & (map.entries.len - 1) while true { @@ -114,9 +111,7 @@ put proc( if (entry.hash == 0) continue idx := entry.hash & (new_entries.len - 1) - while new_entries[idx].hash != 0 { - idx = (idx + 1) & (new_entries.len - 1) - } + while (new_entries[idx].hash != 0) idx = (idx + 1) & (new_entries.len - 1) new_entries[idx] = entry } @@ -126,11 +121,8 @@ put proc( } hash usize := 0 - if $(hash_key == null) { - hash = normalize(auto_hash(K, key)) - } else { - hash = normalize(call_hash(K, hash_key?, key)) - } + if ($(hash_key == null)) hash = normalize(auto_hash(K, key)) + else hash = normalize(call_hash(K, hash_key?, key)) idx := hash & (map.entries.len - 1) while true { diff --git a/std/io/io.hon b/std/io/io.hon index d69d680..9a55584 100644 --- a/std/io/io.hon +++ b/std/io/io.hon @@ -269,9 +269,7 @@ parse_format proc($N usize, $format []u8, $Args type) [N]mut FormatToken { while cursor < format.len { byte :: format[cursor] if byte == '{' { - if cursor + 1 >= format.len { - compile_error!("io.print format has an unmatched '{'") - } + if (cursor + 1 >= format.len) compile_error!("io.print format has an unmatched '{'") if cursor > literal_start { tokens[token_count] = FormatToken{ kind = .literal, @@ -298,9 +296,7 @@ parse_format proc($N usize, $format []u8, $Args type) [N]mut FormatToken { kind FormatTokenKind := .default width := 2 if next != '}' { - if cursor + 2 >= format.len or format[cursor + 2] != '}' { - compile_error!("io.print format expects a one-character specifier") - } + if (cursor + 2 >= format.len or format[cursor + 2] != '}') compile_error!("io.print format expects a one-character specifier") width = 3 if (next == 's') kind = .string @@ -314,9 +310,7 @@ parse_format proc($N usize, $format []u8, $Args type) [N]mut FormatToken { else compile_error!("io.print format has an unknown specifier") } - if argument_count >= field_count { - compile_error!("io.print format argument count does not match the tuple") - } + if (argument_count >= field_count) compile_error!("io.print format argument count does not match the tuple") tokens[token_count] = FormatToken{ kind = kind, @@ -333,9 +327,7 @@ parse_format proc($N usize, $format []u8, $Args type) [N]mut FormatToken { } if byte == '}' { - if cursor + 1 >= format.len or format[cursor + 1] != '}' { - compile_error!("io.print format has an unmatched '}'") - } + if (cursor + 1 >= format.len or format[cursor + 1] != '}') compile_error!("io.print format has an unmatched '}'") if cursor > literal_start { tokens[token_count] = FormatToken{ kind = .literal, @@ -368,9 +360,7 @@ parse_format proc($N usize, $format []u8, $Args type) [N]mut FormatToken { } } - if argument_count != field_count { - compile_error!("io.print format argument count does not match the tuple") - } + if (argument_count != field_count) compile_error!("io.print format argument count does not match the tuple") return tokens } @@ -466,9 +456,7 @@ write_decimal proc($T type, output Writer, value T) void ! WriteError { write_character proc($T type, output Writer, value T) void ! WriteError { match typeinfo!(T) { .integer: { - if minval!(T) < 0 or maxval!(T) > 255 { - compile_error!("io.print '{c}' requires an unsigned integer that fits in u8") - } + if (minval!(T) < 0 or maxval!(T) > 255) compile_error!("io.print '{c}' requires an unsigned integer that fits in u8") buffer [1]u8 :: [u8(value)] try write_all(output, buffer[..]) } diff --git a/std/mem/mem.hon b/std/mem/mem.hon index 1725255..03f96da 100644 --- a/std/mem/mem.hon +++ b/std/mem/mem.hon @@ -70,9 +70,7 @@ alloc proc($T type, allocator Allocator, count usize) []mut T ! AllocError { element_size :: sizeof!(T) if (element_size == 0) return empty_slice(T, count) - if count > divtrunc!(maxval!(usize), element_size) { - return .out_of_memory - } + if (count > divtrunc!(maxval!(usize), element_size)) return .out_of_memory memory :: raw_alloc(allocator, count * element_size, alignof!(T)) if memory |bytes| { @@ -194,9 +192,7 @@ c_realloc proc( } if memory |old_memory| { - if alignment <= malloc_alignment { - return ptrcast!(c.realloc(old_memory, c_ulong(new_size))) - } + if (alignment <= malloc_alignment) return ptrcast!(c.realloc(old_memory, c_ulong(new_size))) new_memory :: c_alloc(null, new_size, alignment) if new_memory |new_bytes| { diff --git a/std/strconv/strconv.hon b/std/strconv/strconv.hon index 15aaf5c..00b2d84 100644 --- a/std/strconv/strconv.hon +++ b/std/strconv/strconv.hon @@ -58,9 +58,7 @@ parse_float proc(allocator mem.Allocator, text []u8) f64 ! (mem.AllocError | Par magnitude >= u64(9218868437227405312) or (magnitude == 0 and nonzero) or (range_error and magnitude >= u64(4607182418800017408)) - ) { - return .out_of_range - } + ) return .out_of_range return value } diff --git a/std/strmap/strmap.hon b/std/strmap/strmap.hon index d33336d..7694386 100644 --- a/std/strmap/strmap.hon +++ b/std/strmap/strmap.hon @@ -18,23 +18,17 @@ Pair proc($V type) type { #! initializes a static string map from a list of key-value pairs (constructed at compile-time). #! returned views use compile-time storage and require no cleanup. init proc($V type, $N usize, $entries [N]Pair(V)) StaticStringMap(V) { - if N > usize(maxval!(u32)) { - compile_error!("static string map has too many entries") - } + if (N > usize(maxval!(u32))) compile_error!("static string map has too many entries") keys [N]mut []u8 := undefined values [N]mut V := undefined # assert no duplicate keys for entries |entry, i| { - if entry.0.len > usize(maxval!(u32)) { - compile_error!("static string map key is too long") - } + if (entry.0.len > usize(maxval!(u32))) compile_error!("static string map key is too long") for (0..i) |prior| { - if mem.eql(u8, entry.0, entries[prior].0) { - compile_error!("duplicate static string map key") - } + if mem.eql(u8, entry.0, entries[prior].0) compile_error!("duplicate static string map key") } keys[i] = entry.0