Fix integer random functions so they correctly handle all representable
ranges
This commit is contained in:
parent
46396646bf
commit
17be975d3a
@ -51,14 +51,22 @@
|
|||||||
} \
|
} \
|
||||||
return bit_array; \
|
return bit_array; \
|
||||||
} \
|
} \
|
||||||
public c_type KindOfInt ## $random(int64_t min, int64_t max) { \
|
public c_type KindOfInt ## $random(c_type min, c_type max) { \
|
||||||
if (min > max) fail("Random min (%ld) is larger than max (%ld)", min, max); \
|
if (min > max) fail("Random minimum value (%ld) is larger than the maximum value (%ld)", min, max); \
|
||||||
if (min < (int64_t)min_val) fail("Random min (%ld) is smaller than the minimum "#KindOfInt" value", min); \
|
if (min == max) return min; \
|
||||||
if (max > (int64_t)max_val) fail("Random max (%ld) is smaller than the maximum "#KindOfInt" value", max); \
|
if (min == min_val && max == max_val) { \
|
||||||
int64_t range = max - min; \
|
c_type r; \
|
||||||
if (range > UINT32_MAX) fail("Random range (%ld) is larger than the maximum allowed (%ld)", range, UINT32_MAX); \
|
arc4random_buf(&r, sizeof(r)); \
|
||||||
uint32_t r = arc4random_uniform((uint32_t)range); \
|
return r; \
|
||||||
return min + (c_type)r; \
|
} \
|
||||||
|
uint64_t range = (uint64_t)max - (uint64_t)min + 1; \
|
||||||
|
uint64_t min_r = -range % range; \
|
||||||
|
uint64_t r; \
|
||||||
|
for (;;) { \
|
||||||
|
arc4random_buf(&r, sizeof(r)); \
|
||||||
|
if (r >= min_r) break; \
|
||||||
|
} \
|
||||||
|
return (c_type)((uint64_t)min + (r % range)); \
|
||||||
} \
|
} \
|
||||||
public c_type KindOfInt ## $from_text(CORD text, CORD *the_rest) { \
|
public c_type KindOfInt ## $from_text(CORD text, CORD *the_rest) { \
|
||||||
const char *str = CORD_to_const_char_star(text); \
|
const char *str = CORD_to_const_char_star(text); \
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
CORD type_name ## $hex(c_type i, int64_t digits, bool uppercase, bool prefix); \
|
CORD type_name ## $hex(c_type i, int64_t digits, bool uppercase, bool prefix); \
|
||||||
CORD type_name ## $octal(c_type i, int64_t digits, bool prefix); \
|
CORD type_name ## $octal(c_type i, int64_t digits, bool prefix); \
|
||||||
array_t type_name ## $bits(c_type x); \
|
array_t type_name ## $bits(c_type x); \
|
||||||
c_type type_name ## $random(int64_t min, int64_t max); \
|
c_type type_name ## $random(c_type min, c_type max); \
|
||||||
c_type type_name ## $from_text(CORD text, CORD *the_rest); \
|
c_type type_name ## $from_text(CORD text, CORD *the_rest); \
|
||||||
extern const c_type type_name ## $min, type_name##$max; \
|
extern const c_type type_name ## $min, type_name##$max; \
|
||||||
extern const TypeInfo $ ## type_name;
|
extern const TypeInfo $ ## type_name;
|
||||||
|
10
compile.c
10
compile.c
@ -181,7 +181,11 @@ static CORD compile_lvalue(env_t *env, ast_t *ast)
|
|||||||
} else if (container_t->tag == TableType) {
|
} else if (container_t->tag == TableType) {
|
||||||
CORD target_code = compile_to_pointer_depth(env, index->indexed, 1, false);
|
CORD target_code = compile_to_pointer_depth(env, index->indexed, 1, false);
|
||||||
type_t *value_t = Match(container_t, TableType)->value_type;
|
type_t *value_t = Match(container_t, TableType)->value_type;
|
||||||
return CORD_all("*(", compile_type(value_t), "*)Table$reserve_value(", target_code, ", ",
|
CORD key = compile(env, index->index);
|
||||||
|
if (!promote(env, &key, get_type(env, index->index), Match(container_t, TableType)->key_type))
|
||||||
|
code_err(index->index, "I couldn't promote this type from %T to %T",
|
||||||
|
get_type(env, index->index), Match(container_t, TableType)->key_type);
|
||||||
|
return CORD_all("*(", compile_type(value_t), "*)Table$reserve_value(", target_code, ", (", compile_type(Match(container_t, TableType)->key_type), ")",
|
||||||
compile(env, index->index),", ", compile_type_info(env, container_t), ")");
|
compile(env, index->index),", ", compile_type_info(env, container_t), ")");
|
||||||
} else {
|
} else {
|
||||||
code_err(ast, "I don't know how to assign to this target");
|
code_err(ast, "I don't know how to assign to this target");
|
||||||
@ -1671,12 +1675,12 @@ CORD compile(env_t *env, ast_t *ast)
|
|||||||
case Table: {
|
case Table: {
|
||||||
auto table = Match(ast, Table);
|
auto table = Match(ast, Table);
|
||||||
if (!table->entries) {
|
if (!table->entries) {
|
||||||
CORD code = "(table_t){";
|
CORD code = "((table_t){";
|
||||||
if (table->fallback)
|
if (table->fallback)
|
||||||
code = CORD_all(code, ".fallback=", compile(env, table->fallback),",");
|
code = CORD_all(code, ".fallback=", compile(env, table->fallback),",");
|
||||||
if (table->default_value)
|
if (table->default_value)
|
||||||
code = CORD_all(code, ".default_value=heap(", compile(env, table->default_value),"),");
|
code = CORD_all(code, ".default_value=heap(", compile(env, table->default_value),"),");
|
||||||
return CORD_cat(code, "}");
|
return CORD_cat(code, "})");
|
||||||
}
|
}
|
||||||
|
|
||||||
type_t *table_type = get_type(env, ast);
|
type_t *table_type = get_type(env, ast);
|
||||||
|
@ -74,7 +74,7 @@ env_t *new_compilation_unit(CORD *libname)
|
|||||||
{"format", "Int$format", "func(i:Int, digits=0)->Text"},
|
{"format", "Int$format", "func(i:Int, digits=0)->Text"},
|
||||||
{"hex", "Int$hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes)->Text"},
|
{"hex", "Int$hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes)->Text"},
|
||||||
{"octal", "Int$octal", "func(i:Int, digits=0, prefix=yes)->Text"},
|
{"octal", "Int$octal", "func(i:Int, digits=0, prefix=yes)->Text"},
|
||||||
{"random", "Int$random", "func(min=0, max=0xffffffff)->Int"},
|
{"random", "Int$random", "func(min=-0x8000000000000000, max=0x7FFFFFFFFFFFFFFF)->Int"},
|
||||||
{"from_text", "Int$from_text", "func(text:Text, the_rest=!&Text)->Int"},
|
{"from_text", "Int$from_text", "func(text:Text, the_rest=!&Text)->Int"},
|
||||||
{"bits", "Int$bits", "func(x:Int)->[Bool]"},
|
{"bits", "Int$bits", "func(x:Int)->[Bool]"},
|
||||||
{"abs", "labs", "func(i:Int)->Int"},
|
{"abs", "labs", "func(i:Int)->Int"},
|
||||||
@ -85,7 +85,7 @@ env_t *new_compilation_unit(CORD *libname)
|
|||||||
{"format", "Int32$format", "func(i:Int32, digits=0)->Text"},
|
{"format", "Int32$format", "func(i:Int32, digits=0)->Text"},
|
||||||
{"hex", "Int32$hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes)->Text"},
|
{"hex", "Int32$hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes)->Text"},
|
||||||
{"octal", "Int32$octal", "func(i:Int32, digits=0, prefix=yes)->Text"},
|
{"octal", "Int32$octal", "func(i:Int32, digits=0, prefix=yes)->Text"},
|
||||||
{"random", "Int32$random", "func(min=0, max=0xffffffff)->Int32"},
|
{"random", "Int32$random", "func(min=-0x80000000_i32, max=0x7FFFFFFF_i32)->Int32"},
|
||||||
{"from_text", "Int$from_text", "func(text:Text, the_rest=!&Text)->Int32"},
|
{"from_text", "Int$from_text", "func(text:Text, the_rest=!&Text)->Int32"},
|
||||||
{"bits", "Int32$bits", "func(x:Int32)->[Bool]"},
|
{"bits", "Int32$bits", "func(x:Int32)->[Bool]"},
|
||||||
{"abs", "abs", "func(i:Int32)->Int32"},
|
{"abs", "abs", "func(i:Int32)->Int32"},
|
||||||
@ -96,7 +96,7 @@ env_t *new_compilation_unit(CORD *libname)
|
|||||||
{"format", "Int16$format", "func(i:Int16, digits=0)->Text"},
|
{"format", "Int16$format", "func(i:Int16, digits=0)->Text"},
|
||||||
{"hex", "Int16$hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes)->Text"},
|
{"hex", "Int16$hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes)->Text"},
|
||||||
{"octal", "Int16$octal", "func(i:Int16, digits=0, prefix=yes)->Text"},
|
{"octal", "Int16$octal", "func(i:Int16, digits=0, prefix=yes)->Text"},
|
||||||
{"random", "Int16$random", "func(min=0, max=0xffffffff)->Int16"},
|
{"random", "Int16$random", "func(min=-0x8000_i16, max=0x7FFF_i16)->Int16"},
|
||||||
{"from_text", "Int$from_text", "func(text:Text, the_rest=!&Text)->Int16"},
|
{"from_text", "Int$from_text", "func(text:Text, the_rest=!&Text)->Int16"},
|
||||||
{"bits", "Int16$bits", "func(x:Int16)->[Bool]"},
|
{"bits", "Int16$bits", "func(x:Int16)->[Bool]"},
|
||||||
{"abs", "abs", "func(i:Int16)->Int16"},
|
{"abs", "abs", "func(i:Int16)->Int16"},
|
||||||
@ -107,7 +107,7 @@ env_t *new_compilation_unit(CORD *libname)
|
|||||||
{"format", "Int8$format", "func(i:Int8, digits=0)->Text"},
|
{"format", "Int8$format", "func(i:Int8, digits=0)->Text"},
|
||||||
{"hex", "Int8$hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes)->Text"},
|
{"hex", "Int8$hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes)->Text"},
|
||||||
{"octal", "Int8$octal", "func(i:Int8, digits=0, prefix=yes)->Text"},
|
{"octal", "Int8$octal", "func(i:Int8, digits=0, prefix=yes)->Text"},
|
||||||
{"random", "Int8$random", "func(min=0, max=0xffffffff)->Int8"},
|
{"random", "Int8$random", "func(min=-0x80_i8, max=0x7F_i8)->Int8"},
|
||||||
{"from_text", "Int$from_text", "func(text:Text, the_rest=!&Text)->Int8"},
|
{"from_text", "Int$from_text", "func(text:Text, the_rest=!&Text)->Int8"},
|
||||||
{"bits", "Int8$bits", "func(x:Int8)->[Bool]"},
|
{"bits", "Int8$bits", "func(x:Int8)->[Bool]"},
|
||||||
{"abs", "abs", "func(i:Int8)->Int8"},
|
{"abs", "abs", "func(i:Int8)->Int8"},
|
||||||
|
Loading…
Reference in New Issue
Block a user