Rename "NULL" to "NONE"

This commit is contained in:
Bruce Hill 2024-11-24 16:18:21 -05:00
parent 0e10313d64
commit 1e3fb8a2c0
36 changed files with 126 additions and 126 deletions

View File

@ -422,7 +422,7 @@ CORD check_null(type_t *t, CORD value)
else if (t->tag == TableType || t->tag == SetType) else if (t->tag == TableType || t->tag == SetType)
return CORD_all("((", value, ").entries.length < 0)"); return CORD_all("((", value, ").entries.length < 0)");
else if (t->tag == BoolType) else if (t->tag == BoolType)
return CORD_all("((", value, ") == NULL_BOOL)"); return CORD_all("((", value, ") == NONE_BOOL)");
else if (t->tag == TextType) else if (t->tag == TextType)
return CORD_all("((", value, ").length < 0)"); return CORD_all("((", value, ").length < 0)");
else if (t->tag == IntType || t->tag == ByteType || t->tag == StructType) else if (t->tag == IntType || t->tag == ByteType || t->tag == StructType)
@ -1862,28 +1862,28 @@ CORD compile_null(type_t *t)
if (t == THREAD_TYPE) return "NULL"; if (t == THREAD_TYPE) return "NULL";
switch (t->tag) { switch (t->tag) {
case BigIntType: return "NULL_INT"; case BigIntType: return "NONE_INT";
case IntType: { case IntType: {
switch (Match(t, IntType)->bits) { switch (Match(t, IntType)->bits) {
case TYPE_IBITS8: return "NULL_INT8"; case TYPE_IBITS8: return "NONE_INT8";
case TYPE_IBITS16: return "NULL_INT16"; case TYPE_IBITS16: return "NONE_INT16";
case TYPE_IBITS32: return "NULL_INT32"; case TYPE_IBITS32: return "NONE_INT32";
case TYPE_IBITS64: return "NULL_INT64"; case TYPE_IBITS64: return "NONE_INT64";
default: errx(1, "Invalid integer bit size"); default: errx(1, "Invalid integer bit size");
} }
break; break;
} }
case BoolType: return "NULL_BOOL"; case BoolType: return "NONE_BOOL";
case ByteType: return "NULL_BYTE"; case ByteType: return "NONE_BYTE";
case ArrayType: return "NULL_ARRAY"; case ArrayType: return "NONE_ARRAY";
case TableType: return "NULL_TABLE"; case TableType: return "NONE_TABLE";
case SetType: return "NULL_TABLE"; case SetType: return "NONE_TABLE";
case ChannelType: return "NULL"; case ChannelType: return "NULL";
case TextType: return "NULL_TEXT"; case TextType: return "NONE_TEXT";
case CStringType: return "NULL"; case CStringType: return "NULL";
case MomentType: return "NULL_MOMENT"; case MomentType: return "NONE_MOMENT";
case PointerType: return CORD_all("((", compile_type(t), ")NULL)"); case PointerType: return CORD_all("((", compile_type(t), ")NULL)");
case ClosureType: return "NULL_CLOSURE"; case ClosureType: return "NONE_CLOSURE";
case NumType: return "nan(\"null\")"; case NumType: return "nan(\"null\")";
case StructType: return CORD_all("((", compile_type(Type(OptionalType, .type=t)), "){.is_null=yes})"); case StructType: return CORD_all("((", compile_type(Type(OptionalType, .type=t)), "){.is_null=yes})");
case EnumType: { case EnumType: {
@ -3245,12 +3245,12 @@ CORD compile(env_t *env, ast_t *ast)
CORD code = CORD_all( CORD code = CORD_all(
"({ // Reduction:\n", "({ // Reduction:\n",
compile_declaration(item_t, "prev"), ";\n" compile_declaration(item_t, "prev"), ";\n"
"OptionalBool_t result = NULL_BOOL;\n" "OptionalBool_t result = NONE_BOOL;\n"
); );
ast_t *comparison = WrapAST(ast, BinaryOp, .op=op, .lhs=FakeAST(InlineCCode, .code="prev", .type=item_t), .rhs=item); ast_t *comparison = WrapAST(ast, BinaryOp, .op=op, .lhs=FakeAST(InlineCCode, .code="prev", .type=item_t), .rhs=item);
body->__data.InlineCCode.code = CORD_all( body->__data.InlineCCode.code = CORD_all(
"if (result == NULL_BOOL) {\n" "if (result == NONE_BOOL) {\n"
" prev = ", compile(body_scope, item), ";\n" " prev = ", compile(body_scope, item), ";\n"
" result = yes;\n" " result = yes;\n"
"} else {\n" "} else {\n"
@ -3439,7 +3439,7 @@ CORD compile(env_t *env, ast_t *ast)
"values.data += ", CORD_asprintf("%zu", offset), ";\n" "values.data += ", CORD_asprintf("%zu", offset), ";\n"
"values; })"); "values; })");
} else if (streq(f->field, "fallback")) { } else if (streq(f->field, "fallback")) {
return CORD_all("({ Table_t *_fallback = (", compile_to_pointer_depth(env, f->fielded, 0, false), ").fallback; _fallback ? *_fallback : NULL_TABLE; })"); return CORD_all("({ Table_t *_fallback = (", compile_to_pointer_depth(env, f->fielded, 0, false), ").fallback; _fallback ? *_fallback : NONE_TABLE; })");
} }
code_err(ast, "There is no '%s' field on tables", f->field); code_err(ast, "There is no '%s' field on tables", f->field);
} }

View File

@ -366,7 +366,7 @@ The index of the first occurrence or `!Int` if not found.
= 2 : Int? = 2 : Int?
>> [10, 20, 30, 40, 50]:find(9999) >> [10, 20, 30, 40, 50]:find(9999)
= NULL : Int? = NONE : Int?
``` ```
--- ---
@ -396,7 +396,7 @@ item matches.
>> [4, 5, 6]:find(func(i:&Int): i:is_prime()) >> [4, 5, 6]:find(func(i:&Int): i:is_prime())
= 5 : Int? = 5 : Int?
>> [4, 6, 8]:find(func(i:&Int): i:is_prime()) >> [4, 6, 8]:find(func(i:&Int): i:is_prime())
= NULL : Int? = NONE : Int?
``` ```
--- ---

