diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-09-11 12:39:56 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-09-11 12:39:56 -0400 |
| commit | 30d39378c721aa6506c5aa038f6da9bf98cb1527 (patch) | |
| tree | 5051263c667915bfd9178bbfdf691afb54088e3f | |
| parent | 210179ee672a0c3799328a54e886f574b3823e3d (diff) | |
Optional C Strings
| -rw-r--r-- | builtins/c_string.c | 2 | ||||
| -rw-r--r-- | builtins/functions.c | 8 | ||||
| -rw-r--r-- | builtins/optionals.c | 5 | ||||
| -rw-r--r-- | builtins/types.h | 2 | ||||
| -rw-r--r-- | compile.c | 5 | ||||
| -rw-r--r-- | test/optionals.tm | 19 |
6 files changed, 31 insertions, 10 deletions
diff --git a/builtins/c_string.c b/builtins/c_string.c index 3e3ef740..c7c7a563 100644 --- a/builtins/c_string.c +++ b/builtins/c_string.c @@ -46,7 +46,7 @@ PUREFUNC public uint64_t CString$hash(const char **c_str) public const TypeInfo CString$info = { .size=sizeof(char*), .align=__alignof__(char*), - .tag=CustomInfo, + .tag=CStringInfo, .CustomInfo={.as_text=(void*)CString$as_text, .compare=(void*)CString$compare, .equal=(void*)CString$equal, .hash=(void*)CString$hash}, }; diff --git a/builtins/functions.c b/builtins/functions.c index ed0889d4..e506fe1c 100644 --- a/builtins/functions.c +++ b/builtins/functions.c @@ -118,7 +118,7 @@ PUREFUNC public uint64_t generic_hash(const void *obj, const TypeInfo *type) errx(1, "Optional hash not implemented"); } case EmptyStructInfo: return 0; - case CustomInfo: case StructInfo: case EnumInfo: // These all share the same info + case CustomInfo: case StructInfo: case EnumInfo: case CStringInfo: // These all share the same info if (!type->CustomInfo.hash) goto hash_data; return type->CustomInfo.hash(obj, type); @@ -143,7 +143,7 @@ PUREFUNC public int32_t generic_compare(const void *x, const void *y, const Type errx(1, "Optional compare not implemented"); } case EmptyStructInfo: return 0; - case CustomInfo: case StructInfo: case EnumInfo: // These all share the same info + case CustomInfo: case StructInfo: case EnumInfo: case CStringInfo: // These all share the same info if (!type->CustomInfo.compare) goto compare_data; return type->CustomInfo.compare(x, y, type); @@ -167,7 +167,7 @@ PUREFUNC public bool generic_equal(const void *x, const void *y, const TypeInfo case OptionalInfo: { errx(1, "Optional equal not implemented"); } - case CustomInfo: case StructInfo: case EnumInfo: // These all share the same info + case CustomInfo: case StructInfo: case EnumInfo: case CStringInfo: // These all share the same info if (!type->CustomInfo.equal) goto use_generic_compare; return type->CustomInfo.equal(x, y, type); @@ -191,7 +191,7 @@ public Text_t generic_as_text(const void *obj, bool colorize, const TypeInfo *ty case EmptyStructInfo: return colorize ? Text$concat(Text("\x1b[0;1m"), Text$from_str(type->EmptyStructInfo.name), Text("\x1b[m()")) : Text$concat(Text$from_str(type->EmptyStructInfo.name), Text("()")); - case CustomInfo: case StructInfo: case EnumInfo: // These all share the same info + case CustomInfo: case StructInfo: case EnumInfo: case CStringInfo: // These all share the same info if (!type->CustomInfo.as_text) fail("No text function provided for type!\n"); return type->CustomInfo.as_text(obj, colorize, type); diff --git a/builtins/optionals.c b/builtins/optionals.c index 88f08097..93fac2ed 100644 --- a/builtins/optionals.c +++ b/builtins/optionals.c @@ -42,9 +42,8 @@ static inline bool is_null(const void *obj, const TypeInfo *non_optional_type) offset += non_optional_type->align - (offset % non_optional_type->align); return *(bool*)(obj + offset); } - case EnumInfo: { - return (*(int*)obj) == 0; // NULL tag - } + case EnumInfo: return (*(int*)obj) == 0; // NULL tag + case CStringInfo: return (*(char**)obj) == NULL; default: { Text_t t = generic_as_text(NULL, false, non_optional_type); errx(1, "is_null() not implemented for: %k", &t); diff --git a/builtins/types.h b/builtins/types.h index 38d8bdc5..a7b4bb51 100644 --- a/builtins/types.h +++ b/builtins/types.h @@ -18,7 +18,7 @@ typedef struct TypeInfo { int64_t size, align; struct { // Anonymous tagged union for convenience enum { CustomInfo, StructInfo, EnumInfo, PointerInfo, TextInfo, ArrayInfo, ChannelInfo, TableInfo, FunctionInfo, - OptionalInfo, TypeInfoInfo, OpaqueInfo, EmptyStructInfo } tag; + OptionalInfo, TypeInfoInfo, OpaqueInfo, EmptyStructInfo, CStringInfo } tag; union { struct { equal_fn_t equal; @@ -328,7 +328,7 @@ static CORD compile_optional_check(env_t *env, ast_t *ast) { type_t *t = get_type(env, ast); t = Match(t, OptionalType)->type; - if (t->tag == PointerType || t->tag == FunctionType) + if (t->tag == PointerType || t->tag == FunctionType || t->tag == CStringType || t == THREAD_TYPE) return CORD_all("(", compile(env, ast), " != NULL)"); else if (t->tag == BigIntType) return CORD_all("((", compile(env, ast), ").small != 0)"); @@ -1688,6 +1688,8 @@ CORD compile(env_t *env, ast_t *ast) switch (ast->tag) { case Nil: { type_t *t = parse_type_ast(env, Match(ast, Nil)->type); + if (t == THREAD_TYPE) return "NULL"; + switch (t->tag) { case BigIntType: return "NULL_INT"; case IntType: { @@ -1705,6 +1707,7 @@ CORD compile(env_t *env, ast_t *ast) case TableType: return "NULL_TABLE"; case SetType: return "NULL_TABLE"; case TextType: return "NULL_TEXT"; + case CStringType: return "NULL"; case PointerType: return CORD_all("((", compile_type(t), ")NULL)"); case ClosureType: return "NULL_CLOSURE"; case NumType: return "nan(\"null\")"; diff --git a/test/optionals.tm b/test/optionals.tm index a721deaa..521bba51 100644 --- a/test/optionals.tm +++ b/test/optionals.tm @@ -49,6 +49,12 @@ func maybe_lambda(should_i:Bool)-> func()?: else: return !func() +func maybe_c_string(should_i:Bool)->CString?: + if should_i: + return ("hi":as_c_string())? + else: + return !CString + func main(): >> 5? = 5? : Int? @@ -162,6 +168,19 @@ func main(): fail("Truthy: $nope") else: !! Falsey: $nope + do: + !! ... + !! C Strings: + >> yep := maybe_c_string(yes) + = CString("hi")? + >> nope := maybe_c_string(no) + = !CString + >> if yep: >> yep + else: fail("Falsey: $yep") + >> if nope: + fail("Truthy: $nope") + else: !! Falsey: $nope + if yep := maybe_int(yes): >> yep = 123 : Int |
