mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge remote-tracking branch 'origin/master' into llvm7
This commit is contained in:
commit
7dd18294b7
@ -1565,7 +1565,7 @@ var foo: u8 align(4) = 100;
|
||||
test "global variable alignment" {
|
||||
assert(@typeOf(&foo).alignment == 4);
|
||||
assert(@typeOf(&foo) == *align(4) u8);
|
||||
const slice = (&foo)[0..1];
|
||||
const slice = (*[1]u8)(&foo)[0..];
|
||||
assert(@typeOf(slice) == []align(4) u8);
|
||||
}
|
||||
|
||||
@ -1671,7 +1671,7 @@ test "using slices for strings" {
|
||||
|
||||
test "slice pointer" {
|
||||
var array: [10]u8 = undefined;
|
||||
const ptr = &array[0];
|
||||
const ptr = &array;
|
||||
|
||||
// You can use slicing syntax to convert a pointer into a slice:
|
||||
const slice = ptr[0..5];
|
||||
@ -4893,10 +4893,10 @@ pub const TypeId = enum {
|
||||
Pointer,
|
||||
Array,
|
||||
Struct,
|
||||
FloatLiteral,
|
||||
IntLiteral,
|
||||
UndefinedLiteral,
|
||||
NullLiteral,
|
||||
ComptimeFloat,
|
||||
ComptimeInt,
|
||||
Undefined,
|
||||
Null,
|
||||
Nullable,
|
||||
ErrorUnion,
|
||||
Error,
|
||||
@ -4927,10 +4927,10 @@ pub const TypeInfo = union(TypeId) {
|
||||
Pointer: Pointer,
|
||||
Array: Array,
|
||||
Struct: Struct,
|
||||
FloatLiteral: void,
|
||||
IntLiteral: void,
|
||||
UndefinedLiteral: void,
|
||||
NullLiteral: void,
|
||||
ComptimeFloat: void,
|
||||
ComptimeInt: void,
|
||||
Undefined: void,
|
||||
Null: void,
|
||||
Nullable: Nullable,
|
||||
ErrorUnion: ErrorUnion,
|
||||
ErrorSet: ErrorSet,
|
||||
@ -5685,10 +5685,10 @@ pub const TypeId = enum {
|
||||
Pointer,
|
||||
Array,
|
||||
Struct,
|
||||
FloatLiteral,
|
||||
IntLiteral,
|
||||
UndefinedLiteral,
|
||||
NullLiteral,
|
||||
ComptimeFloat,
|
||||
ComptimeInt,
|
||||
Undefined,
|
||||
Null,
|
||||
Nullable,
|
||||
ErrorUnion,
|
||||
ErrorSet,
|
||||
@ -5713,10 +5713,10 @@ pub const TypeInfo = union(TypeId) {
|
||||
Pointer: Pointer,
|
||||
Array: Array,
|
||||
Struct: Struct,
|
||||
FloatLiteral: void,
|
||||
IntLiteral: void,
|
||||
UndefinedLiteral: void,
|
||||
NullLiteral: void,
|
||||
ComptimeFloat: void,
|
||||
ComptimeInt: void,
|
||||
Undefined: void,
|
||||
Null: void,
|
||||
Nullable: Nullable,
|
||||
ErrorUnion: ErrorUnion,
|
||||
ErrorSet: ErrorSet,
|
||||
@ -6004,9 +6004,12 @@ const c = @cImport({
|
||||
{#code_begin|syntax#}
|
||||
const base64 = @import("std").base64;
|
||||
|
||||
export fn decode_base_64(dest_ptr: *u8, dest_len: usize,
|
||||
source_ptr: *const u8, source_len: usize) usize
|
||||
{
|
||||
export fn decode_base_64(
|
||||
dest_ptr: [*]u8,
|
||||
dest_len: usize,
|
||||
source_ptr: [*]const u8,
|
||||
source_len: usize,
|
||||
) usize {
|
||||
const src = source_ptr[0..source_len];
|
||||
const dest = dest_ptr[0..dest_len];
|
||||
const base64_decoder = base64.standard_decoder_unsafe;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const base64 = @import("std").base64;
|
||||
|
||||
export fn decode_base_64(dest_ptr: *u8, dest_len: usize, source_ptr: *const u8, source_len: usize) usize {
|
||||
export fn decode_base_64(dest_ptr: [*]u8, dest_len: usize, source_ptr: [*]const u8, source_len: usize) usize {
|
||||
const src = source_ptr[0..source_len];
|
||||
const dest = dest_ptr[0..dest_len];
|
||||
const base64_decoder = base64.standard_decoder_unsafe;
|
||||
|
||||
@ -83,6 +83,7 @@ enum ConstParentId {
|
||||
ConstParentIdStruct,
|
||||
ConstParentIdArray,
|
||||
ConstParentIdUnion,
|
||||
ConstParentIdScalar,
|
||||
};
|
||||
|
||||
struct ConstParent {
|
||||
@ -100,6 +101,9 @@ struct ConstParent {
|
||||
struct {
|
||||
ConstExprValue *union_val;
|
||||
} p_union;
|
||||
struct {
|
||||
ConstExprValue *scalar_val;
|
||||
} p_scalar;
|
||||
} data;
|
||||
};
|
||||
|
||||
@ -578,6 +582,7 @@ enum CastOp {
|
||||
CastOpBytesToSlice,
|
||||
CastOpNumLitToConcrete,
|
||||
CastOpErrSet,
|
||||
CastOpBitCast,
|
||||
};
|
||||
|
||||
struct AstNodeFnCallExpr {
|
||||
@ -1154,10 +1159,10 @@ enum TypeTableEntryId {
|
||||
TypeTableEntryIdPointer,
|
||||
TypeTableEntryIdArray,
|
||||
TypeTableEntryIdStruct,
|
||||
TypeTableEntryIdNumLitFloat,
|
||||
TypeTableEntryIdNumLitInt,
|
||||
TypeTableEntryIdUndefLit,
|
||||
TypeTableEntryIdNullLit,
|
||||
TypeTableEntryIdComptimeFloat,
|
||||
TypeTableEntryIdComptimeInt,
|
||||
TypeTableEntryIdUndefined,
|
||||
TypeTableEntryIdNull,
|
||||
TypeTableEntryIdMaybe,
|
||||
TypeTableEntryIdErrorUnion,
|
||||
TypeTableEntryIdErrorSet,
|
||||
|
||||
202
src/analyze.cpp
202
src/analyze.cpp
@ -232,10 +232,10 @@ bool type_is_complete(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
@ -268,10 +268,10 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
@ -1333,10 +1333,10 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdNamespace:
|
||||
@ -1374,10 +1374,10 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdNamespace:
|
||||
@ -1511,15 +1511,15 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
case TypeTableEntryIdInvalid:
|
||||
return g->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
add_node_error(g, param_node->data.param_decl.type,
|
||||
buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -1599,16 +1599,16 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
|
||||
case TypeTableEntryIdInvalid:
|
||||
zig_unreachable();
|
||||
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
add_node_error(g, fn_proto->return_type,
|
||||
buf_sprintf("return type '%s' not allowed", buf_ptr(&fn_type_id.return_type->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -1860,7 +1860,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
|
||||
}
|
||||
|
||||
assert(!struct_type->data.structure.zero_bits_loop_flag);
|
||||
assert(struct_type->data.structure.fields);
|
||||
assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0);
|
||||
assert(decl_node->type == NodeTypeContainerDecl);
|
||||
|
||||
size_t field_count = struct_type->data.structure.src_field_count;
|
||||
@ -2677,8 +2677,8 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
|
||||
return;
|
||||
}
|
||||
tag_type = enum_type;
|
||||
abi_alignment_so_far = get_abi_alignment(g, enum_type); // this populates src_field_count
|
||||
covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count);
|
||||
abi_alignment_so_far = get_abi_alignment(g, enum_type);
|
||||
} else {
|
||||
tag_type = nullptr;
|
||||
abi_alignment_so_far = 0;
|
||||
@ -3337,16 +3337,16 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
|
||||
case TypeTableEntryIdInvalid:
|
||||
return g->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdOpaque:
|
||||
add_node_error(g, source_node, buf_sprintf("variable of type '%s' not allowed",
|
||||
buf_ptr(&type_entry->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdVoid:
|
||||
@ -3480,12 +3480,12 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
|
||||
add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
|
||||
implicit_type = g->builtin_types.entry_invalid;
|
||||
} else if ((!is_const || linkage == VarLinkageExternal) &&
|
||||
(implicit_type->id == TypeTableEntryIdNumLitFloat ||
|
||||
implicit_type->id == TypeTableEntryIdNumLitInt))
|
||||
(implicit_type->id == TypeTableEntryIdComptimeFloat ||
|
||||
implicit_type->id == TypeTableEntryIdComptimeInt))
|
||||
{
|
||||
add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
|
||||
implicit_type = g->builtin_types.entry_invalid;
|
||||
} else if (implicit_type->id == TypeTableEntryIdNullLit) {
|
||||
} else if (implicit_type->id == TypeTableEntryIdNull) {
|
||||
add_node_error(g, source_node, buf_sprintf("unable to infer variable type"));
|
||||
implicit_type = g->builtin_types.entry_invalid;
|
||||
} else if (implicit_type->id == TypeTableEntryIdMetaType && !is_const) {
|
||||
@ -3730,10 +3730,10 @@ static bool is_container(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
@ -3779,10 +3779,10 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
@ -4283,10 +4283,10 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -4568,7 +4568,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||
case TypeTableEntryIdVoid:
|
||||
return (uint32_t)4149439618;
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
{
|
||||
uint32_t result = 1331471175;
|
||||
for (size_t i = 0; i < const_val->data.x_bigint.digit_count; i += 1) {
|
||||
@ -4609,7 +4609,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
{
|
||||
float128_t f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
|
||||
uint32_t ints[4];
|
||||
@ -4672,9 +4672,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||
case TypeTableEntryIdPromise:
|
||||
// TODO better hashing algorithm
|
||||
return 223048345;
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdUndefined:
|
||||
return 162837799;
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdNull:
|
||||
return 844854567;
|
||||
case TypeTableEntryIdArray:
|
||||
// TODO better hashing algorithm
|
||||
@ -4754,10 +4754,10 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdFn:
|
||||
@ -4819,10 +4819,10 @@ static bool return_type_is_cacheable(TypeTableEntry *return_type) {
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdFn:
|
||||
@ -4930,10 +4930,10 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdOpaque:
|
||||
zig_unreachable();
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
@ -5070,7 +5070,7 @@ ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {
|
||||
void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value) {
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->type = type;
|
||||
if (type->id == TypeTableEntryIdNumLitFloat) {
|
||||
if (type->id == TypeTableEntryIdComptimeFloat) {
|
||||
bigfloat_init_64(&const_val->data.x_bigfloat, value);
|
||||
} else if (type->id == TypeTableEntryIdFloat) {
|
||||
switch (type->data.floating.bit_count) {
|
||||
@ -5158,7 +5158,8 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
|
||||
const_val->type = get_slice_type(g, ptr_type);
|
||||
const_val->data.x_struct.fields = create_const_vals(2);
|
||||
|
||||
init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const);
|
||||
init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const,
|
||||
PtrLenUnknown);
|
||||
init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len);
|
||||
}
|
||||
|
||||
@ -5169,21 +5170,24 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
|
||||
}
|
||||
|
||||
void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
|
||||
size_t elem_index, bool is_const)
|
||||
size_t elem_index, bool is_const, PtrLen ptr_len)
|
||||
{
|
||||
assert(array_val->type->id == TypeTableEntryIdArray);
|
||||
TypeTableEntry *child_type = array_val->type->data.array.child_type;
|
||||
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->type = get_pointer_to_type(g, child_type, is_const);
|
||||
const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,
|
||||
ptr_len, get_abi_alignment(g, child_type), 0, 0);
|
||||
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
|
||||
const_val->data.x_ptr.data.base_array.array_val = array_val;
|
||||
const_val->data.x_ptr.data.base_array.elem_index = elem_index;
|
||||
}
|
||||
|
||||
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const) {
|
||||
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const,
|
||||
PtrLen ptr_len)
|
||||
{
|
||||
ConstExprValue *const_val = create_const_vals(1);
|
||||
init_const_ptr_array(g, const_val, array_val, elem_index, is_const);
|
||||
init_const_ptr_array(g, const_val, array_val, elem_index, is_const, ptr_len);
|
||||
return const_val;
|
||||
}
|
||||
|
||||
@ -5346,10 +5350,10 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
return bigint_cmp(&a->data.x_bigint, &b->data.x_bigint) == CmpEQ;
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdFn:
|
||||
@ -5406,9 +5410,9 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdUndefined:
|
||||
zig_panic("TODO");
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdNull:
|
||||
zig_panic("TODO");
|
||||
case TypeTableEntryIdMaybe:
|
||||
if (a->data.x_maybe == nullptr || b->data.x_maybe == nullptr) {
|
||||
@ -5510,7 +5514,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
case TypeTableEntryIdVoid:
|
||||
buf_appendf(buf, "{}");
|
||||
return;
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
bigfloat_append_buf(buf, &const_val->data.x_bigfloat);
|
||||
return;
|
||||
case TypeTableEntryIdFloat:
|
||||
@ -5538,7 +5542,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdInt:
|
||||
bigint_append_buf(buf, &const_val->data.x_bigint, 10);
|
||||
return;
|
||||
@ -5642,12 +5646,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
buf_appendf(buf, "}");
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdNull:
|
||||
{
|
||||
buf_appendf(buf, "null");
|
||||
return;
|
||||
}
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdUndefined:
|
||||
{
|
||||
buf_appendf(buf, "undefined");
|
||||
return;
|
||||
@ -5757,10 +5761,10 @@ uint32_t type_id_hash(TypeId x) {
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdEnum:
|
||||
@ -5803,10 +5807,10 @@ bool type_id_eql(TypeId a, TypeId b) {
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdStruct:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdMaybe:
|
||||
case TypeTableEntryIdPromise:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
@ -5925,10 +5929,10 @@ static const TypeTableEntryId all_type_ids[] = {
|
||||
TypeTableEntryIdPointer,
|
||||
TypeTableEntryIdArray,
|
||||
TypeTableEntryIdStruct,
|
||||
TypeTableEntryIdNumLitFloat,
|
||||
TypeTableEntryIdNumLitInt,
|
||||
TypeTableEntryIdUndefLit,
|
||||
TypeTableEntryIdNullLit,
|
||||
TypeTableEntryIdComptimeFloat,
|
||||
TypeTableEntryIdComptimeInt,
|
||||
TypeTableEntryIdUndefined,
|
||||
TypeTableEntryIdNull,
|
||||
TypeTableEntryIdMaybe,
|
||||
TypeTableEntryIdErrorUnion,
|
||||
TypeTableEntryIdErrorSet,
|
||||
@ -5976,13 +5980,13 @@ size_t type_id_index(TypeTableEntry *entry) {
|
||||
if (entry->data.structure.is_slice)
|
||||
return 25;
|
||||
return 8;
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
return 9;
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
return 10;
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdUndefined:
|
||||
return 11;
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdNull:
|
||||
return 12;
|
||||
case TypeTableEntryIdMaybe:
|
||||
return 13;
|
||||
@ -6034,14 +6038,14 @@ const char *type_id_name(TypeTableEntryId id) {
|
||||
return "Array";
|
||||
case TypeTableEntryIdStruct:
|
||||
return "Struct";
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
return "FloatLiteral";
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
return "IntLiteral";
|
||||
case TypeTableEntryIdUndefLit:
|
||||
return "UndefinedLiteral";
|
||||
case TypeTableEntryIdNullLit:
|
||||
return "NullLiteral";
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
return "ComptimeFloat";
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
return "ComptimeInt";
|
||||
case TypeTableEntryIdUndefined:
|
||||
return "Undefined";
|
||||
case TypeTableEntryIdNull:
|
||||
return "Null";
|
||||
case TypeTableEntryIdMaybe:
|
||||
return "Nullable";
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
|
||||
@ -152,8 +152,9 @@ ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *poi
|
||||
size_t addr, bool is_const);
|
||||
|
||||
void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
|
||||
size_t elem_index, bool is_const);
|
||||
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const);
|
||||
size_t elem_index, bool is_const, PtrLen ptr_len);
|
||||
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index,
|
||||
bool is_const, PtrLen ptr_len);
|
||||
|
||||
void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
|
||||
size_t start, size_t len, bool is_const);
|
||||
|
||||
@ -2541,6 +2541,8 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
add_error_range_check(g, wanted_type, g->err_tag_type, expr_val);
|
||||
}
|
||||
return expr_val;
|
||||
case CastOpBitCast:
|
||||
return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -2823,7 +2825,13 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
|
||||
bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on;
|
||||
|
||||
if (array_type->id == TypeTableEntryIdArray) {
|
||||
if (array_type->id == TypeTableEntryIdArray ||
|
||||
(array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
|
||||
{
|
||||
if (array_type->id == TypeTableEntryIdPointer) {
|
||||
assert(array_type->data.pointer.child_type->id == TypeTableEntryIdArray);
|
||||
array_type = array_type->data.pointer.child_type;
|
||||
}
|
||||
if (safety_check_on) {
|
||||
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
|
||||
array_type->data.array.len, false);
|
||||
@ -3709,7 +3717,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
|
||||
|
||||
bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
|
||||
|
||||
if (array_type->id == TypeTableEntryIdArray) {
|
||||
if (array_type->id == TypeTableEntryIdArray ||
|
||||
(array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
|
||||
{
|
||||
if (array_type->id == TypeTableEntryIdPointer) {
|
||||
array_type = array_type->data.pointer.child_type;
|
||||
}
|
||||
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
|
||||
LLVMValueRef end_val;
|
||||
if (instruction->end) {
|
||||
@ -3750,6 +3763,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
|
||||
|
||||
return tmp_struct_ptr;
|
||||
} else if (array_type->id == TypeTableEntryIdPointer) {
|
||||
assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
|
||||
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
|
||||
LLVMValueRef end_val = ir_llvm_value(g, instruction->end);
|
||||
|
||||
@ -4727,7 +4741,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
|
||||
|
||||
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
|
||||
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
|
||||
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *array_const_val);
|
||||
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
|
||||
|
||||
static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
|
||||
switch (parent->id) {
|
||||
@ -4743,6 +4757,10 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
|
||||
parent->data.p_array.elem_index);
|
||||
case ConstParentIdUnion:
|
||||
return gen_const_ptr_union_recursive(g, parent->data.p_union.union_val);
|
||||
case ConstParentIdScalar:
|
||||
render_const_val(g, parent->data.p_scalar.scalar_val, "");
|
||||
render_const_val_global(g, parent->data.p_scalar.scalar_val, "");
|
||||
return parent->data.p_scalar.scalar_val->global_refs->llvm_global;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -4768,7 +4786,8 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
|
||||
};
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
} else {
|
||||
zig_unreachable();
|
||||
assert(parent->id == ConstParentIdScalar);
|
||||
return base_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4812,10 +4831,10 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdNamespace:
|
||||
@ -5258,10 +5277,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdUnreachable:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -5500,7 +5519,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
TldVar *tld_var = g->global_vars.at(i);
|
||||
VariableTableEntry *var = tld_var->var;
|
||||
|
||||
if (var->value->type->id == TypeTableEntryIdNumLitFloat) {
|
||||
if (var->value->type->id == TypeTableEntryIdComptimeFloat) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = var->value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
@ -5514,7 +5533,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var->value->type->id == TypeTableEntryIdNumLitInt) {
|
||||
if (var->value->type->id == TypeTableEntryIdComptimeInt) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = var->value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
@ -5908,25 +5927,27 @@ static void define_builtin_types(CodeGen *g) {
|
||||
g->builtin_types.entry_block = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
|
||||
buf_init_from_str(&entry->name, "(float literal)");
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdComptimeFloat);
|
||||
buf_init_from_str(&entry->name, "comptime_float");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_num_lit_float = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitInt);
|
||||
buf_init_from_str(&entry->name, "(integer literal)");
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdComptimeInt);
|
||||
buf_init_from_str(&entry->name, "comptime_int");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_num_lit_int = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefLit);
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefined);
|
||||
buf_init_from_str(&entry->name, "(undefined)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_undef = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNullLit);
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNull);
|
||||
buf_init_from_str(&entry->name, "(null)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_null = entry;
|
||||
@ -6391,10 +6412,10 @@ static void define_builtin_compile_vars(CodeGen *g) {
|
||||
" Slice: Slice,\n"
|
||||
" Array: Array,\n"
|
||||
" Struct: Struct,\n"
|
||||
" FloatLiteral: void,\n"
|
||||
" IntLiteral: void,\n"
|
||||
" UndefinedLiteral: void,\n"
|
||||
" NullLiteral: void,\n"
|
||||
" ComptimeFloat: void,\n"
|
||||
" ComptimeInt: void,\n"
|
||||
" Undefined: void,\n"
|
||||
" Null: void,\n"
|
||||
" Nullable: Nullable,\n"
|
||||
" ErrorUnion: ErrorUnion,\n"
|
||||
" ErrorSet: ErrorSet,\n"
|
||||
@ -6966,10 +6987,10 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry
|
||||
switch (type_entry->id) {
|
||||
case TypeTableEntryIdInvalid:
|
||||
case TypeTableEntryIdMetaType:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdBoundFn:
|
||||
@ -7151,10 +7172,10 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
|
||||
case TypeTableEntryIdBoundFn:
|
||||
case TypeTableEntryIdNamespace:
|
||||
case TypeTableEntryIdBlock:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdArgTuple:
|
||||
case TypeTableEntryIdPromise:
|
||||
zig_unreachable();
|
||||
@ -7303,11 +7324,11 @@ static void gen_h_file(CodeGen *g) {
|
||||
case TypeTableEntryIdInt:
|
||||
case TypeTableEntryIdFloat:
|
||||
case TypeTableEntryIdPointer:
|
||||
case TypeTableEntryIdNumLitFloat:
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdComptimeFloat:
|
||||
case TypeTableEntryIdComptimeInt:
|
||||
case TypeTableEntryIdArray:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdNullLit:
|
||||
case TypeTableEntryIdUndefined:
|
||||
case TypeTableEntryIdNull:
|
||||
case TypeTableEntryIdErrorUnion:
|
||||
case TypeTableEntryIdErrorSet:
|
||||
case TypeTableEntryIdNamespace:
|
||||
|
||||
497
src/ir.cpp
497
src/ir.cpp
File diff suppressed because it is too large
Load Diff
19
src/util.hpp
19
src/util.hpp
@ -65,6 +65,11 @@ static inline int clzll(unsigned long long mask) {
|
||||
|
||||
template<typename T>
|
||||
ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
|
||||
#ifndef NDEBUG
|
||||
// make behavior when size == 0 portable
|
||||
if (count == 0)
|
||||
return nullptr;
|
||||
#endif
|
||||
T *ptr = reinterpret_cast<T*>(malloc(count * sizeof(T)));
|
||||
if (!ptr)
|
||||
zig_panic("allocation failed");
|
||||
@ -73,6 +78,11 @@ ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
|
||||
|
||||
template<typename T>
|
||||
ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) {
|
||||
#ifndef NDEBUG
|
||||
// make behavior when size == 0 portable
|
||||
if (count == 0)
|
||||
return nullptr;
|
||||
#endif
|
||||
T *ptr = reinterpret_cast<T*>(calloc(count, sizeof(T)));
|
||||
if (!ptr)
|
||||
zig_panic("allocation failed");
|
||||
@ -93,9 +103,7 @@ static inline void safe_memcpy(T *dest, const T *src, size_t count) {
|
||||
|
||||
template<typename T>
|
||||
static inline T *reallocate(T *old, size_t old_count, size_t new_count) {
|
||||
T *ptr = reinterpret_cast<T*>(realloc(old, new_count * sizeof(T)));
|
||||
if (!ptr)
|
||||
zig_panic("allocation failed");
|
||||
T *ptr = reallocate_nonzero(old, old_count, new_count);
|
||||
if (new_count > old_count) {
|
||||
memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T));
|
||||
}
|
||||
@ -104,6 +112,11 @@ static inline T *reallocate(T *old, size_t old_count, size_t new_count) {
|
||||
|
||||
template<typename T>
|
||||
static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count) {
|
||||
#ifndef NDEBUG
|
||||
// make behavior when size == 0 portable
|
||||
if (new_count == 0 && old == nullptr)
|
||||
return nullptr;
|
||||
#endif
|
||||
T *ptr = reinterpret_cast<T*>(realloc(old, new_count * sizeof(T)));
|
||||
if (!ptr)
|
||||
zig_panic("allocation failed");
|
||||
|
||||
@ -59,7 +59,7 @@ pub fn roundToPrecision(float_decimal: *FloatDecimal, precision: usize, mode: Ro
|
||||
float_decimal.exp += 1;
|
||||
|
||||
// Re-size the buffer to use the reserved leading byte.
|
||||
const one_before = @intToPtr(*u8, @ptrToInt(&float_decimal.digits[0]) - 1);
|
||||
const one_before = @intToPtr([*]u8, @ptrToInt(&float_decimal.digits[0]) - 1);
|
||||
float_decimal.digits = one_before[0 .. float_decimal.digits.len + 1];
|
||||
float_decimal.digits[0] = '1';
|
||||
return;
|
||||
|
||||
@ -16,27 +16,12 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
|
||||
Start,
|
||||
OpenBrace,
|
||||
CloseBrace,
|
||||
Integer,
|
||||
IntegerWidth,
|
||||
Float,
|
||||
FloatWidth,
|
||||
FloatScientific,
|
||||
FloatScientificWidth,
|
||||
Character,
|
||||
Buf,
|
||||
BufWidth,
|
||||
Bytes,
|
||||
BytesBase,
|
||||
BytesWidth,
|
||||
FormatString,
|
||||
};
|
||||
|
||||
comptime var start_index = 0;
|
||||
comptime var state = State.Start;
|
||||
comptime var next_arg = 0;
|
||||
comptime var radix = 0;
|
||||
comptime var uppercase = false;
|
||||
comptime var width = 0;
|
||||
comptime var width_start = 0;
|
||||
|
||||
inline for (fmt) |c, i| {
|
||||
switch (state) {
|
||||
@ -45,8 +30,10 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
|
||||
if (start_index < i) {
|
||||
try output(context, fmt[start_index..i]);
|
||||
}
|
||||
start_index = i;
|
||||
state = State.OpenBrace;
|
||||
},
|
||||
|
||||
'}' => {
|
||||
if (start_index < i) {
|
||||
try output(context, fmt[start_index..i]);
|
||||
@ -61,57 +48,14 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
|
||||
start_index = i;
|
||||
},
|
||||
'}' => {
|
||||
try formatValue(args[next_arg], context, Errors, output);
|
||||
try formatType(args[next_arg], fmt[0..0], context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'd' => {
|
||||
radix = 10;
|
||||
uppercase = false;
|
||||
width = 0;
|
||||
state = State.Integer;
|
||||
else => {
|
||||
state = State.FormatString;
|
||||
},
|
||||
'x' => {
|
||||
radix = 16;
|
||||
uppercase = false;
|
||||
width = 0;
|
||||
state = State.Integer;
|
||||
},
|
||||
'X' => {
|
||||
radix = 16;
|
||||
uppercase = true;
|
||||
width = 0;
|
||||
state = State.Integer;
|
||||
},
|
||||
'c' => {
|
||||
state = State.Character;
|
||||
},
|
||||
's' => {
|
||||
state = State.Buf;
|
||||
},
|
||||
'e' => {
|
||||
state = State.FloatScientific;
|
||||
},
|
||||
'.' => {
|
||||
state = State.Float;
|
||||
},
|
||||
'B' => {
|
||||
width = 0;
|
||||
radix = 1000;
|
||||
state = State.Bytes;
|
||||
},
|
||||
else => @compileError("Unknown format character: " ++ []u8{c}),
|
||||
},
|
||||
State.Buf => switch (c) {
|
||||
'}' => {
|
||||
return output(context, args[next_arg]);
|
||||
},
|
||||
'0'...'9' => {
|
||||
width_start = i;
|
||||
state = State.BufWidth;
|
||||
},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.CloseBrace => switch (c) {
|
||||
'}' => {
|
||||
@ -120,138 +64,15 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
|
||||
},
|
||||
else => @compileError("Single '}' encountered in format string"),
|
||||
},
|
||||
State.Integer => switch (c) {
|
||||
State.FormatString => switch (c) {
|
||||
'}' => {
|
||||
try formatInt(args[next_arg], radix, uppercase, width, context, Errors, output);
|
||||
const s = start_index + 1;
|
||||
try formatType(args[next_arg], fmt[s..i], context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {
|
||||
width_start = i;
|
||||
state = State.IntegerWidth;
|
||||
},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.IntegerWidth => switch (c) {
|
||||
'}' => {
|
||||
width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
|
||||
try formatInt(args[next_arg], radix, uppercase, width, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.FloatScientific => switch (c) {
|
||||
'}' => {
|
||||
try formatFloatScientific(args[next_arg], null, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {
|
||||
width_start = i;
|
||||
state = State.FloatScientificWidth;
|
||||
},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.FloatScientificWidth => switch (c) {
|
||||
'}' => {
|
||||
width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
|
||||
try formatFloatScientific(args[next_arg], width, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.Float => switch (c) {
|
||||
'}' => {
|
||||
try formatFloatDecimal(args[next_arg], null, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {
|
||||
width_start = i;
|
||||
state = State.FloatWidth;
|
||||
},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.FloatWidth => switch (c) {
|
||||
'}' => {
|
||||
width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
|
||||
try formatFloatDecimal(args[next_arg], width, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.BufWidth => switch (c) {
|
||||
'}' => {
|
||||
width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
|
||||
try formatBuf(args[next_arg], width, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.Character => switch (c) {
|
||||
'}' => {
|
||||
try formatAsciiChar(args[next_arg], context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.Bytes => switch (c) {
|
||||
'}' => {
|
||||
try formatBytes(args[next_arg], 0, radix, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'i' => {
|
||||
radix = 1024;
|
||||
state = State.BytesBase;
|
||||
},
|
||||
'0'...'9' => {
|
||||
width_start = i;
|
||||
state = State.BytesWidth;
|
||||
},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.BytesBase => switch (c) {
|
||||
'}' => {
|
||||
try formatBytes(args[next_arg], 0, radix, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {
|
||||
width_start = i;
|
||||
state = State.BytesWidth;
|
||||
},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
},
|
||||
State.BytesWidth => switch (c) {
|
||||
'}' => {
|
||||
width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
|
||||
try formatBytes(args[next_arg], width, radix, context, Errors, output);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'0'...'9' => {},
|
||||
else => @compileError("Unexpected character in format string: " ++ []u8{c}),
|
||||
else => {},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -268,14 +89,17 @@ pub fn format(context: var, comptime Errors: type, output: fn (@typeOf(context),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
|
||||
pub fn formatType(
|
||||
value: var,
|
||||
comptime fmt: []const u8,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
const T = @typeOf(value);
|
||||
switch (@typeId(T)) {
|
||||
builtin.TypeId.Int => {
|
||||
return formatInt(value, 10, false, 0, context, Errors, output);
|
||||
},
|
||||
builtin.TypeId.Float => {
|
||||
return formatFloatScientific(value, null, context, Errors, output);
|
||||
builtin.TypeId.Int, builtin.TypeId.Float => {
|
||||
return formatValue(value, fmt, context, Errors, output);
|
||||
},
|
||||
builtin.TypeId.Void => {
|
||||
return output(context, "void");
|
||||
@ -285,16 +109,16 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
|
||||
},
|
||||
builtin.TypeId.Nullable => {
|
||||
if (value) |payload| {
|
||||
return formatValue(payload, context, Errors, output);
|
||||
return formatType(payload, fmt, context, Errors, output);
|
||||
} else {
|
||||
return output(context, "null");
|
||||
}
|
||||
},
|
||||
builtin.TypeId.ErrorUnion => {
|
||||
if (value) |payload| {
|
||||
return formatValue(payload, context, Errors, output);
|
||||
return formatType(payload, fmt, context, Errors, output);
|
||||
} else |err| {
|
||||
return formatValue(err, context, Errors, output);
|
||||
return formatType(err, fmt, context, Errors, output);
|
||||
}
|
||||
},
|
||||
builtin.TypeId.ErrorSet => {
|
||||
@ -302,10 +126,34 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
|
||||
return output(context, @errorName(value));
|
||||
},
|
||||
builtin.TypeId.Pointer => {
|
||||
if (@typeId(T.Child) == builtin.TypeId.Array and T.Child.Child == u8) {
|
||||
return output(context, (value.*)[0..]);
|
||||
} else {
|
||||
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
|
||||
switch (@typeId(T.Child)) {
|
||||
builtin.TypeId.Array => {
|
||||
if (T.Child.Child == u8) {
|
||||
return formatText(value, fmt, context, Errors, output);
|
||||
}
|
||||
},
|
||||
builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
|
||||
const has_cust_fmt = comptime cf: {
|
||||
const info = @typeInfo(T.Child);
|
||||
const defs = switch (info) {
|
||||
builtin.TypeId.Struct => |s| s.defs,
|
||||
builtin.TypeId.Union => |u| u.defs,
|
||||
builtin.TypeId.Enum => |e| e.defs,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
for (defs) |def| {
|
||||
if (mem.eql(u8, def.name, "format")) {
|
||||
break :cf true;
|
||||
}
|
||||
}
|
||||
break :cf false;
|
||||
};
|
||||
|
||||
if (has_cust_fmt) return value.format(fmt, context, Errors, output);
|
||||
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
|
||||
},
|
||||
else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)),
|
||||
}
|
||||
},
|
||||
else => if (@canImplicitCast([]const u8, value)) {
|
||||
@ -317,11 +165,129 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn (
|
||||
}
|
||||
}
|
||||
|
||||
pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
|
||||
return output(context, (&c)[0..1]);
|
||||
fn formatValue(
|
||||
value: var,
|
||||
comptime fmt: []const u8,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
if (fmt.len > 0) {
|
||||
if (fmt[0] == 'B') {
|
||||
comptime var width: ?usize = null;
|
||||
if (fmt.len > 1) {
|
||||
if (fmt[1] == 'i') {
|
||||
if (fmt.len > 2) width = comptime (parseUnsigned(usize, fmt[2..], 10) catch unreachable);
|
||||
return formatBytes(value, width, 1024, context, Errors, output);
|
||||
}
|
||||
width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
|
||||
}
|
||||
return formatBytes(value, width, 1000, context, Errors, output);
|
||||
}
|
||||
}
|
||||
|
||||
comptime var T = @typeOf(value);
|
||||
switch (@typeId(T)) {
|
||||
builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
|
||||
builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
|
||||
pub fn formatIntValue(
|
||||
value: var,
|
||||
comptime fmt: []const u8,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
comptime var radix = 10;
|
||||
comptime var uppercase = false;
|
||||
comptime var width = 0;
|
||||
if (fmt.len > 0) {
|
||||
switch (fmt[0]) {
|
||||
'c' => {
|
||||
if (@typeOf(value) == u8) {
|
||||
if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});
|
||||
return formatAsciiChar(value, context, Errors, output);
|
||||
}
|
||||
},
|
||||
'd' => {
|
||||
radix = 10;
|
||||
uppercase = false;
|
||||
width = 0;
|
||||
},
|
||||
'x' => {
|
||||
radix = 16;
|
||||
uppercase = false;
|
||||
width = 0;
|
||||
},
|
||||
'X' => {
|
||||
radix = 16;
|
||||
uppercase = true;
|
||||
width = 0;
|
||||
},
|
||||
else => @compileError("Unknown format character: " ++ []u8{fmt[0]}),
|
||||
}
|
||||
if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
|
||||
}
|
||||
return formatInt(value, radix, uppercase, width, context, Errors, output);
|
||||
}
|
||||
|
||||
fn formatFloatValue(
|
||||
value: var,
|
||||
comptime fmt: []const u8,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
comptime var width: ?usize = null;
|
||||
comptime var float_fmt = 'e';
|
||||
if (fmt.len > 0) {
|
||||
float_fmt = fmt[0];
|
||||
if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
|
||||
}
|
||||
|
||||
switch (float_fmt) {
|
||||
'e' => try formatFloatScientific(value, width, context, Errors, output),
|
||||
'.' => try formatFloatDecimal(value, width, context, Errors, output),
|
||||
else => @compileError("Unknown format character: " ++ []u8{float_fmt}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn formatText(
|
||||
bytes: []const u8,
|
||||
comptime fmt: []const u8,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
if (fmt.len > 0) {
|
||||
if (fmt[0] == 's') {
|
||||
comptime var width = 0;
|
||||
if (fmt.len > 1) width = comptime (parseUnsigned(usize, fmt[1..], 10) catch unreachable);
|
||||
return formatBuf(bytes, width, context, Errors, output);
|
||||
} else @compileError("Unknown format character: " ++ []u8{fmt[0]});
|
||||
}
|
||||
return output(context, bytes);
|
||||
}
|
||||
|
||||
pub fn formatAsciiChar(
|
||||
c: u8,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
return output(context, (*[1]u8)(&c)[0..]);
|
||||
}
|
||||
|
||||
pub fn formatBuf(
|
||||
buf: []const u8,
|
||||
width: usize,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
try output(context, buf);
|
||||
|
||||
var leftover_padding = if (width > buf.len) (width - buf.len) else return;
|
||||
@ -334,7 +300,13 @@ pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: t
|
||||
// Print a float in scientific notation to the specified precision. Null uses full precision.
|
||||
// It should be the case that every full precision, printed value can be re-parsed back to the
|
||||
// same type unambiguously.
|
||||
pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
|
||||
pub fn formatFloatScientific(
|
||||
value: var,
|
||||
maybe_precision: ?usize,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
var x = f64(value);
|
||||
|
||||
// Errol doesn't handle these special cases.
|
||||
@ -423,7 +395,13 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var,
|
||||
|
||||
// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.
|
||||
// By default floats are printed at full precision (no rounding).
|
||||
pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
|
||||
pub fn formatFloatDecimal(
|
||||
value: var,
|
||||
maybe_precision: ?usize,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
var x = f64(value);
|
||||
|
||||
// Errol doesn't handle these special cases.
|
||||
@ -613,11 +591,19 @@ pub fn formatInt(
|
||||
}
|
||||
}
|
||||
|
||||
fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
|
||||
fn formatIntSigned(
|
||||
value: var,
|
||||
base: u8,
|
||||
uppercase: bool,
|
||||
width: usize,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
const uint = @IntType(false, @typeOf(value).bit_count);
|
||||
if (value < 0) {
|
||||
const minus_sign: u8 = '-';
|
||||
try output(context, (&minus_sign)[0..1]);
|
||||
try output(context, (*[1]u8)(&minus_sign)[0..]);
|
||||
const new_value = uint(-(value + 1)) + 1;
|
||||
const new_width = if (width == 0) 0 else (width - 1);
|
||||
return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output);
|
||||
@ -625,14 +611,22 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context:
|
||||
return formatIntUnsigned(uint(value), base, uppercase, width, context, Errors, output);
|
||||
} else {
|
||||
const plus_sign: u8 = '+';
|
||||
try output(context, (&plus_sign)[0..1]);
|
||||
try output(context, (*[1]u8)(&plus_sign)[0..]);
|
||||
const new_value = uint(value);
|
||||
const new_width = if (width == 0) 0 else (width - 1);
|
||||
return formatIntUnsigned(new_value, base, uppercase, new_width, context, Errors, output);
|
||||
}
|
||||
}
|
||||
|
||||
fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void) Errors!void {
|
||||
fn formatIntUnsigned(
|
||||
value: var,
|
||||
base: u8,
|
||||
uppercase: bool,
|
||||
width: usize,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
// max_int_digits accounts for the minus sign. when printing an unsigned
|
||||
// number we don't need to do that.
|
||||
var buf: [max_int_digits - 1]u8 = undefined;
|
||||
@ -654,7 +648,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, contex
|
||||
const zero_byte: u8 = '0';
|
||||
var leftover_padding = padding - index;
|
||||
while (true) {
|
||||
try output(context, (&zero_byte)[0..1]);
|
||||
try output(context, (*[1]u8)(&zero_byte)[0..]);
|
||||
leftover_padding -= 1;
|
||||
if (leftover_padding == 0) break;
|
||||
}
|
||||
@ -831,6 +825,10 @@ test "fmt.format" {
|
||||
const value: u3 = 0b101;
|
||||
try testFmt("u3: 5\n", "u3: {}\n", value);
|
||||
}
|
||||
{
|
||||
const value: u8 = 'a';
|
||||
try testFmt("u8: a\n", "u8: {c}\n", value);
|
||||
}
|
||||
try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));
|
||||
try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));
|
||||
{
|
||||
@ -1048,6 +1046,42 @@ test "fmt.format" {
|
||||
const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
|
||||
assert(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));
|
||||
}
|
||||
//custom type format
|
||||
{
|
||||
const Vec2 = struct {
|
||||
const SelfType = this;
|
||||
x: f32,
|
||||
y: f32,
|
||||
|
||||
pub fn format(
|
||||
self: *SelfType,
|
||||
comptime fmt: []const u8,
|
||||
context: var,
|
||||
comptime Errors: type,
|
||||
output: fn (@typeOf(context), []const u8) Errors!void,
|
||||
) Errors!void {
|
||||
if (fmt.len > 0) {
|
||||
if (fmt.len > 1) unreachable;
|
||||
switch (fmt[0]) {
|
||||
//point format
|
||||
'p' => return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y),
|
||||
//dimension format
|
||||
'd' => return std.fmt.format(context, Errors, output, "{.3}x{.3}", self.x, self.y),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
return std.fmt.format(context, Errors, output, "({.3},{.3})", self.x, self.y);
|
||||
}
|
||||
};
|
||||
|
||||
var buf1: [32]u8 = undefined;
|
||||
var value = Vec2{
|
||||
.x = 10.2,
|
||||
.y = 2.22,
|
||||
};
|
||||
try testFmt("point: (10.200,2.220)\n", "point: {}\n", &value);
|
||||
try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", &value);
|
||||
}
|
||||
}
|
||||
|
||||
fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {
|
||||
|
||||
@ -24,7 +24,7 @@ fn cAlloc(self: *Allocator, n: usize, alignment: u29) ![]u8 {
|
||||
fn cRealloc(self: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
|
||||
const old_ptr = @ptrCast([*]c_void, old_mem.ptr);
|
||||
if (c.realloc(old_ptr, new_size)) |buf| {
|
||||
return @ptrCast(*u8, buf)[0..new_size];
|
||||
return @ptrCast([*]u8, buf)[0..new_size];
|
||||
} else if (new_size <= old_mem.len) {
|
||||
return old_mem[0..new_size];
|
||||
} else {
|
||||
|
||||
@ -219,12 +219,12 @@ pub fn OutStream(comptime WriteError: type) type {
|
||||
}
|
||||
|
||||
pub fn writeByte(self: *Self, byte: u8) !void {
|
||||
const slice = (&byte)[0..1];
|
||||
const slice = (*[1]u8)(&byte)[0..];
|
||||
return self.writeFn(self, slice);
|
||||
}
|
||||
|
||||
pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) !void {
|
||||
const slice = (&byte)[0..1];
|
||||
const slice = (*[1]u8)(&byte)[0..];
|
||||
var i: usize = 0;
|
||||
while (i < n) : (i += 1) {
|
||||
try self.writeFn(self, slice);
|
||||
|
||||
@ -164,7 +164,7 @@ fn readNoEof(in: *io.FileInStream, comptime T: type, result: []T) !void {
|
||||
return in.stream.readNoEof(([]u8)(result));
|
||||
}
|
||||
fn readOneNoEof(in: *io.FileInStream, comptime T: type, result: *T) !void {
|
||||
return readNoEof(in, T, result[0..1]);
|
||||
return readNoEof(in, T, (*[1]T)(result)[0..]);
|
||||
}
|
||||
|
||||
fn isSymbol(sym: *const Nlist64) bool {
|
||||
|
||||
@ -14,7 +14,7 @@ const TypeId = builtin.TypeId;
|
||||
pub fn ln(x: var) @typeOf(x) {
|
||||
const T = @typeOf(x);
|
||||
switch (@typeId(T)) {
|
||||
TypeId.FloatLiteral => {
|
||||
TypeId.ComptimeFloat => {
|
||||
return @typeOf(1.0)(ln_64(x));
|
||||
},
|
||||
TypeId.Float => {
|
||||
@ -24,7 +24,7 @@ pub fn ln(x: var) @typeOf(x) {
|
||||
else => @compileError("ln not implemented for " ++ @typeName(T)),
|
||||
};
|
||||
},
|
||||
TypeId.IntLiteral => {
|
||||
TypeId.ComptimeInt => {
|
||||
return @typeOf(1)(math.floor(ln_64(f64(x))));
|
||||
},
|
||||
TypeId.Int => {
|
||||
|
||||
@ -9,15 +9,15 @@ pub fn log(comptime T: type, base: T, x: T) T {
|
||||
return math.log2(x);
|
||||
} else if (base == 10) {
|
||||
return math.log10(x);
|
||||
} else if ((@typeId(T) == TypeId.Float or @typeId(T) == TypeId.FloatLiteral) and base == math.e) {
|
||||
} else if ((@typeId(T) == TypeId.Float or @typeId(T) == TypeId.ComptimeFloat) and base == math.e) {
|
||||
return math.ln(x);
|
||||
}
|
||||
|
||||
switch (@typeId(T)) {
|
||||
TypeId.FloatLiteral => {
|
||||
TypeId.ComptimeFloat => {
|
||||
return @typeOf(1.0)(math.ln(f64(x)) / math.ln(f64(base)));
|
||||
},
|
||||
TypeId.IntLiteral => {
|
||||
TypeId.ComptimeInt => {
|
||||
return @typeOf(1)(math.floor(math.ln(f64(x)) / math.ln(f64(base))));
|
||||
},
|
||||
builtin.TypeId.Int => {
|
||||
|
||||
@ -14,7 +14,7 @@ const TypeId = builtin.TypeId;
|
||||
pub fn log10(x: var) @typeOf(x) {
|
||||
const T = @typeOf(x);
|
||||
switch (@typeId(T)) {
|
||||
TypeId.FloatLiteral => {
|
||||
TypeId.ComptimeFloat => {
|
||||
return @typeOf(1.0)(log10_64(x));
|
||||
},
|
||||
TypeId.Float => {
|
||||
@ -24,7 +24,7 @@ pub fn log10(x: var) @typeOf(x) {
|
||||
else => @compileError("log10 not implemented for " ++ @typeName(T)),
|
||||
};
|
||||
},
|
||||
TypeId.IntLiteral => {
|
||||
TypeId.ComptimeInt => {
|
||||
return @typeOf(1)(math.floor(log10_64(f64(x))));
|
||||
},
|
||||
TypeId.Int => {
|
||||
|
||||
@ -14,7 +14,7 @@ const TypeId = builtin.TypeId;
|
||||
pub fn log2(x: var) @typeOf(x) {
|
||||
const T = @typeOf(x);
|
||||
switch (@typeId(T)) {
|
||||
TypeId.FloatLiteral => {
|
||||
TypeId.ComptimeFloat => {
|
||||
return @typeOf(1.0)(log2_64(x));
|
||||
},
|
||||
TypeId.Float => {
|
||||
@ -24,7 +24,7 @@ pub fn log2(x: var) @typeOf(x) {
|
||||
else => @compileError("log2 not implemented for " ++ @typeName(T)),
|
||||
};
|
||||
},
|
||||
TypeId.IntLiteral => comptime {
|
||||
TypeId.ComptimeInt => comptime {
|
||||
var result = 0;
|
||||
var x_shifted = x;
|
||||
while (b: {
|
||||
|
||||
@ -14,9 +14,9 @@ const TypeId = builtin.TypeId;
|
||||
pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {
|
||||
const T = @typeOf(x);
|
||||
switch (@typeId(T)) {
|
||||
TypeId.FloatLiteral => return T(@sqrt(f64, x)), // TODO upgrade to f128
|
||||
TypeId.ComptimeFloat => return T(@sqrt(f64, x)), // TODO upgrade to f128
|
||||
TypeId.Float => return @sqrt(T, x),
|
||||
TypeId.IntLiteral => comptime {
|
||||
TypeId.ComptimeInt => comptime {
|
||||
if (x > @maxValue(u128)) {
|
||||
@compileError("sqrt not implemented for comptime_int greater than 128 bits");
|
||||
}
|
||||
|
||||
34
std/mem.zig
34
std/mem.zig
@ -31,14 +31,16 @@ pub const Allocator = struct {
|
||||
/// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
|
||||
freeFn: fn (self: *Allocator, old_mem: []u8) void,
|
||||
|
||||
fn create(self: *Allocator, comptime T: type) !*T {
|
||||
/// Call destroy with the result
|
||||
pub fn create(self: *Allocator, comptime T: type) !*T {
|
||||
if (@sizeOf(T) == 0) return *{};
|
||||
const slice = try self.alloc(T, 1);
|
||||
return &slice[0];
|
||||
}
|
||||
|
||||
// TODO once #733 is solved, this will replace create
|
||||
fn construct(self: *Allocator, init: var) t: {
|
||||
/// Call destroy with the result
|
||||
/// TODO once #733 is solved, this will replace create
|
||||
pub fn construct(self: *Allocator, init: var) t: {
|
||||
// TODO this is a workaround for type getting parsed as Error!&const T
|
||||
const T = @typeOf(init).Child;
|
||||
break :t Error!*T;
|
||||
@ -51,17 +53,19 @@ pub const Allocator = struct {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
fn destroy(self: *Allocator, ptr: var) void {
|
||||
self.free(ptr[0..1]);
|
||||
/// `ptr` should be the return value of `construct` or `create`
|
||||
pub fn destroy(self: *Allocator, ptr: var) void {
|
||||
const non_const_ptr = @intToPtr([*]u8, @ptrToInt(ptr));
|
||||
self.freeFn(self, non_const_ptr[0..@sizeOf(@typeOf(ptr).Child)]);
|
||||
}
|
||||
|
||||
fn alloc(self: *Allocator, comptime T: type, n: usize) ![]T {
|
||||
pub fn alloc(self: *Allocator, comptime T: type, n: usize) ![]T {
|
||||
return self.alignedAlloc(T, @alignOf(T), n);
|
||||
}
|
||||
|
||||
fn alignedAlloc(self: *Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T {
|
||||
pub fn alignedAlloc(self: *Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T {
|
||||
if (n == 0) {
|
||||
return (*align(alignment) T)(undefined)[0..0];
|
||||
return ([*]align(alignment) T)(undefined)[0..0];
|
||||
}
|
||||
const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;
|
||||
const byte_slice = try self.allocFn(self, byte_count, alignment);
|
||||
@ -73,17 +77,17 @@ pub const Allocator = struct {
|
||||
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
|
||||
}
|
||||
|
||||
fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T {
|
||||
pub fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T {
|
||||
return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
|
||||
}
|
||||
|
||||
fn alignedRealloc(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T {
|
||||
pub fn alignedRealloc(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T {
|
||||
if (old_mem.len == 0) {
|
||||
return self.alloc(T, n);
|
||||
}
|
||||
if (n == 0) {
|
||||
self.free(old_mem);
|
||||
return (*align(alignment) T)(undefined)[0..0];
|
||||
return ([*]align(alignment) T)(undefined)[0..0];
|
||||
}
|
||||
|
||||
const old_byte_slice = ([]u8)(old_mem);
|
||||
@ -102,11 +106,11 @@ pub const Allocator = struct {
|
||||
/// Reallocate, but `n` must be less than or equal to `old_mem.len`.
|
||||
/// Unlike `realloc`, this function cannot fail.
|
||||
/// Shrinking to 0 is the same as calling `free`.
|
||||
fn shrink(self: *Allocator, comptime T: type, old_mem: []T, n: usize) []T {
|
||||
pub fn shrink(self: *Allocator, comptime T: type, old_mem: []T, n: usize) []T {
|
||||
return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
|
||||
}
|
||||
|
||||
fn alignedShrink(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T {
|
||||
pub fn alignedShrink(self: *Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T {
|
||||
if (n == 0) {
|
||||
self.free(old_mem);
|
||||
return old_mem[0..0];
|
||||
@ -123,10 +127,10 @@ pub const Allocator = struct {
|
||||
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
|
||||
}
|
||||
|
||||
fn free(self: *Allocator, memory: var) void {
|
||||
pub fn free(self: *Allocator, memory: var) void {
|
||||
const bytes = ([]const u8)(memory);
|
||||
if (bytes.len == 0) return;
|
||||
const non_const_ptr = @intToPtr(*u8, @ptrToInt(bytes.ptr));
|
||||
const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));
|
||||
self.freeFn(self, non_const_ptr[0..bytes.len]);
|
||||
}
|
||||
};
|
||||
|
||||
@ -68,7 +68,7 @@ pub const Address = struct {
|
||||
|
||||
pub fn parseIp4(buf: []const u8) !u32 {
|
||||
var result: u32 = undefined;
|
||||
const out_ptr = ([]u8)((&result)[0..1]);
|
||||
const out_ptr = ([]u8)((*[1]u32)(&result)[0..]);
|
||||
|
||||
var x: u8 = 0;
|
||||
var index: u8 = 0;
|
||||
|
||||
@ -1240,7 +1240,7 @@ pub const Dir = struct {
|
||||
const next_index = self.index + darwin_entry.d_reclen;
|
||||
self.index = next_index;
|
||||
|
||||
const name = (&darwin_entry.d_name)[0..darwin_entry.d_namlen];
|
||||
const name = @ptrCast([*]u8, &darwin_entry.d_name)[0..darwin_entry.d_namlen];
|
||||
|
||||
// skip . and .. entries
|
||||
if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {
|
||||
@ -1704,7 +1704,7 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
|
||||
for (args_alloc) |arg| {
|
||||
total_bytes += @sizeOf([]u8) + arg.len;
|
||||
}
|
||||
const unaligned_allocated_buf = @ptrCast(*const u8, args_alloc.ptr)[0..total_bytes];
|
||||
const unaligned_allocated_buf = @ptrCast([*]const u8, args_alloc.ptr)[0..total_bytes];
|
||||
const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf);
|
||||
return allocator.free(aligned_allocated_buf);
|
||||
}
|
||||
|
||||
@ -266,7 +266,7 @@ test "os.time.timestamp" {
|
||||
|
||||
test "os.time.Timer" {
|
||||
const ns_per_ms = (ns_per_s / ms_per_s);
|
||||
const margin = ns_per_ms * 50;
|
||||
const margin = ns_per_ms * 150;
|
||||
|
||||
var timer = try Timer.start();
|
||||
sleep(0, 10 * ns_per_ms);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// Disable formatting to avoid unnecessary source repository bloat.
|
||||
// zig fmt: off
|
||||
const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// Disable formatting to avoid unnecessary source repository bloat.
|
||||
// zig fmt: off
|
||||
const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4;
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
|
||||
@ -1,3 +1,29 @@
|
||||
test "zig fmt: comment to disable/enable zig fmt first" {
|
||||
try testCanonical(
|
||||
\\// Test trailing comma syntax
|
||||
\\// zig fmt: off
|
||||
\\
|
||||
\\const struct_trailing_comma = struct { x: i32, y: i32, };
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: comment to disable/enable zig fmt" {
|
||||
try testTransform(
|
||||
\\const a = b;
|
||||
\\// zig fmt: off
|
||||
\\const c = d;
|
||||
\\// zig fmt: on
|
||||
\\const e = f;
|
||||
,
|
||||
\\const a = b;
|
||||
\\// zig fmt: off
|
||||
\\const c = d;
|
||||
\\// zig fmt: on
|
||||
\\const e = f;
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: pointer of unknown length" {
|
||||
try testCanonical(
|
||||
\\fn foo(ptr: [*]u8) void {}
|
||||
|
||||
@ -82,8 +82,45 @@ fn renderRoot(
|
||||
|
||||
var start_col: usize = 0;
|
||||
var it = tree.root_node.decls.iterator(0);
|
||||
while (it.next()) |decl| {
|
||||
try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl.*);
|
||||
while (true) {
|
||||
var decl = (it.next() ?? return).*;
|
||||
// look for zig fmt: off comment
|
||||
var start_token_index = decl.firstToken();
|
||||
zig_fmt_loop: while (start_token_index != 0) {
|
||||
start_token_index -= 1;
|
||||
const start_token = tree.tokens.at(start_token_index);
|
||||
switch (start_token.id) {
|
||||
Token.Id.LineComment => {},
|
||||
Token.Id.DocComment => continue,
|
||||
else => break,
|
||||
}
|
||||
if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(start_token)[2..], " "), "zig fmt: off")) {
|
||||
var end_token_index = start_token_index;
|
||||
while (true) {
|
||||
end_token_index += 1;
|
||||
const end_token = tree.tokens.at(end_token_index);
|
||||
switch (end_token.id) {
|
||||
Token.Id.LineComment => {},
|
||||
Token.Id.Eof => {
|
||||
const start = tree.tokens.at(start_token_index + 1).start;
|
||||
try stream.write(tree.source[start..]);
|
||||
return;
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
if (mem.eql(u8, mem.trim(u8, tree.tokenSlicePtr(end_token)[2..], " "), "zig fmt: on")) {
|
||||
const start = tree.tokens.at(start_token_index + 1).start;
|
||||
try stream.print("{}\n", tree.source[start..end_token.end]);
|
||||
while (tree.tokens.at(decl.firstToken()).start < end_token.end) {
|
||||
decl = (it.next() ?? return).*;
|
||||
}
|
||||
break :zig_fmt_loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl);
|
||||
if (it.peek()) |next_decl| {
|
||||
try renderExtraNewline(tree, stream, &start_col, next_decl.*);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ var foo: u8 align(4) = 100;
|
||||
test "global variable alignment" {
|
||||
assert(@typeOf(&foo).alignment == 4);
|
||||
assert(@typeOf(&foo) == *align(4) u8);
|
||||
const slice = (&foo)[0..1];
|
||||
const slice = (*[1]u8)(&foo)[0..];
|
||||
assert(@typeOf(slice) == []align(4) u8);
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
|
||||
test "implicitly decreasing slice alignment" {
|
||||
const a: u32 align(4) = 3;
|
||||
const b: u32 align(8) = 4;
|
||||
assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
|
||||
assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
|
||||
}
|
||||
fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
|
||||
return a[0] + b[0];
|
||||
|
||||
@ -115,3 +115,32 @@ test "array len property" {
|
||||
var x: [5]i32 = undefined;
|
||||
assert(@typeOf(x).len == 5);
|
||||
}
|
||||
|
||||
test "single-item pointer to array indexing and slicing" {
|
||||
testSingleItemPtrArrayIndexSlice();
|
||||
comptime testSingleItemPtrArrayIndexSlice();
|
||||
}
|
||||
|
||||
fn testSingleItemPtrArrayIndexSlice() void {
|
||||
var array = "aaaa";
|
||||
doSomeMangling(&array);
|
||||
assert(mem.eql(u8, "azya", array));
|
||||
}
|
||||
|
||||
fn doSomeMangling(array: *[4]u8) void {
|
||||
array[1] = 'z';
|
||||
array[2..3][0] = 'y';
|
||||
}
|
||||
|
||||
test "implicit cast single-item pointer" {
|
||||
testImplicitCastSingleItemPtr();
|
||||
comptime testImplicitCastSingleItemPtr();
|
||||
}
|
||||
|
||||
fn testImplicitCastSingleItemPtr() void {
|
||||
var byte: u8 = 100;
|
||||
const slice = (*[1]u8)(&byte)[0..];
|
||||
slice[0] += 1;
|
||||
assert(byte == 101);
|
||||
}
|
||||
|
||||
|
||||
@ -418,9 +418,9 @@ test "string literal used as comptime slice is memoized" {
|
||||
}
|
||||
|
||||
test "comptime slice of undefined pointer of length 0" {
|
||||
const slice1 = (*i32)(undefined)[0..0];
|
||||
const slice1 = ([*]i32)(undefined)[0..0];
|
||||
assert(slice1.len == 0);
|
||||
const slice2 = (*i32)(undefined)[100..100];
|
||||
const slice2 = ([*]i32)(undefined)[100..100];
|
||||
assert(slice2.len == 0);
|
||||
}
|
||||
|
||||
@ -508,7 +508,7 @@ test "comptime slice of slice preserves comptime var" {
|
||||
test "comptime slice of pointer preserves comptime var" {
|
||||
comptime {
|
||||
var buff: [10]u8 = undefined;
|
||||
var a = &buff[0];
|
||||
var a = buff[0..].ptr;
|
||||
a[0..1][0] = 1;
|
||||
assert(buff[0..][0..][0] == 1);
|
||||
}
|
||||
|
||||
@ -329,14 +329,14 @@ fn testShrExact(x: u8) void {
|
||||
assert(shifted == 0b00101101);
|
||||
}
|
||||
|
||||
test "big number addition" {
|
||||
test "comptime_int addition" {
|
||||
comptime {
|
||||
assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
|
||||
assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
|
||||
}
|
||||
}
|
||||
|
||||
test "big number multiplication" {
|
||||
test "comptime_int multiplication" {
|
||||
comptime {
|
||||
assert(
|
||||
45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
|
||||
@ -347,13 +347,13 @@ test "big number multiplication" {
|
||||
}
|
||||
}
|
||||
|
||||
test "big number shifting" {
|
||||
test "comptime_int shifting" {
|
||||
comptime {
|
||||
assert((u128(1) << 127) == 0x80000000000000000000000000000000);
|
||||
}
|
||||
}
|
||||
|
||||
test "big number multi-limb shift and mask" {
|
||||
test "comptime_int multi-limb shift and mask" {
|
||||
comptime {
|
||||
var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
|
||||
|
||||
@ -370,7 +370,7 @@ test "big number multi-limb shift and mask" {
|
||||
}
|
||||
}
|
||||
|
||||
test "big number multi-limb partial shift right" {
|
||||
test "comptime_int multi-limb partial shift right" {
|
||||
comptime {
|
||||
var a = 0x1ffffffffeeeeeeee;
|
||||
a >>= 16;
|
||||
@ -391,7 +391,7 @@ fn test_xor() void {
|
||||
assert(0xFF ^ 0xFF == 0x00);
|
||||
}
|
||||
|
||||
test "big number xor" {
|
||||
test "comptime_int xor" {
|
||||
comptime {
|
||||
assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
@ -449,3 +449,15 @@ test "@sqrt" {
|
||||
fn testSqrt(comptime T: type, x: T) void {
|
||||
assert(@sqrt(T, x * x) == x);
|
||||
}
|
||||
|
||||
test "comptime_int param and return" {
|
||||
const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
|
||||
assert(a == 137114567242441932203689521744947848950);
|
||||
|
||||
const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
|
||||
assert(b == 985095453608931032642182098849559179469148836107390954364380);
|
||||
}
|
||||
|
||||
fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
@ -274,7 +274,7 @@ test "generic malloc free" {
|
||||
}
|
||||
var some_mem: [100]u8 = undefined;
|
||||
fn memAlloc(comptime T: type, n: usize) error![]T {
|
||||
return @ptrCast(*T, &some_mem[0])[0..n];
|
||||
return @ptrCast([*]T, &some_mem[0])[0..n];
|
||||
}
|
||||
fn memFree(comptime T: type, memory: []T) void {}
|
||||
|
||||
@ -501,10 +501,10 @@ test "@typeId" {
|
||||
assert(@typeId(*f32) == Tid.Pointer);
|
||||
assert(@typeId([2]u8) == Tid.Array);
|
||||
assert(@typeId(AStruct) == Tid.Struct);
|
||||
assert(@typeId(@typeOf(1)) == Tid.IntLiteral);
|
||||
assert(@typeId(@typeOf(1.0)) == Tid.FloatLiteral);
|
||||
assert(@typeId(@typeOf(undefined)) == Tid.UndefinedLiteral);
|
||||
assert(@typeId(@typeOf(null)) == Tid.NullLiteral);
|
||||
assert(@typeId(@typeOf(1)) == Tid.ComptimeInt);
|
||||
assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
|
||||
assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
|
||||
assert(@typeId(@typeOf(null)) == Tid.Null);
|
||||
assert(@typeId(?i32) == Tid.Nullable);
|
||||
assert(@typeId(error!i32) == Tid.ErrorUnion);
|
||||
assert(@typeId(error) == Tid.ErrorSet);
|
||||
@ -588,7 +588,7 @@ var global_ptr = &gdt[0];
|
||||
|
||||
// can't really run this test but we can make sure it has no compile error
|
||||
// and generates code
|
||||
const vram = @intToPtr(*volatile u8, 0x20000000)[0..0x8000];
|
||||
const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
|
||||
export fn writeToVRam() void {
|
||||
vram[0] = 'X';
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
const x = @intToPtr(*i32, 0x1000)[0..0x500];
|
||||
const x = @intToPtr([*]i32, 0x1000)[0..0x500];
|
||||
const y = x[0x100..];
|
||||
test "compile time slice of pointer to hard coded address" {
|
||||
assert(@ptrToInt(x.ptr) == 0x1000);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
// Test trailing comma syntax
|
||||
// zig fmt: off
|
||||
|
||||
const struct_trailing_comma = struct { x: i32, y: i32, };
|
||||
const struct_no_comma = struct { x: i32, y: i32 };
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add(
|
||||
"slicing single-item pointer",
|
||||
\\export fn entry(ptr: *i32) void {
|
||||
\\ const slice = ptr[0..2];
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:22: error: slice of single-item pointer",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"indexing single-item pointer",
|
||||
\\export fn entry(ptr: *i32) i32 {
|
||||
\\ return ptr[1];
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:15: error: indexing not allowed on pointer to single item",
|
||||
".tmp_source.zig:2:15: error: index of single-item pointer",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -144,10 +153,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add(
|
||||
"comptime slice of undefined pointer non-zero len",
|
||||
\\export fn entry() void {
|
||||
\\ const slice = (*i32)(undefined)[0..1];
|
||||
\\ const slice = ([*]i32)(undefined)[0..1];
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:36: error: non-zero length slice of undefined pointer",
|
||||
".tmp_source.zig:2:38: error: non-zero length slice of undefined pointer",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -1530,7 +1539,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\fn foo() *const i32 { return y; }
|
||||
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
|
||||
,
|
||||
".tmp_source.zig:3:30: error: expected type '*const i32', found '*const (integer literal)'",
|
||||
".tmp_source.zig:3:30: error: expected type '*const i32', found '*const comptime_int'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -1546,7 +1555,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\const x = 2 == 2.0;
|
||||
\\export fn entry() usize { return @sizeOf(@typeOf(x)); }
|
||||
,
|
||||
".tmp_source.zig:1:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'",
|
||||
".tmp_source.zig:1:11: error: integer value 2 cannot be implicitly casted to type 'comptime_float'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -2180,7 +2189,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\
|
||||
\\export fn entry() usize { return @sizeOf(@typeOf(block_aligned_stuff)); }
|
||||
,
|
||||
".tmp_source.zig:3:60: error: unable to perform binary not operation on type '(integer literal)'",
|
||||
".tmp_source.zig:3:60: error: unable to perform binary not operation on type 'comptime_int'",
|
||||
);
|
||||
|
||||
cases.addCase(x: {
|
||||
@ -3129,14 +3138,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\export fn entry() void {
|
||||
\\ var foo = Foo { .a = 1, .b = 10 };
|
||||
\\ foo.b += 1;
|
||||
\\ bar((&foo.b)[0..1]);
|
||||
\\ bar((*[1]u32)(&foo.b)[0..]);
|
||||
\\}
|
||||
\\
|
||||
\\fn bar(x: []u32) void {
|
||||
\\ x[0] += 1;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align(1) u32'",
|
||||
".tmp_source.zig:9:18: error: cast increases pointer alignment",
|
||||
".tmp_source.zig:9:23: note: '*align(1) u32' has alignment 1",
|
||||
".tmp_source.zig:9:18: note: '*[1]u32' has alignment 4",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@ -3258,10 +3269,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ fn bar(self: *const Foo) void {}
|
||||
\\};
|
||||
,
|
||||
".tmp_source.zig:4:4: error: variable of type '*(integer literal)' must be const or comptime",
|
||||
".tmp_source.zig:4:4: error: variable of type '*comptime_int' must be const or comptime",
|
||||
".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime",
|
||||
".tmp_source.zig:8:4: error: variable of type '(integer literal)' must be const or comptime",
|
||||
".tmp_source.zig:9:4: error: variable of type '(float literal)' must be const or comptime",
|
||||
".tmp_source.zig:8:4: error: variable of type 'comptime_int' must be const or comptime",
|
||||
".tmp_source.zig:9:4: error: variable of type 'comptime_float' must be const or comptime",
|
||||
".tmp_source.zig:10:4: error: variable of type '(block)' must be const or comptime",
|
||||
".tmp_source.zig:11:4: error: variable of type '(null)' must be const or comptime",
|
||||
".tmp_source.zig:12:4: error: variable of type 'Opaque' must be const or comptime",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user