View File

@ -33,5 +33,5 @@ func parse(text: Text -> Bool?)
>> Bool.parse("no") >> Bool.parse("no")
= no : Bool? = no : Bool?
>> Bool.parse("???") >> Bool.parse("???")
= NULL : Bool? = NONE : Bool?
``` ```

View File

@ -171,7 +171,7 @@ func parse(text: Text -> Int?)
**Returns:** **Returns:**
The integer represented by the text. If the given text contains a value outside The integer represented by the text. If the given text contains a value outside
of the representable range or if the entire text can't be parsed as an integer, of the representable range or if the entire text can't be parsed as an integer,
`NULL` will be returned. `NONE` will be returned.
**Example:** **Example:**
```tomo ```tomo
@ -182,11 +182,11 @@ of the representable range or if the entire text can't be parsed as an integer,
# Can't parse: # Can't parse:
>> Int.parse("asdf") >> Int.parse("asdf")
= NULL : Int? = NONE : Int?
# Outside valid range: # Outside valid range:
>> Int8.parse("9999999") >> Int8.parse("9999999")
= NULL : Int8? = NONE : Int8?
``` ```
--- ---

View File

@ -22,7 +22,7 @@ successively gets one line from a file at a time until the file is exhausted:
>> iter() >> iter()
= "line three" : Text? = "line three" : Text?
>> iter() >> iter()
= NULL : Text? = NONE : Text?
for line in (./test.txt):each_line(): for line in (./test.txt):each_line():
pass pass

View File

@ -6,7 +6,7 @@ behavior that is required for all types:
- `func as_text(obj:&T?, colorize=no, type:&TypeInfo_t -> Text)`: a method to - `func as_text(obj:&T?, colorize=no, type:&TypeInfo_t -> Text)`: a method to
convert the type to a string. If `colorize` is `yes`, then the method should convert the type to a string. If `colorize` is `yes`, then the method should
include ANSI escape codes for syntax highlighting. If the `obj` pointer is include ANSI escape codes for syntax highlighting. If the `obj` pointer is
`NULL`, a string representation of the type will be returned instead. `NONE`, a string representation of the type will be returned instead.
- `func compare(x:&T, y:&T, type:&TypeInfo_t -> Int32)`: Return an integer representing - `func compare(x:&T, y:&T, type:&TypeInfo_t -> Int32)`: Return an integer representing
the result of comparing `x` and `y`, where negative numbers mean `x` is less the result of comparing `x` and `y`, where negative numbers mean `x` is less

View File

@ -523,7 +523,7 @@ Returns a `Moment` object representing the current date and time.
**Description:** **Description:**
Return a new `Moment` object parsed from the given string in the given format, Return a new `Moment` object parsed from the given string in the given format,
or `NULL` if the value could not be successfully parsed. or `NONE` if the value could not be successfully parsed.
**Signature:** **Signature:**
```tomo ```tomo
@ -539,7 +539,7 @@ func parse(text: Text, format: Text = "%Y-%m-%dT%H:%M:%S%z" -> Moment?)
**Returns:** **Returns:**
If the text was successfully parsed according to the given format, return a If the text was successfully parsed according to the given format, return a
`Moment` representing that information. Otherwise, return `NULL`. `Moment` representing that information. Otherwise, return `NONE`.
**Example:** **Example:**
```tomo ```tomo

View File

@ -583,7 +583,7 @@ func parse(text: Text -> Num?)
- `text`: The text containing the number. - `text`: The text containing the number.
**Returns:** **Returns:**
The number represented by the text or `NULL` if the entire text can't be parsed The number represented by the text or `NONE` if the entire text can't be parsed
as a number. as a number.
**Example:** **Example:**

View File

@ -63,7 +63,7 @@ x = !Int
## Type Inference ## Type Inference
For convenience, null values can also be written as `NULL` for any type in For convenience, null values can also be written as `NONE` for any type in
situations where the compiler knows what type of optional value is expected: situations where the compiler knows what type of optional value is expected:
- When assigning to a variable that has already been declared as optional. - When assigning to a variable that has already been declared as optional.
@ -74,12 +74,12 @@ Here are some examples:
```tomo ```tomo
x := 5? x := 5?
x = NULL x = NONE
func doop(arg:Int?)->Text?: func doop(arg:Int?)->Text?:
return NULL return NONE
doop(NULL) doop(NONE)
``` ```
Non-null values can also be automatically promoted to optional values without Non-null values can also be automatically promoted to optional values without

View File

@ -495,7 +495,7 @@ raised.
= "Hello" : Text? = "Hello" : Text?
>> (./nosuchfile.xxx):read() >> (./nosuchfile.xxx):read()
= NULL : Text? = NONE : Text?
``` ```
--- ---
@ -524,7 +524,7 @@ returned.
= [72[B], 101[B], 108[B], 108[B], 111[B]] : [Byte]? = [72[B], 101[B], 108[B], 108[B], 111[B]] : [Byte]?
>> (./nosuchfile.xxx):read() >> (./nosuchfile.xxx):read()
= NULL : [Byte]? = NONE : [Byte]?
``` ```
--- ---

View File

@ -22,7 +22,7 @@ nums := [:Int]
sum := (+: nums) sum := (+: nums)
>> sum >> sum
= NULL : Int? = NONE : Int?
>> sum or 0 >> sum or 0
= 0 = 0

View File

@ -50,7 +50,7 @@ was found or error if it wasn't:
>> t:get("x") >> t:get("x")
= 1 : Int? = 1 : Int?
>> t:get("????") >> t:get("????")
= NULL : Int? = NONE : Int?
>> t:get("x")! >> t:get("x")!
= 1 = 1
``` ```
@ -190,7 +190,7 @@ The value associated with the key or null if the key is not found.
= 1 : Int? = 1 : Int?
>> t:get("????") >> t:get("????")
= NULL : Int? = NONE : Int?
>> t:get("A")! >> t:get("A")!
= 1 : Int = 1 : Int

