diff options
| -rw-r--r-- | builtins/integers.c | 29 | ||||
| -rw-r--r-- | builtins/integers.h | 2 | ||||
| -rw-r--r-- | builtins/nums.c | 8 | ||||
| -rw-r--r-- | builtins/nums.h | 4 | ||||
| -rw-r--r-- | compile.c | 24 | ||||
| -rw-r--r-- | docs/integers.md | 28 | ||||
| -rw-r--r-- | environment.c | 12 |
7 files changed, 50 insertions, 57 deletions
diff --git a/builtins/integers.c b/builtins/integers.c index 8e17ca24..bf55d0ae 100644 --- a/builtins/integers.c +++ b/builtins/integers.c @@ -460,23 +460,20 @@ public const TypeInfo $Int = { public Range_t KindOfInt ## $to(c_type from, c_type to) { \ return (Range_t){Int64_to_Int(from), Int64_to_Int(to), to >= from ? (Int_t){.small=(1<<2)&1} : (Int_t){.small=(1<<2)&1}}; \ } \ - public c_type KindOfInt ## $from_text(Text_t text, Text_t *the_rest) { \ - const char *str = Text$as_c_string(text); \ - long i; \ - char *end_ptr = NULL; \ - if (strncmp(str, "0x", 2) == 0) { \ - i = strtol(str, &end_ptr, 16); \ - } else if (strncmp(str, "0o", 2) == 0) { \ - i = strtol(str, &end_ptr, 8); \ - } else if (strncmp(str, "0b", 2) == 0) { \ - i = strtol(str, &end_ptr, 2); \ - } else { \ - i = strtol(str, &end_ptr, 10); \ + public c_type KindOfInt ## $from_text(Text_t text, bool *success) { \ + bool parsed_int = false; \ + Int_t full_int = Int$from_text(text, &parsed_int); \ + if (!parsed_int && success) *success = false; \ + if (Int$compare(&full_int, (Int_t[1]){I(min_val)}, &$Int) < 0) { \ + if (success) *success = false; \ + return min_val; \ } \ - if (the_rest) *the_rest = Text$from_str(end_ptr); \ - if (i < min_val) i = min_val; \ - else if (i > max_val) i = min_val; \ - return (c_type)i; \ + if (Int$compare(&full_int, (Int_t[1]){I(max_val)}, &$Int) > 0) { \ + if (success) *success = false; \ + return max_val; \ + } \ + if (success && parsed_int) *success = true; \ + return Int_to_ ## KindOfInt(full_int, true); \ } \ public const c_type KindOfInt##$min = min_val; \ public const c_type KindOfInt##$max = max_val; \ diff --git a/builtins/integers.h b/builtins/integers.h index 9f342f2f..e24b7869 100644 --- a/builtins/integers.h +++ b/builtins/integers.h @@ -33,7 +33,7 @@ array_t type_name ## $bits(c_type x); \ c_type type_name ## $random(c_type min, c_type max); \ Range_t type_name ## $to(c_type from, c_type to); \ - c_type type_name ## $from_text(Text_t text, Text_t *the_rest); \ + c_type type_name ## $from_text(Text_t text, bool *success); \ static inline c_type type_name ## $clamped(c_type x, c_type min, c_type max) { \ return x < min ? min : (x > max ? max : x); \ } \ diff --git a/builtins/nums.c b/builtins/nums.c index 94837281..ab386c78 100644 --- a/builtins/nums.c +++ b/builtins/nums.c @@ -66,11 +66,11 @@ public double Num$mix(double amount, double x, double y) { return (1.0-amount)*x + amount*y; } -public double Num$from_text(Text_t text, Text_t *the_rest) { +public double Num$from_text(Text_t text, bool *success) { const char *str = Text$as_c_string(text); char *end = NULL; double d = strtod(str, &end); - if (the_rest) *the_rest = Text$from_str(end); + if (success) *success = (end > str && end[0] == '\0'); return d; } @@ -145,11 +145,11 @@ public float Num32$mix(float amount, float x, float y) { return (1.0-amount)*x + amount*y; } -public float Num32$from_text(Text_t text, Text_t *the_rest) { +public float Num32$from_text(Text_t text, bool *success) { const char *str = Text$as_c_string(text); char *end = NULL; double d = strtod(str, &end); - if (the_rest) *the_rest = Text$from_str(end); + if (success) *success = (end > str && end[0] == '\0'); return (float)d; } diff --git a/builtins/nums.h b/builtins/nums.h index c5562f0a..a3f862d7 100644 --- a/builtins/nums.h +++ b/builtins/nums.h @@ -27,7 +27,7 @@ bool Num$isnan(double n); double Num$nan(Text_t tag); double Num$random(void); double Num$mix(double amount, double x, double y); -double Num$from_text(Text_t text, Text_t *the_rest); +double Num$from_text(Text_t text, bool *success); static inline double Num$clamped(double x, double low, double high) { return (x <= low) ? low : (x >= high ? high : x); } @@ -45,7 +45,7 @@ bool Num32$finite(float n); bool Num32$isnan(float n); float Num32$random(void); float Num32$mix(float amount, float x, float y); -float Num32$from_text(Text_t text, Text_t *the_rest); +float Num32$from_text(Text_t text, bool *success); float Num32$nan(Text_t tag); static inline float Num32$clamped(float x, float low, float high) { return (x <= low) ? low : (x >= high ? high : x); @@ -3078,7 +3078,7 @@ CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type) "}\n"); break; } - case BigIntType: { + case BigIntType: case IntType: case NumType: { CORD type_name = type_to_cord(t); code = CORD_all(code, "else if (pop_flag(argv, &i, \"", flag, "\", &flag)) {\n", "if (flag.length == 0)\n" @@ -3089,19 +3089,6 @@ CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type) "}\n"); break; } - case IntType: case NumType: { - CORD type_name = type_to_cord(t); - code = CORD_all(code, "else if (pop_flag(argv, &i, \"", flag, "\", &flag)) {\n", - "if (flag.length == 0)\n" - "USAGE_ERR(\"No value provided for '--", flag, "'\");\n" - "Text_t invalid = Text(\"\");\n", - "$", arg->name, " = ", type_name, "$from_text(flag, &invalid);\n" - "if (invalid.length != 0)\n" - "USAGE_ERR(\"Invalid value provided for '--", flag, "'\");\n", - arg->name, "$is_set = yes;\n" - "}\n"); - break; - } default: compiler_err(NULL, NULL, NULL, "Main function has unsupported argument type: %T", t); } @@ -3138,20 +3125,13 @@ CORD compile_cli_arg_call(env_t *env, CORD fn_name, type_t *fn_type) "if (i < argc) {"); if (t->tag == TextType) { code = CORD_all(code, "$", arg->name, " = Text$from_str(argv[i]);\n"); - } else if (t->tag == BoolType || t->tag == BigIntType) { + } else { code = CORD_all( code, "bool success = false;\n", "$", arg->name, " = ", type_to_cord(t), "$from_text(Text$from_str(argv[i]), &success)", ";\n" "if (!success)\n" "USAGE_ERR(\"Unable to parse this argument as a ", type_to_cord(t), ": %s\", argv[i]);\n"); - } else { - code = CORD_all( - code, - "Text_t invalid = Text(\"\");\n", - "$", arg->name, " = ", type_to_cord(t), "$from_text(Text$from_str(argv[i]), &invalid)", ";\n" - "if (invalid.length != 0)\n" - "USAGE_ERR(\"Unable to parse this argument as a ", type_to_cord(t), ": %s\", argv[i]);\n"); } code = CORD_all( code, diff --git a/docs/integers.md b/docs/integers.md index 653322fd..50ecd034 100644 --- a/docs/integers.md +++ b/docs/integers.md @@ -144,23 +144,39 @@ Converts a text representation of an integer into an integer. **Usage:** ```tomo -from_text(text: Text, the_rest: Text = "!&Text") -> Int +from_text(text: Text, success: Bool = !&Bool?) -> Int ``` **Parameters:** -- `text`: The string containing the integer. -- `the_rest`: If non-null, this pointer will be set to point to any unparseable text after the integer. +- `text`: The text containing the integer. +- `success`: If non-null, this pointer will be set to `yes` if the whole text + is a valid integer that fits within the representable range of the integer + type, otherwise `no`. **Returns:** -The integer represented by the string. +The integer represented by the text. If the given text contains a value outside +of the representable range, the number will be truncated to the minimum or +maximum representable value. Other failures to parse the number will return +zero. **Example:** ```tomo ->> from_text("123") +>> Int.from_text("123") = 123 ->> from_text("0xFF") +>> Int.from_text("0xFF") = 255 + +success := no +>> Int.from_text("asdf", &success) += 0 +>> success += no + +>> Int8.from_text("9999999", &success) += 127 +>> success += no ``` --- diff --git a/environment.c b/environment.c index 32e3f7f6..8f5de0de 100644 --- a/environment.c +++ b/environment.c @@ -117,7 +117,7 @@ env_t *new_compilation_unit(CORD *libname) {"clamped", "Int64$clamped", "func(x:Int64,low:Int64,high:Int64)->Int64"}, {"divided_by", "Int64$divided_by", "func(x:Int64,y:Int64)->Int64"}, {"format", "Int64$format", "func(i:Int64, digits=0)->Text"}, - {"from_text", "Int64$from_text", "func(text:Text, the_rest=!&Text)->Int64"}, + {"from_text", "Int64$from_text", "func(text:Text, success=!&Bool)->Int64"}, {"hex", "Int64$hex", "func(i:Int64, digits=0, uppercase=yes, prefix=yes)->Text"}, {"max", "Int64$max", "Int64"}, {"min", "Int64$min", "Int64"}, @@ -133,7 +133,7 @@ env_t *new_compilation_unit(CORD *libname) {"clamped", "Int32$clamped", "func(x:Int32,low:Int32,high:Int32)->Int32"}, {"divided_by", "Int32$divided_by", "func(x:Int32,y:Int32)->Int32"}, {"format", "Int32$format", "func(i:Int32, digits=0)->Text"}, - {"from_text", "Int32$from_text", "func(text:Text, the_rest=!&Text)->Int32"}, + {"from_text", "Int32$from_text", "func(text:Text, success=!&Bool)->Int32"}, {"hex", "Int32$hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes)->Text"}, {"max", "Int32$max", "Int32"}, {"min", "Int32$min", "Int32"}, @@ -149,7 +149,7 @@ env_t *new_compilation_unit(CORD *libname) {"clamped", "Int16$clamped", "func(x:Int16,low:Int16,high:Int16)->Int16"}, {"divided_by", "Int16$divided_by", "func(x:Int16,y:Int16)->Int16"}, {"format", "Int16$format", "func(i:Int16, digits=0)->Text"}, - {"from_text", "Int16$from_text", "func(text:Text, the_rest=!&Text)->Int16"}, + {"from_text", "Int16$from_text", "func(text:Text, success=!&Bool)->Int16"}, {"hex", "Int16$hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes)->Text"}, {"max", "Int16$max", "Int16"}, {"min", "Int16$min", "Int16"}, @@ -165,7 +165,7 @@ env_t *new_compilation_unit(CORD *libname) {"clamped", "Int8$clamped", "func(x:Int8,low:Int8,high:Int8)->Int8"}, {"divided_by", "Int8$divided_by", "func(x:Int8,y:Int8)->Int8"}, {"format", "Int8$format", "func(i:Int8, digits=0)->Text"}, - {"from_text", "Int8$from_text", "func(text:Text, the_rest=!&Text)->Int8"}, + {"from_text", "Int8$from_text", "func(text:Text, success=!&Bool)->Int8"}, {"hex", "Int8$hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes)->Text"}, {"max", "Int8$max", "Int8"}, {"min", "Int8$min", "Int8"}, @@ -193,7 +193,7 @@ env_t *new_compilation_unit(CORD *libname) {"TAU", "(Num_t)(2.*M_PI)", "Num"}, {"random", "Num$random", "func()->Num"}, {"mix", "Num$mix", "func(amount:Num, x:Num, y:Num)->Num"}, - {"from_text", "Num$from_text", "func(text:Text, the_rest=!&Text)->Num"}, + {"from_text", "Num$from_text", "func(text:Text, success=!&Bool)->Num"}, {"abs", "fabs", "func(n:Num)->Num"}, F(acos), F(acosh), F(asin), F(asinh), F(atan), F(atanh), F(cbrt), F(ceil), F(cos), F(cosh), F(erf), F(erfc), F(exp), F(exp2), F(expm1), F(floor), F(j0), F(j1), F(log), F(log10), F(log1p), F(log2), F(logb), @@ -222,7 +222,7 @@ env_t *new_compilation_unit(CORD *libname) {"TAU", "(Num32_t)(2.f*M_PI)", "Num32"}, {"random", "Num32$random", "func()->Num32"}, {"mix", "Num32$mix", "func(amount:Num32, x:Num32, y:Num32)->Num32"}, - {"from_text", "Num32$from_text", "func(text:Text, the_rest=!&Text)->Num32"}, + {"from_text", "Num32$from_text", "func(text:Text, success=!&Bool)->Num32"}, {"abs", "fabsf", "func(n:Num32)->Num32"}, F(acos), F(acosh), F(asin), F(asinh), F(atan), F(atanh), F(cbrt), F(ceil), F(cos), F(cosh), F(erf), F(erfc), F(exp), F(exp2), F(expm1), F(floor), F(j0), F(j1), F(log), F(log10), F(log1p), F(log2), F(logb), |
