implement null as a literal type
This commit is contained in:
parent
1f7ec741fa
commit
651dc31247
@ -202,6 +202,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/builtin.zig" DESTINATION "${ZIG_STD_DEST}
|
|||||||
install(FILES "${CMAKE_SOURCE_DIR}/std/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}")
|
install(FILES "${CMAKE_SOURCE_DIR}/std/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/std/cstr.zig" DESTINATION "${ZIG_STD_DEST}")
|
install(FILES "${CMAKE_SOURCE_DIR}/std/cstr.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/std/debug.zig" DESTINATION "${ZIG_STD_DEST}")
|
install(FILES "${CMAKE_SOURCE_DIR}/std/debug.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||||
|
install(FILES "${CMAKE_SOURCE_DIR}/std/dwarf.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/std/elf.zig" DESTINATION "${ZIG_STD_DEST}")
|
install(FILES "${CMAKE_SOURCE_DIR}/std/elf.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/std/empty.zig" DESTINATION "${ZIG_STD_DEST}")
|
install(FILES "${CMAKE_SOURCE_DIR}/std/empty.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/std/endian.zig" DESTINATION "${ZIG_STD_DEST}")
|
install(FILES "${CMAKE_SOURCE_DIR}/std/endian.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||||
|
@ -394,6 +394,7 @@ enum CastOp {
|
|||||||
CastOpWidenOrShorten,
|
CastOpWidenOrShorten,
|
||||||
CastOpToUnknownSizeArray,
|
CastOpToUnknownSizeArray,
|
||||||
CastOpMaybeWrap,
|
CastOpMaybeWrap,
|
||||||
|
CastOpNullToMaybe,
|
||||||
CastOpErrorWrap,
|
CastOpErrorWrap,
|
||||||
CastOpPureErrorWrap,
|
CastOpPureErrorWrap,
|
||||||
CastOpPointerReinterpret,
|
CastOpPointerReinterpret,
|
||||||
@ -692,19 +693,16 @@ struct AstNodeContainerInitExpr {
|
|||||||
|
|
||||||
struct AstNodeNullLiteral {
|
struct AstNodeNullLiteral {
|
||||||
// populated by semantic analyzer
|
// populated by semantic analyzer
|
||||||
StructValExprCodeGen resolved_struct_val_expr;
|
|
||||||
Expr resolved_expr;
|
Expr resolved_expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstNodeUndefinedLiteral {
|
struct AstNodeUndefinedLiteral {
|
||||||
// populated by semantic analyzer
|
// populated by semantic analyzer
|
||||||
StructValExprCodeGen resolved_struct_val_expr;
|
|
||||||
Expr resolved_expr;
|
Expr resolved_expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstNodeZeroesLiteral {
|
struct AstNodeZeroesLiteral {
|
||||||
// populated by semantic analyzer
|
// populated by semantic analyzer
|
||||||
StructValExprCodeGen resolved_struct_val_expr;
|
|
||||||
Expr resolved_expr;
|
Expr resolved_expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -989,6 +987,7 @@ enum TypeTableEntryId {
|
|||||||
TypeTableEntryIdNumLitFloat,
|
TypeTableEntryIdNumLitFloat,
|
||||||
TypeTableEntryIdNumLitInt,
|
TypeTableEntryIdNumLitInt,
|
||||||
TypeTableEntryIdUndefLit,
|
TypeTableEntryIdUndefLit,
|
||||||
|
TypeTableEntryIdNullLit,
|
||||||
TypeTableEntryIdMaybe,
|
TypeTableEntryIdMaybe,
|
||||||
TypeTableEntryIdErrorUnion,
|
TypeTableEntryIdErrorUnion,
|
||||||
TypeTableEntryIdPureError,
|
TypeTableEntryIdPureError,
|
||||||
@ -1228,6 +1227,7 @@ struct CodeGen {
|
|||||||
TypeTableEntry *entry_num_lit_int;
|
TypeTableEntry *entry_num_lit_int;
|
||||||
TypeTableEntry *entry_num_lit_float;
|
TypeTableEntry *entry_num_lit_float;
|
||||||
TypeTableEntry *entry_undef;
|
TypeTableEntry *entry_undef;
|
||||||
|
TypeTableEntry *entry_null;
|
||||||
TypeTableEntry *entry_pure_error;
|
TypeTableEntry *entry_pure_error;
|
||||||
TypeTableEntry *entry_os_enum;
|
TypeTableEntry *entry_os_enum;
|
||||||
TypeTableEntry *entry_arch_enum;
|
TypeTableEntry *entry_arch_enum;
|
||||||
|
@ -237,6 +237,7 @@ static bool type_is_complete(TypeTableEntry *type_entry) {
|
|||||||
case TypeTableEntryIdNumLitFloat:
|
case TypeTableEntryIdNumLitFloat:
|
||||||
case TypeTableEntryIdNumLitInt:
|
case TypeTableEntryIdNumLitInt:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdMaybe:
|
case TypeTableEntryIdMaybe:
|
||||||
case TypeTableEntryIdErrorUnion:
|
case TypeTableEntryIdErrorUnion:
|
||||||
case TypeTableEntryIdPureError:
|
case TypeTableEntryIdPureError:
|
||||||
@ -925,6 +926,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
|
|||||||
case TypeTableEntryIdNumLitFloat:
|
case TypeTableEntryIdNumLitFloat:
|
||||||
case TypeTableEntryIdNumLitInt:
|
case TypeTableEntryIdNumLitInt:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdNamespace:
|
case TypeTableEntryIdNamespace:
|
||||||
case TypeTableEntryIdGenericFn:
|
case TypeTableEntryIdGenericFn:
|
||||||
fn_proto->skip = true;
|
fn_proto->skip = true;
|
||||||
@ -963,6 +965,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
|
|||||||
case TypeTableEntryIdNumLitFloat:
|
case TypeTableEntryIdNumLitFloat:
|
||||||
case TypeTableEntryIdNumLitInt:
|
case TypeTableEntryIdNumLitInt:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdUnreachable:
|
case TypeTableEntryIdUnreachable:
|
||||||
case TypeTableEntryIdNamespace:
|
case TypeTableEntryIdNamespace:
|
||||||
case TypeTableEntryIdGenericFn:
|
case TypeTableEntryIdGenericFn:
|
||||||
@ -1912,6 +1915,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
|
|||||||
case TypeTableEntryIdNumLitFloat:
|
case TypeTableEntryIdNumLitFloat:
|
||||||
case TypeTableEntryIdNumLitInt:
|
case TypeTableEntryIdNumLitInt:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdNamespace:
|
case TypeTableEntryIdNamespace:
|
||||||
case TypeTableEntryIdGenericFn:
|
case TypeTableEntryIdGenericFn:
|
||||||
return false;
|
return false;
|
||||||
@ -2167,6 +2171,13 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implicit conversion from null literal to maybe type
|
||||||
|
if (expected_type->id == TypeTableEntryIdMaybe &&
|
||||||
|
actual_type->id == TypeTableEntryIdNullLit)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// implicit conversion from error child type to error type
|
// implicit conversion from error child type to error type
|
||||||
if (expected_type->id == TypeTableEntryIdErrorUnion &&
|
if (expected_type->id == TypeTableEntryIdErrorUnion &&
|
||||||
types_match_with_implicit_cast(g, expected_type->data.error.child_type, actual_type,
|
types_match_with_implicit_cast(g, expected_type->data.error.child_type, actual_type,
|
||||||
@ -2971,13 +2982,6 @@ static TypeTableEntry *resolve_expr_const_val_as_bool(CodeGen *g, AstNode *node,
|
|||||||
return g->builtin_types.entry_bool;
|
return g->builtin_types.entry_bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeTableEntry *resolve_expr_const_val_as_null(CodeGen *g, AstNode *node, TypeTableEntry *type) {
|
|
||||||
Expr *expr = get_resolved_expr(node);
|
|
||||||
expr->const_val.ok = true;
|
|
||||||
expr->const_val.data.x_maybe = nullptr;
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TypeTableEntry *resolve_expr_const_val_as_non_null(CodeGen *g, AstNode *node,
|
static TypeTableEntry *resolve_expr_const_val_as_non_null(CodeGen *g, AstNode *node,
|
||||||
TypeTableEntry *type, ConstExprValue *other_val)
|
TypeTableEntry *type, ConstExprValue *other_val)
|
||||||
{
|
{
|
||||||
@ -3358,6 +3362,7 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
|
|||||||
case TypeTableEntryIdArray:
|
case TypeTableEntryIdArray:
|
||||||
case TypeTableEntryIdStruct:
|
case TypeTableEntryIdStruct:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdMaybe:
|
case TypeTableEntryIdMaybe:
|
||||||
case TypeTableEntryIdErrorUnion:
|
case TypeTableEntryIdErrorUnion:
|
||||||
case TypeTableEntryIdUnion:
|
case TypeTableEntryIdUnion:
|
||||||
@ -3916,26 +3921,17 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i
|
|||||||
{
|
{
|
||||||
assert(node->type == NodeTypeNullLiteral);
|
assert(node->type == NodeTypeNullLiteral);
|
||||||
|
|
||||||
if (!expected_type) {
|
ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
|
||||||
add_node_error(g, node, buf_sprintf("unable to determine null type"));
|
const_val->ok = true;
|
||||||
return g->builtin_types.entry_invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expected_type->id != TypeTableEntryIdMaybe) {
|
return g->builtin_types.entry_null;
|
||||||
add_node_error(g, node,
|
|
||||||
buf_sprintf("expected maybe type, got '%s'", buf_ptr(&expected_type->name)));
|
|
||||||
return g->builtin_types.entry_invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->data.null_literal.resolved_struct_val_expr.type_entry = expected_type;
|
|
||||||
node->data.null_literal.resolved_struct_val_expr.source_node = node;
|
|
||||||
|
|
||||||
return resolve_expr_const_val_as_null(g, node, expected_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
|
||||||
TypeTableEntry *expected_type, AstNode *node)
|
TypeTableEntry *expected_type, AstNode *node)
|
||||||
{
|
{
|
||||||
|
assert(node->type == NodeTypeUndefinedLiteral);
|
||||||
|
|
||||||
Expr *expr = get_resolved_expr(node);
|
Expr *expr = get_resolved_expr(node);
|
||||||
ConstExprValue *const_val = &expr->const_val;
|
ConstExprValue *const_val = &expr->const_val;
|
||||||
|
|
||||||
@ -4519,6 +4515,14 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// explicit cast from null literal to maybe type
|
||||||
|
if (wanted_type->id == TypeTableEntryIdMaybe &&
|
||||||
|
actual_type->id == TypeTableEntryIdNullLit)
|
||||||
|
{
|
||||||
|
get_resolved_expr(node)->return_knowledge = ReturnKnowledgeKnownNull;
|
||||||
|
return resolve_cast(g, context, node, expr_node, wanted_type, CastOpNullToMaybe, true);
|
||||||
|
}
|
||||||
|
|
||||||
// explicit cast from child type of error type to error type
|
// explicit cast from child type of error type to error type
|
||||||
if (wanted_type->id == TypeTableEntryIdErrorUnion) {
|
if (wanted_type->id == TypeTableEntryIdErrorUnion) {
|
||||||
if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
|
if (types_match_const_cast_only(wanted_type->data.error.child_type, actual_type)) {
|
||||||
@ -5203,6 +5207,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
|
|||||||
case TypeTableEntryIdNumLitFloat:
|
case TypeTableEntryIdNumLitFloat:
|
||||||
case TypeTableEntryIdNumLitInt:
|
case TypeTableEntryIdNumLitInt:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdNamespace:
|
case TypeTableEntryIdNamespace:
|
||||||
case TypeTableEntryIdGenericFn:
|
case TypeTableEntryIdGenericFn:
|
||||||
add_node_error(g, expr_node,
|
add_node_error(g, expr_node,
|
||||||
@ -6252,13 +6257,12 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
|
|||||||
if (resolved_type->id == TypeTableEntryIdInvalid) {
|
if (resolved_type->id == TypeTableEntryIdInvalid) {
|
||||||
return resolved_type;
|
return resolved_type;
|
||||||
} else if (resolved_type->id == TypeTableEntryIdErrorUnion) {
|
} else if (resolved_type->id == TypeTableEntryIdErrorUnion) {
|
||||||
TypeTableEntry *return_type = context->fn_entry->type_entry->data.fn.fn_type_id.return_type;
|
if (expected_return_type->id != TypeTableEntryIdErrorUnion &&
|
||||||
if (return_type->id != TypeTableEntryIdErrorUnion &&
|
expected_return_type->id != TypeTableEntryIdPureError)
|
||||||
return_type->id != TypeTableEntryIdPureError)
|
|
||||||
{
|
{
|
||||||
ErrorMsg *msg = add_node_error(g, node,
|
ErrorMsg *msg = add_node_error(g, node,
|
||||||
buf_sprintf("%%return statement in function with return type '%s'",
|
buf_sprintf("%%return statement in function with return type '%s'",
|
||||||
buf_ptr(&return_type->name)));
|
buf_ptr(&expected_return_type->name)));
|
||||||
AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
|
AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
|
||||||
add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
|
add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
|
||||||
}
|
}
|
||||||
@ -6283,11 +6287,10 @@ static TypeTableEntry *analyze_return_expr(CodeGen *g, ImportTableEntry *import,
|
|||||||
if (resolved_type->id == TypeTableEntryIdInvalid) {
|
if (resolved_type->id == TypeTableEntryIdInvalid) {
|
||||||
return resolved_type;
|
return resolved_type;
|
||||||
} else if (resolved_type->id == TypeTableEntryIdMaybe) {
|
} else if (resolved_type->id == TypeTableEntryIdMaybe) {
|
||||||
TypeTableEntry *return_type = context->fn_entry->type_entry->data.fn.fn_type_id.return_type;
|
if (expected_return_type->id != TypeTableEntryIdMaybe) {
|
||||||
if (return_type->id != TypeTableEntryIdMaybe) {
|
|
||||||
ErrorMsg *msg = add_node_error(g, node,
|
ErrorMsg *msg = add_node_error(g, node,
|
||||||
buf_sprintf("?return statement in function with return type '%s'",
|
buf_sprintf("?return statement in function with return type '%s'",
|
||||||
buf_ptr(&return_type->name)));
|
buf_ptr(&expected_return_type->name)));
|
||||||
AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
|
AstNode *return_type_node = context->fn_entry->fn_def_node->data.fn_def.fn_proto->data.fn_proto.return_type;
|
||||||
add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
|
add_error_note(g, msg, return_type_node, buf_sprintf("function return type here"));
|
||||||
}
|
}
|
||||||
@ -7227,6 +7230,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
|
|||||||
case TypeTableEntryIdNumLitFloat:
|
case TypeTableEntryIdNumLitFloat:
|
||||||
case TypeTableEntryIdNumLitInt:
|
case TypeTableEntryIdNumLitInt:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdNamespace:
|
case TypeTableEntryIdNamespace:
|
||||||
case TypeTableEntryIdGenericFn:
|
case TypeTableEntryIdGenericFn:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
@ -7335,6 +7339,8 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)
|
|||||||
return hash_ptr(const_val->data.x_ptr.ptr);
|
return hash_ptr(const_val->data.x_ptr.ptr);
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
return 162837799;
|
return 162837799;
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
|
return 844854567;
|
||||||
case TypeTableEntryIdArray:
|
case TypeTableEntryIdArray:
|
||||||
// TODO better hashing algorithm
|
// TODO better hashing algorithm
|
||||||
return 1166190605;
|
return 1166190605;
|
||||||
@ -7428,6 +7434,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
|
|||||||
case TypeTableEntryIdNumLitFloat:
|
case TypeTableEntryIdNumLitFloat:
|
||||||
case TypeTableEntryIdNumLitInt:
|
case TypeTableEntryIdNumLitInt:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdUnreachable:
|
case TypeTableEntryIdUnreachable:
|
||||||
case TypeTableEntryIdMetaType:
|
case TypeTableEntryIdMetaType:
|
||||||
case TypeTableEntryIdVoid:
|
case TypeTableEntryIdVoid:
|
||||||
|
@ -875,6 +875,9 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
|
|||||||
|
|
||||||
return cast_expr->tmp_ptr;
|
return cast_expr->tmp_ptr;
|
||||||
}
|
}
|
||||||
|
case CastOpNullToMaybe:
|
||||||
|
// handled by constant expression evaluator
|
||||||
|
zig_unreachable();
|
||||||
case CastOpErrorWrap:
|
case CastOpErrorWrap:
|
||||||
{
|
{
|
||||||
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
|
assert(wanted_type->id == TypeTableEntryIdErrorUnion);
|
||||||
@ -3806,6 +3809,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
|||||||
case TypeTableEntryIdNumLitFloat:
|
case TypeTableEntryIdNumLitFloat:
|
||||||
case TypeTableEntryIdNumLitInt:
|
case TypeTableEntryIdNumLitInt:
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
case TypeTableEntryIdVoid:
|
case TypeTableEntryIdVoid:
|
||||||
case TypeTableEntryIdNamespace:
|
case TypeTableEntryIdNamespace:
|
||||||
case TypeTableEntryIdGenericFn:
|
case TypeTableEntryIdGenericFn:
|
||||||
@ -4311,6 +4315,12 @@ static void define_builtin_types(CodeGen *g) {
|
|||||||
entry->deep_const = true;
|
entry->deep_const = true;
|
||||||
g->builtin_types.entry_undef = entry;
|
g->builtin_types.entry_undef = entry;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNullLit);
|
||||||
|
buf_init_from_str(&entry->name, "(null)");
|
||||||
|
entry->deep_const = true;
|
||||||
|
g->builtin_types.entry_null = entry;
|
||||||
|
}
|
||||||
|
|
||||||
for (int int_size_i = 0; int_size_i < array_length(int_sizes_in_bits); int_size_i += 1) {
|
for (int int_size_i = 0; int_size_i < array_length(int_sizes_in_bits); int_size_i += 1) {
|
||||||
int size_in_bits = int_sizes_in_bits[int_size_i];
|
int size_in_bits = int_sizes_in_bits[int_size_i];
|
||||||
|
@ -45,6 +45,8 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty
|
|||||||
zig_panic("TODO");
|
zig_panic("TODO");
|
||||||
case TypeTableEntryIdUndefLit:
|
case TypeTableEntryIdUndefLit:
|
||||||
zig_panic("TODO");
|
zig_panic("TODO");
|
||||||
|
case TypeTableEntryIdNullLit:
|
||||||
|
zig_panic("TODO");
|
||||||
case TypeTableEntryIdMaybe:
|
case TypeTableEntryIdMaybe:
|
||||||
zig_panic("TODO");
|
zig_panic("TODO");
|
||||||
case TypeTableEntryIdErrorUnion:
|
case TypeTableEntryIdErrorUnion:
|
||||||
@ -650,6 +652,10 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
|
|||||||
const_val->data.x_maybe = other_val;
|
const_val->data.x_maybe = other_val;
|
||||||
const_val->ok = true;
|
const_val->ok = true;
|
||||||
break;
|
break;
|
||||||
|
case CastOpNullToMaybe:
|
||||||
|
const_val->data.x_maybe = nullptr;
|
||||||
|
const_val->ok = true;
|
||||||
|
break;
|
||||||
case CastOpErrorWrap:
|
case CastOpErrorWrap:
|
||||||
const_val->data.x_err.err = nullptr;
|
const_val->data.x_err.err = nullptr;
|
||||||
const_val->data.x_err.payload = other_val;
|
const_val->data.x_err.payload = other_val;
|
||||||
|
@ -40,7 +40,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void {
|
|||||||
|
|
||||||
%return out_stream.printInt(usize, return_address);
|
%return out_stream.printInt(usize, return_address);
|
||||||
%return out_stream.printf(" -> ");
|
%return out_stream.printf(" -> ");
|
||||||
%return out_stream.printInt(u64, debug_info_offset);
|
%return out_stream.printInt(u64, compile_unit_offset);
|
||||||
%return out_stream.printf("\n");
|
%return out_stream.printf("\n");
|
||||||
maybe_fp = *(&const ?&const u8)(fp);
|
maybe_fp = *(&const ?&const u8)(fp);
|
||||||
}
|
}
|
||||||
@ -82,7 +82,8 @@ fn findCompileUnitOffset(st: &ElfStackTrace, target_address: usize) -> %u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn arangesOffset(st: &ElfStackTrace, target_address: usize) -> %?u64 {
|
fn arangesOffset(st: &ElfStackTrace, target_address: usize) -> %?u64 {
|
||||||
const aranges = ?return st.aranges;
|
// TODO ability to implicitly cast null to %?T
|
||||||
|
const aranges = st.aranges ?? return (?u64)(null);
|
||||||
|
|
||||||
%return st.elf.seekToSection(aranges);
|
%return st.elf.seekToSection(aranges);
|
||||||
|
|
||||||
@ -129,7 +130,8 @@ fn arangesOffset(st: &ElfStackTrace, target_address: usize) -> %?u64 {
|
|||||||
if (address == 0 && length == 0) break;
|
if (address == 0 && length == 0) break;
|
||||||
|
|
||||||
if (target_address >= address && target_address < address + length) {
|
if (target_address >= address && target_address < address + length) {
|
||||||
return debug_info_offset;
|
// TODO ability to implicitly cast T to %?T
|
||||||
|
return (?u64)(debug_info_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
test/cases/maybe_return.zig
Normal file
15
test/cases/maybe_return.zig
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const assert = @import("std").debug.assert;
|
||||||
|
|
||||||
|
#attribute("test")
|
||||||
|
fn maybeReturn() {
|
||||||
|
assert(??foo(1235));
|
||||||
|
assert(if (const _ ?= foo(null)) false else true);
|
||||||
|
assert(!??foo(1234));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add another function with static_eval_enable(true)
|
||||||
|
#static_eval_enable(false)
|
||||||
|
fn foo(x: ?i32) -> ?bool {
|
||||||
|
const value = ?return x;
|
||||||
|
return value > 1234;
|
||||||
|
}
|
@ -1211,7 +1211,7 @@ fn derp(){}
|
|||||||
|
|
||||||
add_compile_fail_case("assign null to non-nullable pointer", R"SOURCE(
|
add_compile_fail_case("assign null to non-nullable pointer", R"SOURCE(
|
||||||
const a: &u8 = null;
|
const a: &u8 = null;
|
||||||
)SOURCE", 1, ".tmp_source.zig:2:16: error: expected maybe type, got '&u8'");
|
)SOURCE", 1, ".tmp_source.zig:2:16: error: expected type '&u8', got '(null)'");
|
||||||
|
|
||||||
add_compile_fail_case("indexing an array of size zero", R"SOURCE(
|
add_compile_fail_case("indexing an array of size zero", R"SOURCE(
|
||||||
const array = []u8{};
|
const array = []u8{};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user