View File

@ -3,7 +3,7 @@
`Text` is Tomo's datatype to represent text. The name `Text` is used instead of `Text` is Tomo's datatype to represent text. The name `Text` is used instead of
"string" because Tomo text represents immutable, normalized unicode data with "string" because Tomo text represents immutable, normalized unicode data with
fast indexing that has an implementation that is efficient for concatenation. fast indexing that has an implementation that is efficient for concatenation.
These are _not_ C-style NULL-terminated character arrays. GNU libunistring is These are _not_ C-style NUL-terminated character arrays. GNU libunistring is
used for full Unicode functionality (grapheme cluster counts, capitalization, used for full Unicode functionality (grapheme cluster counts, capitalization,
etc.). etc.).
@ -695,9 +695,9 @@ containing information about the match.
**Example:** **Example:**
```tomo ```tomo
>> " #one #two #three ":find($/#{id}/, start=-999) >> " #one #two #three ":find($/#{id}/, start=-999)
= NULL : Match? = NONE : Match?
>> " #one #two #three ":find($/#{id}/, start=999) >> " #one #two #three ":find($/#{id}/, start=999)
= NULL : Match? = NONE : Match?
>> " #one #two #three ":find($/#{id}/) >> " #one #two #three ":find($/#{id}/)
= Match(text="#one", index=2, captures=["one"]) : Match? = Match(text="#one", index=2, captures=["one"]) : Match?
>> " #one #two #three ":find("{id}", start=6) >> " #one #two #three ":find("{id}", start=6)
@ -887,7 +887,7 @@ or a null value otherwise.
**Example:** **Example:**
```tomo ```tomo
>> "hello world":matches($/{id}/) >> "hello world":matches($/{id}/)
= NULL : [Text]? = NONE : [Text]?
>> "hello world":matches($/{id} {id}/) >> "hello world":matches($/{id} {id}/)
= ["hello", "world"] : [Text]? = ["hello", "world"] : [Text]?

View File

@ -53,7 +53,7 @@ int op_tightness[] = {
static const char *keywords[] = { static const char *keywords[] = {
"yes", "xor", "while", "when", "use", "unless", "struct", "stop", "skip", "return", "yes", "xor", "while", "when", "use", "unless", "struct", "stop", "skip", "return",
"or", "not", "no", "mod1", "mod", "pass", "lang", "inline", "in", "if", "or", "not", "no", "mod1", "mod", "pass", "lang", "inline", "in", "if",
"func", "for", "extern", "enum", "else", "do", "defer", "and", "_min_", "_max_", "func", "for", "extern", "enum", "else", "do", "defer", "and", "NONE", "_min_", "_max_",
NULL, NULL,
}; };
@ -1532,7 +1532,7 @@ PARSER(parse_lambda) {
PARSER(parse_null) { PARSER(parse_null) {
const char *start = pos; const char *start = pos;
if (match_word(&pos, "NULL")) if (match_word(&pos, "NONE"))
return NewAST(ctx->file, start, pos, Null, .type=NULL); return NewAST(ctx->file, start, pos, Null, .type=NULL);
if (!match(&pos, "!")) return NULL; if (!match(&pos, "!")) return NULL;
type_ast_t *type = parse_type(ctx, pos); type_ast_t *type = parse_type(ctx, pos);

View File

@ -222,7 +222,7 @@ public Int_t Array$find(Array_t arr, void *item, const TypeInfo_t *type)
if (generic_equal(item, arr.data + i*arr.stride, item_type)) if (generic_equal(item, arr.data + i*arr.stride, item_type))
return I(i+1); return I(i+1);
} }
return NULL_INT; return NONE_INT;
} }
public Int_t Array$first(Array_t arr, Closure_t predicate) public Int_t Array$first(Array_t arr, Closure_t predicate)
@ -232,7 +232,7 @@ public Int_t Array$first(Array_t arr, Closure_t predicate)
if (is_good(arr.data + i*arr.stride, predicate.userdata)) if (is_good(arr.data + i*arr.stride, predicate.userdata))
return I(i+1); return I(i+1);
} }
return NULL_INT; return NONE_INT;
} }
public void Array$sort(Array_t *arr, Closure_t comparison, int64_t padded_item_size) public void Array$sort(Array_t *arr, Closure_t comparison, int64_t padded_item_size)

View File

@ -35,7 +35,7 @@ PUREFUNC public OptionalBool_t Bool$parse(Text_t text)
|| Text$equal_ignoring_case(text, Text("0"))) { || Text$equal_ignoring_case(text, Text("0"))) {
return no; return no;
} else { } else {
return NULL_BOOL; return NONE_BOOL;
} }
} }

View File

@ -35,6 +35,6 @@ typedef struct {
bool is_null:1; bool is_null:1;
} OptionalByte_t; } OptionalByte_t;
#define NULL_BYTE ((OptionalByte_t){.is_null=true}) #define NONE_BYTE ((OptionalByte_t){.is_null=true})
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0

View File

@ -303,7 +303,7 @@ public Int_t Int$power(Int_t base, Int_t exponent)
public OptionalInt_t Int$sqrt(Int_t i) public OptionalInt_t Int$sqrt(Int_t i)
{ {
if (Int$compare_value(i, I(0)) < 0) if (Int$compare_value(i, I(0)) < 0)
return NULL_INT; return NONE_INT;
mpz_t result; mpz_t result;
mpz_init_set_int(result, i); mpz_init_set_int(result, i);
mpz_sqrt(result, result); mpz_sqrt(result, result);
@ -327,7 +327,7 @@ public Int_t Int$from_str(const char *str) {
result = mpz_init_set_str(i, str, 10); result = mpz_init_set_str(i, str, 10);
} }
if (result != 0) if (result != 0)
return NULL_INT; return NONE_INT;
return Int$from_mpz(i); return Int$from_mpz(i);
} }

