aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtins/integers.c29
-rw-r--r--builtins/integers.h2
-rw-r--r--builtins/nums.c8
-rw-r--r--builtins/nums.h4
-rw-r--r--compile.c24
-rw-r--r--docs/integers.md28
-rw-r--r--environment.c12
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);
diff --git a/compile.c b/compile.c
index 5c934d8d..caa59e3d 100644
--- a/compile.c
+++ b/compile.c
@@ -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),