View File

@ -79,10 +79,10 @@ DEFINE_INT_TYPE(int16_t, Int16, CONSTFUNC)
DEFINE_INT_TYPE(int8_t, Int8, CONSTFUNC) DEFINE_INT_TYPE(int8_t, Int8, CONSTFUNC)
#undef DEFINE_INT_TYPE #undef DEFINE_INT_TYPE
#define NULL_INT64 ((OptionalInt64_t){.is_null=true}) #define NONE_INT64 ((OptionalInt64_t){.is_null=true})
#define NULL_INT32 ((OptionalInt32_t){.is_null=true}) #define NONE_INT32 ((OptionalInt32_t){.is_null=true})
#define NULL_INT16 ((OptionalInt16_t){.is_null=true}) #define NONE_INT16 ((OptionalInt16_t){.is_null=true})
#define NULL_INT8 ((OptionalInt8_t){.is_null=true}) #define NONE_INT8 ((OptionalInt8_t){.is_null=true})
#define Int64$abs(...) I64(labs(__VA_ARGS__)) #define Int64$abs(...) I64(labs(__VA_ARGS__))
#define Int32$abs(...) I32(abs(__VA_ARGS__)) #define Int32$abs(...) I32(abs(__VA_ARGS__))

View File

@ -14,7 +14,7 @@
#include "text.h" #include "text.h"
#include "util.h" #include "util.h"
static OptionalText_t _local_timezone = NULL_TEXT; static OptionalText_t _local_timezone = NONE_TEXT;
#define WITH_TIMEZONE(tz, body) ({ if (tz.length >= 0) { \ #define WITH_TIMEZONE(tz, body) ({ if (tz.length >= 0) { \
OptionalText_t old_timezone = _local_timezone; \ OptionalText_t old_timezone = _local_timezone; \
@ -220,7 +220,7 @@ public OptionalMoment_t Moment$parse(Text_t text, Text_t format)
char *invalid = strptime(str, fmt, &info); char *invalid = strptime(str, fmt, &info);
if (!invalid || invalid[0] != '\0') if (!invalid || invalid[0] != '\0')
return NULL_MOMENT; return NONE_MOMENT;
long offset = info.tm_gmtoff; // Need to cache this because mktime() mutates it to local timezone >:( long offset = info.tm_gmtoff; // Need to cache this because mktime() mutates it to local timezone >:(
time_t t = mktime(&info); time_t t = mktime(&info);

View File

@ -18,7 +18,7 @@ public PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_typ
if (non_optional_type == &Int$info) if (non_optional_type == &Int$info)
return ((Int_t*)obj)->small == 0; return ((Int_t*)obj)->small == 0;
else if (non_optional_type == &Bool$info) else if (non_optional_type == &Bool$info)
return *((OptionalBool_t*)obj) == NULL_BOOL; return *((OptionalBool_t*)obj) == NONE_BOOL;
else if (non_optional_type == &Num$info) else if (non_optional_type == &Num$info)
return isnan(*((Num_t*)obj)); return isnan(*((Num_t*)obj));
else if (non_optional_type == &Num32$info) else if (non_optional_type == &Num32$info)
@ -72,7 +72,7 @@ public Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t
return Text$concat(generic_as_text(obj, colorize, type->OptionalInfo.type), Text("?")); return Text$concat(generic_as_text(obj, colorize, type->OptionalInfo.type), Text("?"));
if (is_null(obj, type->OptionalInfo.type)) if (is_null(obj, type->OptionalInfo.type))
return colorize ? Text("\x1b[31mNULL\x1b[m") : Text("NULL"); return colorize ? Text("\x1b[31mNONE\x1b[m") : Text("NONE");
return generic_as_text(obj, colorize, type->OptionalInfo.type); return generic_as_text(obj, colorize, type->OptionalInfo.type);
} }

View File

@ -16,13 +16,13 @@
#define OptionalText_t Text_t #define OptionalText_t Text_t
#define OptionalClosure_t Closure_t #define OptionalClosure_t Closure_t
#define NULL_ARRAY ((Array_t){.length=-1}) #define NONE_ARRAY ((Array_t){.length=-1})
#define NULL_BOOL ((OptionalBool_t)2) #define NONE_BOOL ((OptionalBool_t)2)
#define NULL_INT ((OptionalInt_t){.small=0}) #define NONE_INT ((OptionalInt_t){.small=0})
#define NULL_TABLE ((OptionalTable_t){.entries.length=-1}) #define NONE_TABLE ((OptionalTable_t){.entries.length=-1})
#define NULL_CLOSURE ((OptionalClosure_t){.fn=NULL}) #define NONE_CLOSURE ((OptionalClosure_t){.fn=NULL})
#define NULL_TEXT ((OptionalText_t){.length=-1}) #define NONE_TEXT ((OptionalText_t){.length=-1})
#define NULL_MOMENT ((OptionalMoment_t){.tv_usec=-1}) #define NONE_MOMENT ((OptionalMoment_t){.tv_usec=-1})
PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_type); PUREFUNC bool is_null(const void *obj, const TypeInfo_t *non_optional_type);
Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type); Text_t Optional$as_text(const void *obj, bool colorize, const TypeInfo_t *type);

View File

@ -209,7 +209,7 @@ public OptionalMoment_t Path$modified(Path_t path, bool follow_symlinks)
{ {
struct stat sb; struct stat sb;
int status = path_stat(path, follow_symlinks, &sb); int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return NULL_MOMENT; if (status != 0) return NONE_MOMENT;
return (Moment_t){.tv_sec=sb.st_mtime}; return (Moment_t){.tv_sec=sb.st_mtime};
} }
@ -217,7 +217,7 @@ public OptionalMoment_t Path$accessed(Path_t path, bool follow_symlinks)
{ {
struct stat sb; struct stat sb;
int status = path_stat(path, follow_symlinks, &sb); int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return NULL_MOMENT; if (status != 0) return NONE_MOMENT;
return (Moment_t){.tv_sec=sb.st_atime}; return (Moment_t){.tv_sec=sb.st_atime};
} }
@ -225,7 +225,7 @@ public OptionalMoment_t Path$changed(Path_t path, bool follow_symlinks)
{ {
struct stat sb; struct stat sb;
int status = path_stat(path, follow_symlinks, &sb); int status = path_stat(path, follow_symlinks, &sb);
if (status != 0) return NULL_MOMENT; if (status != 0) return NONE_MOMENT;
return (Moment_t){.tv_sec=sb.st_ctime}; return (Moment_t){.tv_sec=sb.st_ctime};
} }
@ -271,11 +271,11 @@ public OptionalArray_t Path$read_bytes(Path_t path, OptionalInt_t count)
path = Path$_expand_home(path); path = Path$_expand_home(path);
int fd = open(Text$as_c_string(path), O_RDONLY); int fd = open(Text$as_c_string(path), O_RDONLY);
if (fd == -1) if (fd == -1)
return NULL_ARRAY; return NONE_ARRAY;
struct stat sb; struct stat sb;
if (fstat(fd, &sb) != 0) if (fstat(fd, &sb) != 0)
return NULL_ARRAY; return NONE_ARRAY;
int64_t const target_count = count.small ? Int_to_Int64(count, false) : INT64_MAX; int64_t const target_count = count.small ? Int_to_Int64(count, false) : INT64_MAX;
if (target_count < 0) if (target_count < 0)
@ -301,7 +301,7 @@ public OptionalArray_t Path$read_bytes(Path_t path, OptionalInt_t count)
ssize_t just_read = read(fd, chunk, to_read); ssize_t just_read = read(fd, chunk, to_read);
if (just_read < 0) { if (just_read < 0) {
close(fd); close(fd);
return NULL_ARRAY; return NONE_ARRAY;
} else if (just_read == 0) { } else if (just_read == 0) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
continue; continue;
@ -325,8 +325,8 @@ public OptionalArray_t Path$read_bytes(Path_t path, OptionalInt_t count)
public OptionalText_t Path$read(Path_t path) public OptionalText_t Path$read(Path_t path)
{ {
Array_t bytes = Path$read_bytes(path, NULL_INT); Array_t bytes = Path$read_bytes(path, NONE_INT);
if (bytes.length < 0) return NULL_TEXT; if (bytes.length < 0) return NONE_TEXT;
return Text$from_bytes(bytes); return Text$from_bytes(bytes);
} }
@ -511,14 +511,14 @@ static void _line_reader_cleanup(FILE **f)
static Text_t _next_line(FILE **f) static Text_t _next_line(FILE **f)
{ {
if (!f || !*f) return NULL_TEXT; if (!f || !*f) return NONE_TEXT;
char *line = NULL; char *line = NULL;
size_t size = 0; size_t size = 0;
ssize_t len = getline(&line, &size, *f); ssize_t len = getline(&line, &size, *f);
if (len <= 0) { if (len <= 0) {
_line_reader_cleanup(f); _line_reader_cleanup(f);
return NULL_TEXT; return NONE_TEXT;
} }
while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n')) while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n'))
@ -538,7 +538,7 @@ public OptionalClosure_t Path$by_line(Path_t path)
FILE *f = fopen(Text$as_c_string(path), "r"); FILE *f = fopen(Text$as_c_string(path), "r");
if (f == NULL) if (f == NULL)
return NULL_CLOSURE; return NONE_CLOSURE;
FILE **wrapper = GC_MALLOC(sizeof(FILE*)); FILE **wrapper = GC_MALLOC(sizeof(FILE*));
*wrapper = f; *wrapper = f;

View File

@ -802,13 +802,13 @@ public OptionalMatch_t Text$find(Text_t text, Pattern_t pattern, Int_t from_inde
if (first == 0) fail("Invalid index: 0"); if (first == 0) fail("Invalid index: 0");
if (first < 0) first = text.length + first + 1; if (first < 0) first = text.length + first + 1;
if (first > text.length || first < 1) if (first > text.length || first < 1)
return NULL_MATCH; return NONE_MATCH;
capture_t captures[MAX_BACKREFS] = {}; capture_t captures[MAX_BACKREFS] = {};
int64_t len = 0; int64_t len = 0;
int64_t found = _find(text, pattern, first-1, text.length-1, &len, captures); int64_t found = _find(text, pattern, first-1, text.length-1, &len, captures);
if (found == -1) if (found == -1)
return NULL_MATCH; return NONE_MATCH;
Array_t capture_array = {}; Array_t capture_array = {};
for (int i = 0; captures[i].occupied; i++) { for (int i = 0; captures[i].occupied; i++) {
@ -845,7 +845,7 @@ public OptionalArray_t Text$matches(Text_t text, Pattern_t pattern)
capture_t captures[MAX_BACKREFS] = {}; capture_t captures[MAX_BACKREFS] = {};
int64_t match_len = match(text, 0, pattern, 0, captures, 0); int64_t match_len = match(text, 0, pattern, 0, captures, 0);
if (match_len != text.length) if (match_len != text.length)
return NULL_ARRAY; return NONE_ARRAY;
Array_t capture_array = {}; Array_t capture_array = {};
for (int i = 0; captures[i].occupied; i++) { for (int i = 0; captures[i].occupied; i++) {

View File

@ -21,7 +21,7 @@ typedef struct {
} Match_t; } Match_t;
typedef Match_t OptionalMatch_t; typedef Match_t OptionalMatch_t;
#define NULL_MATCH ((OptionalMatch_t){.index=NULL_INT}) #define NONE_MATCH ((OptionalMatch_t){.index=NONE_INT})
Text_t Text$replace(Text_t str, Pattern_t pat, Text_t replacement, Pattern_t backref_pat, bool recursive); Text_t Text$replace(Text_t str, Pattern_t pat, Text_t replacement, Pattern_t backref_pat, bool recursive);
Pattern_t Pattern$escape_text(Text_t text); Pattern_t Pattern$escape_text(Text_t text);

View File

@ -50,7 +50,7 @@ public OptionalArray_t Shell$run_bytes(Shell_t command)
const char *cmd_str = Text$as_c_string(command); const char *cmd_str = Text$as_c_string(command);
FILE *prog = popen(cmd_str, "r"); FILE *prog = popen(cmd_str, "r");
if (!prog) if (!prog)
return NULL_ARRAY; return NONE_ARRAY;
size_t capacity = 256, len = 0; size_t capacity = 256, len = 0;
char *content = GC_MALLOC_ATOMIC(capacity); char *content = GC_MALLOC_ATOMIC(capacity);
@ -73,7 +73,7 @@ public OptionalArray_t Shell$run_bytes(Shell_t command)
int status = pclose(prog); int status = pclose(prog);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
return NULL_ARRAY; return NONE_ARRAY;
return (Array_t){.data=content, .atomic=1, .stride=1, .length=len}; return (Array_t){.data=content, .atomic=1, .stride=1, .length=len};
} }
@ -82,7 +82,7 @@ public OptionalText_t Shell$run(Shell_t command)
{ {
Array_t bytes = Shell$run_bytes(command); Array_t bytes = Shell$run_bytes(command);
if (bytes.length < 0) if (bytes.length < 0)
return NULL_TEXT; return NONE_TEXT;
if (bytes.length > 0 && *(char*)(bytes.data + (bytes.length-1)*bytes.stride) == '\n') { if (bytes.length > 0 && *(char*)(bytes.data + (bytes.length-1)*bytes.stride) == '\n') {
--bytes.length; --bytes.length;
@ -102,14 +102,14 @@ static void _line_reader_cleanup(FILE **f)
static Text_t _next_line(FILE **f) static Text_t _next_line(FILE **f)
{ {
if (!f || !*f) return NULL_TEXT; if (!f || !*f) return NONE_TEXT;
char *line = NULL; char *line = NULL;
size_t size = 0; size_t size = 0;
ssize_t len = getline(&line, &size, *f); ssize_t len = getline(&line, &size, *f);
if (len <= 0) { if (len <= 0) {
_line_reader_cleanup(f); _line_reader_cleanup(f);
return NULL_TEXT; return NONE_TEXT;
} }
while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n')) while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n'))
@ -128,7 +128,7 @@ public OptionalClosure_t Shell$by_line(Shell_t command)
const char *cmd_str = Text$as_c_string(command); const char *cmd_str = Text$as_c_string(command);
FILE *prog = popen(cmd_str, "r"); FILE *prog = popen(cmd_str, "r");
if (!prog) if (!prog)
return NULL_CLOSURE; return NONE_CLOSURE;
FILE **wrapper = GC_MALLOC(sizeof(FILE*)); FILE **wrapper = GC_MALLOC(sizeof(FILE*));
*wrapper = prog; *wrapper = prog;

View File

@ -96,9 +96,9 @@ static bool parse_single_arg(const TypeInfo_t *info, char *arg, void *dest)
return !parsed.is_null; return !parsed.is_null;
} else if (info == &Bool$info) { } else if (info == &Bool$info) {
OptionalBool_t parsed = Bool$parse(Text$from_str(arg)); OptionalBool_t parsed = Bool$parse(Text$from_str(arg));
if (parsed != NULL_BOOL) if (parsed != NONE_BOOL)
*(OptionalBool_t*)dest = parsed; *(OptionalBool_t*)dest = parsed;
return parsed != NULL_BOOL; return parsed != NONE_BOOL;
} else if (info == &Num$info) { } else if (info == &Num$info) {
OptionalNum_t parsed = Num$parse(Text$from_str(arg)); OptionalNum_t parsed = Num$parse(Text$from_str(arg));
if (!isnan(parsed)) if (!isnan(parsed))

View File

@ -678,7 +678,7 @@ public OptionalText_t Text$from_strn(const char *str, size_t len)
return ret; return ret;
} else { } else {
if (u8_check((uint8_t*)str, len) != NULL) if (u8_check((uint8_t*)str, len) != NULL)
return NULL_TEXT; return NONE_TEXT;
ucs4_t buf[128]; ucs4_t buf[128];
size_t length = sizeof(buf)/sizeof(buf[0]); size_t length = sizeof(buf)/sizeof(buf[0]);
@ -1330,7 +1330,7 @@ public OptionalText_t Text$from_codepoint_names(Array_t codepoint_names)
const char *name_str = Text$as_c_string(*name); const char *name_str = Text$as_c_string(*name);
ucs4_t codepoint = unicode_name_character(name_str); ucs4_t codepoint = unicode_name_character(name_str);
if (codepoint == UNINAME_INVALID) if (codepoint == UNINAME_INVALID)
return NULL_TEXT; return NONE_TEXT;
Array$insert(&codepoints, &codepoint, I_small(0), sizeof(ucs4_t)); Array$insert(&codepoints, &codepoint, I_small(0), sizeof(ucs4_t));
} }
return Text$from_codepoints(codepoints); return Text$from_codepoints(codepoints);

View File

@ -166,9 +166,9 @@ func main():
>> ["a", "b", "c"]:find("b") >> ["a", "b", "c"]:find("b")
= 2 : Int? = 2 : Int?
>> ["a", "b", "c"]:find("XXX") >> ["a", "b", "c"]:find("XXX")
= NULL : Int? = NONE : Int?
>> [10, 20]:first(func(i:&Int): i:is_prime()) >> [10, 20]:first(func(i:&Int): i:is_prime())
= NULL : Int? = NONE : Int?
>> [4, 5, 6]:first(func(i:&Int): i:is_prime()) >> [4, 5, 6]:first(func(i:&Int): i:is_prime())
= 2 : Int? = 2 : Int?

View File

@ -23,9 +23,9 @@ func main():
= yes = yes
>> Num.NAN >> Num.NAN
= NULL : Num? = NONE : Num?
>> nan := Num.NAN >> nan := Num.NAN
= NULL : Num? = NONE : Num?
>> nan == nan >> nan == nan
= yes = yes
>> nan < nan >> nan < nan
@ -48,10 +48,10 @@ func main():
= -1 = -1
>> nan + 1 >> nan + 1
= NULL : Num? = NONE : Num?
>> 0./0. >> 0./0.
= NULL : Num? = NONE : Num?
>> Num.PI:cos()!:near(-1) >> Num.PI:cos()!:near(-1)
= yes = yes

View File

@ -4,7 +4,7 @@ struct Struct(x:Int, y:Text):
if should_i: if should_i:
return Struct(123, "hello") return Struct(123, "hello")
else: else:
return NULL return NONE
enum Enum(X, Y(y:Int)): enum Enum(X, Y(y:Int)):
func maybe(should_i:Bool->Enum?): func maybe(should_i:Bool->Enum?):
@ -100,7 +100,7 @@ func main():
>> yep := maybe_int(yes) >> yep := maybe_int(yes)
= 123 : Int? = 123 : Int?
>> nope := maybe_int(no) >> nope := maybe_int(no)
= NULL : Int? = NONE : Int?
>> if yep: >> if yep:
>> yep >> yep
= 123 = 123
@ -115,7 +115,7 @@ func main():
>> yep := maybe_int64(yes) >> yep := maybe_int64(yes)
= 123 : Int64? = 123 : Int64?
>> nope := maybe_int64(no) >> nope := maybe_int64(no)
= NULL : Int64? = NONE : Int64?
>> if yep: >> if yep:
>> yep >> yep
= 123 = 123
@ -130,7 +130,7 @@ func main():
>> yep := maybe_array(yes) >> yep := maybe_array(yes)
= [10, 20, 30] : [Int]? = [10, 20, 30] : [Int]?
>> nope := maybe_array(no) >> nope := maybe_array(no)
= NULL : [Int]? = NONE : [Int]?
>> if yep: >> if yep:
>> yep >> yep
= [10, 20, 30] = [10, 20, 30]
@ -145,7 +145,7 @@ func main():
>> yep := maybe_bool(yes) >> yep := maybe_bool(yes)
= no : Bool? = no : Bool?
>> nope := maybe_bool(no) >> nope := maybe_bool(no)
= NULL : Bool? = NONE : Bool?
>> if yep: >> if yep:
>> yep >> yep
= no = no
@ -160,7 +160,7 @@ func main():
>> yep := maybe_text(yes) >> yep := maybe_text(yes)
= "Hello" : Text? = "Hello" : Text?
>> nope := maybe_text(no) >> nope := maybe_text(no)
= NULL : Text? = NONE : Text?
>> if yep: >> if yep:
>> yep >> yep
= "Hello" = "Hello"
@ -175,7 +175,7 @@ func main():
>> yep := maybe_num(yes) >> yep := maybe_num(yes)
= 12.3 : Num? = 12.3 : Num?
>> nope := maybe_num(no) >> nope := maybe_num(no)
= NULL : Num? = NONE : Num?
>> if yep: >> if yep:
>> yep >> yep
= 12.3 = 12.3
@ -190,7 +190,7 @@ func main():
>> yep := maybe_lambda(yes) >> yep := maybe_lambda(yes)
= func() [optionals.tm:54] : func()? = func() [optionals.tm:54] : func()?
>> nope := maybe_lambda(no) >> nope := maybe_lambda(no)
= NULL : func()? = NONE : func()?
>> if yep: >> if yep:
>> yep >> yep
= func() [optionals.tm:54] = func() [optionals.tm:54]
@ -205,7 +205,7 @@ func main():
>> yep := Struct.maybe(yes) >> yep := Struct.maybe(yes)
= Struct(x=123, y="hello") : Struct? = Struct(x=123, y="hello") : Struct?
>> nope := Struct.maybe(no) >> nope := Struct.maybe(no)
= NULL : Struct? = NONE : Struct?
>> if yep: >> if yep:
>> yep >> yep
= Struct(x=123, y="hello") = Struct(x=123, y="hello")
@ -220,7 +220,7 @@ func main():
>> yep := Enum.maybe(yes) >> yep := Enum.maybe(yes)
= Enum.Y(123) : Enum? = Enum.Y(123) : Enum?
>> nope := Enum.maybe(no) >> nope := Enum.maybe(no)
= NULL : Enum? = NONE : Enum?
>> if yep: >> if yep:
>> yep >> yep
= Enum.Y(123) = Enum.Y(123)
@ -235,7 +235,7 @@ func main():
>> yep := maybe_c_string(yes) >> yep := maybe_c_string(yes)
= CString("hi") : CString? = CString("hi") : CString?
>> nope := maybe_c_string(no) >> nope := maybe_c_string(no)
= NULL : CString? = NONE : CString?
>> if yep: >> if yep:
>> yep >> yep
= CString("hi") = CString("hi")
@ -250,7 +250,7 @@ func main():
>> yep := maybe_channel(yes) >> yep := maybe_channel(yes)
# No "=" test here because channels use addresses in the text version # No "=" test here because channels use addresses in the text version
>> nope := maybe_channel(no) >> nope := maybe_channel(no)
= NULL : |:Int|? = NONE : |:Int|?
>> if yep: >> yep >> if yep: >> yep
else: fail("Falsey: $yep") else: fail("Falsey: $yep")
>> if nope: >> if nope:
@ -263,7 +263,7 @@ func main():
>> yep := maybe_thread(yes) >> yep := maybe_thread(yes)
# No "=" test here because threads use addresses in the text version # No "=" test here because threads use addresses in the text version
>> nope := maybe_thread(no) >> nope := maybe_thread(no)
= NULL : Thread? = NONE : Thread?
>> if yep: >> yep >> if yep: >> yep
else: fail("Falsey: $yep") else: fail("Falsey: $yep")
>> if nope: >> if nope:
@ -284,9 +284,9 @@ func main():
>> (5? == 5?) >> (5? == 5?)
= yes = yes
>> {!Int, !Int} >> {!Int, !Int}
= {NULL} = {NONE}
>> [5?, !Int, !Int, 6?]:sorted() >> [5?, !Int, !Int, 6?]:sorted()
= [NULL, NULL, 5, 6] = [NONE, NONE, 5, 6]
do: do:
>> value := if var := 5?: >> value := if var := 5?:

View File

@ -36,9 +36,9 @@ func main():
fail("Couldn't read lines in $tmpfile") fail("Couldn't read lines in $tmpfile")
>> (./does-not-exist.xxx):read() >> (./does-not-exist.xxx):read()
= NULL : Text? = NONE : Text?
>> (./does-not-exist.xxx):read_bytes() >> (./does-not-exist.xxx):read_bytes()
= NULL : [Byte]? = NONE : [Byte]?
if lines := (./does-not-exist.xxx):by_line(): if lines := (./does-not-exist.xxx):by_line():
fail("I could read lines in a nonexistent file") fail("I could read lines in a nonexistent file")
else: else:

View File

@ -5,7 +5,7 @@ func main():
= 60 : Int? = 60 : Int?
>> (+: [:Int]) >> (+: [:Int])
= NULL : Int? = NONE : Int?
>> (+: [10, 20, 30]) or 0 >> (+: [10, 20, 30]) or 0
= 60 = 60
@ -37,7 +37,7 @@ func main():
= yes = yes
>> (<=: [:Int]) >> (<=: [:Int])
= NULL : Bool? = NONE : Bool?
>> (<=: [5, 4, 3, 2, 1])! >> (<=: [5, 4, 3, 2, 1])!
= no = no

View File

@ -7,7 +7,7 @@ func main():
>> t:get("two") >> t:get("two")
= 2 : Int? = 2 : Int?
>> t:get("???") >> t:get("???")
= NULL : Int? = NONE : Int?
>> t:get("one")! >> t:get("one")!
= 1 = 1
>> t:get("???") or -1 >> t:get("???") or -1
@ -22,7 +22,7 @@ func main():
>> t.length >> t.length
= 2 = 2
>> t.fallback >> t.fallback
= NULL : {Text:Int}? = NONE : {Text:Int}?
>> t.keys >> t.keys
= ["one", "two"] = ["one", "two"]
@ -37,7 +37,7 @@ func main():
>> t2:get("three") >> t2:get("three")
= 3 : Int? = 3 : Int?
>> t2:get("???") >> t2:get("???")
= NULL : Int? = NONE : Int?
>> t2.length >> t2.length
= 1 = 1

View File

@ -35,7 +35,7 @@ func main():
>> Text.from_bytes([:Byte 0x41, 0x6D, 0xC3, 0xA9, 0x6C, 0x69, 0x65])! >> Text.from_bytes([:Byte 0x41, 0x6D, 0xC3, 0xA9, 0x6C, 0x69, 0x65])!
= "Amélie" = "Amélie"
>> Text.from_bytes([Byte(0xFF)]) >> Text.from_bytes([Byte(0xFF)])
= NULL : Text? = NONE : Text?
>> amelie2 := "Am$(\U65\U301)lie" >> amelie2 := "Am$(\U65\U301)lie"
>> amelie2:split() >> amelie2:split()
@ -189,9 +189,9 @@ func main():
!! Test text:find() !! Test text:find()
>> " one two three ":find($/{id}/, start=-999) >> " one two three ":find($/{id}/, start=-999)
= NULL : Match? = NONE : Match?
>> " one two three ":find($/{id}/, start=999) >> " one two three ":find($/{id}/, start=999)
= NULL : Match? = NONE : Match?
>> " one two three ":find($/{id}/) >> " one two three ":find($/{id}/)
= Match(text="one", index=2, captures=["one"]) : Match? = Match(text="one", index=2, captures=["one"]) : Match?
>> " one two three ":find($/{id}/, start=5) >> " one two three ":find($/{id}/, start=5)
@ -222,7 +222,7 @@ func main():
= ["PENGUIN"] = ["PENGUIN"]
>> Text.from_codepoint_names(["not a valid name here buddy"]) >> Text.from_codepoint_names(["not a valid name here buddy"])
= NULL : Text? = NONE : Text?
>> "one two; three four":find_all($/; {..}/) >> "one two; three four":find_all($/; {..}/)
= [Match(text="; three four", index=8, captures=["three four"])] = [Match(text="; three four", index=8, captures=["three four"])]
@ -249,11 +249,11 @@ func main():
>> "Hello":matches($/{id}/) >> "Hello":matches($/{id}/)
= ["Hello"] : [Text]? = ["Hello"] : [Text]?
>> "Hello":matches($/{lower}/) >> "Hello":matches($/{lower}/)
= NULL : [Text]? = NONE : [Text]?
>> "Hello":matches($/{upper}/) >> "Hello":matches($/{upper}/)
= NULL : [Text]? = NONE : [Text]?
>> "Hello...":matches($/{id}/) >> "Hello...":matches($/{id}/)
= NULL : [Text]? = NONE : [Text]?
if matches := "hello world":matches($/{id} {id}/): if matches := "hello world":matches($/{id} {id}/):
>> matches >> matches

4
tomo.c
View File

@ -30,8 +30,8 @@
#define run_cmd(...) ({ const char *_cmd = heap_strf(__VA_ARGS__); if (verbose) puts(_cmd); popen(_cmd, "w"); }) #define run_cmd(...) ({ const char *_cmd = heap_strf(__VA_ARGS__); if (verbose) puts(_cmd); popen(_cmd, "w"); })
#define array_str(arr) Text$as_c_string(Text$join(Text(" "), arr)) #define array_str(arr) Text$as_c_string(Text$join(Text(" "), arr))
static OptionalArray_t files = NULL_ARRAY, static OptionalArray_t files = NONE_ARRAY,
args = NULL_ARRAY; args = NONE_ARRAY;
static OptionalBool_t verbose = false, static OptionalBool_t verbose = false,
show_codegen = false, show_codegen = false,
stop_at_transpile = false, stop_at_transpile = false,