Skip to content

Commit

Permalink
Get rid of nullable types
Browse files Browse the repository at this point in the history
  • Loading branch information
goodpaul6 committed Dec 15, 2024
1 parent be49d7f commit 7b4d038
Show file tree
Hide file tree
Showing 5 changed files with 9 additions and 122 deletions.
7 changes: 7 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# TODO

- IDEA Get rid of nullable types from the code and just implement it as a macro library? `use nullable("int") as nint` + `nint_unwrap` + `nint_or`
- Can store these in a single `Tiny_Value` anyways while we're tagging types
- This will work nicely with the `:` syntax proposed below

- IDEA Add optional `symbolPrefix` argument to `CompileString` which lets you prefix every symbol in the compiled file
- Allows you to prevent name collisions, makes composition via macros easier?

- IDEA Ok, rather than making `struct` non-gc, what if we had `tuple` as a non-gc alternative? It can still have named fields but it truly does
get passed around on the stack
- How does this interact with the C code? If you're passing a tuple as args, what do we do? I guess we pass it as N arguments (one for each field)
Expand Down
78 changes: 1 addition & 77 deletions test/src/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,53 +867,11 @@ static void test_Continue() {
Tiny_DeleteState(state);
}

static void test_ParseNullable() {
Tiny_State *state = CreateState();

const char *code =
"x : ?int = 10\n"
"func f(): ?int\n"
"{ return 10 }\n";

Tiny_CompileString(state, "(parse opt test)", code);

lok(true);

Tiny_DeleteState(state);
}

static void test_BindNullable() {
Tiny_State *state = CreateState();

Tiny_RegisterType(state, "Point");

Tiny_BindFunction(state, "f(?Point, ?int): ?int", Lib_Print);

lok(true);

Tiny_DeleteState(state);
}

static void test_CannotUseNullable() {
Tiny_State *state = CreateState();

const char *code =
"x : ?int = 10\n"
"func f(x: int) {}\n"
"f(x)\n";

Tiny_CompileResult result = Tiny_CompileString(state, "(cannot use nullable test)", code);

lequal(result.type, TINY_COMPILE_ERROR);

Tiny_DeleteState(state);
}

static void test_ParseFailureIsOkay() {
Tiny_State *state = CreateState();

const char *code =
"x : ?int = 10\n"
"x : int = 10\n"
"func fx: int) {}\n"
"f(x)\n";

Expand Down Expand Up @@ -949,33 +907,6 @@ static void test_AssignNullToAny() {
Tiny_DeleteState(state);
}

static void test_AssignValueToNullable() {
Tiny_State *state = CreateState();

const char *code = "x : ?int = 10\n";

Tiny_CompileResult result = Tiny_CompileString(state, "(can assign 10 to int?)", code);

lequal(result.type, TINY_COMPILE_SUCCESS);

Tiny_DeleteState(state);
}

static void test_CantAssignNullableToNonNullable() {
Tiny_State *state = CreateState();

const char *code =
"x: ?int = 10\n"
"y: int = x\n";

Tiny_CompileResult result =
Tiny_CompileString(state, "(can't assign nullable to non-nullable)", code);

lequal(result.type, TINY_COMPILE_ERROR);

Tiny_DeleteState(state);
}

static void test_DisasmOne() {
Tiny_State *state = CreateState();

Expand Down Expand Up @@ -1299,14 +1230,7 @@ int main(int argc, char *argv[]) {
lrun("Tiny Hex Literal", test_HexLiteral);
lrun("Tiny Break Statement", test_Break);
lrun("Tiny Continue Statement", test_Continue);
lrun("Tiny Parse Nullable Types", test_ParseNullable);
lrun("Tiny Bind Nullable Types in Fn", test_BindNullable);
lrun("Tiny Check Cannot Use Nullable", test_CannotUseNullable);
lrun("Tiny Parse Failure is Ok", test_ParseFailureIsOkay);
lrun("Tiny Cannot Assign Null to Non-Nullable", test_CannotAssignNull);
lrun("Tiny Can Assign Null to Any", test_AssignNullToAny);
lrun("Tiny Can Assign Value to Nullable", test_AssignValueToNullable);
lrun("Tiny Can't Assign Nullable to Non-Nullable", test_CantAssignNullableToNonNullable);
lrun("Tiny Test DisasmOne", test_DisasmOne);
lrun("Tiny Test GetStringConstant", test_GetStringConst);
lrun("Tiny Nested Compile Error Propagates", test_NestCompileFailPropagates);
Expand Down
3 changes: 0 additions & 3 deletions tiny/include/tiny.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,6 @@ typedef enum {
TINY_SYM_TAG_ANY,
TINY_SYM_TAG_FOREIGN,
TINY_SYM_TAG_STRUCT,
TINY_SYM_TAG_NULLABLE,
} Tiny_SymbolType;

// For all the fields marked with `// array` below, you can use
Expand Down Expand Up @@ -552,8 +551,6 @@ typedef struct Tiny_Symbol {

struct Tiny_Symbol *fieldTag;

struct Tiny_Symbol *nullableTag;

Tiny_MacroFunction modFunc;
};
} Tiny_Symbol;
Expand Down
2 changes: 1 addition & 1 deletion tiny/src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void ArrayResize(Array *array, int newLen, Tiny_Value newValue) {
}

void ArrayCopy(Array *dest, const Array *src) {
size_t count = sb_count(src->data);
int count = sb_count(src->data);

// TODO(Apaar): No need to fill with null
ArrayResize(dest, count, Tiny_Null);
Expand Down
41 changes: 0 additions & 41 deletions tiny/src/tiny.c
Original file line number Diff line number Diff line change
Expand Up @@ -1567,29 +1567,6 @@ static Tiny_Symbol *GetTagFromName(Tiny_State *state, const char *name, bool dec

static const char *GetTagName(const Tiny_Symbol *tag);

static Tiny_Symbol *GetOrCreateNullable(Tiny_State *state, Tiny_Symbol *inner) {
for (int i = 0; i < sb_count(state->globalSymbols); ++i) {
Tiny_Symbol *sym = state->globalSymbols[i];

if (sym->type == TINY_SYM_TAG_NULLABLE && sym->nullableTag == inner) {
return sym;
}
}

// FIXME(Apaar): Allow names longer than 256 chars
char nameBuf[256] = {0};

snprintf(nameBuf, sizeof(nameBuf), "?%s", GetTagName(inner));

Tiny_Symbol *sym = Symbol_create(TINY_SYM_TAG_NULLABLE, nameBuf, state);

sym->nullableTag = inner;

sb_push(&state->ctx, state->globalSymbols, sym);

return sym;
}

static Tiny_Symbol *GetFieldTag(Tiny_Symbol *s, const char *name, int *index) {
assert(s->type == TINY_SYM_TAG_STRUCT);
assert(s->sstruct.defined);
Expand All @@ -1611,20 +1588,6 @@ static Tiny_Symbol *GetFieldTag(Tiny_Symbol *s, const char *name, int *index) {
static Tiny_TokenKind GetNextToken(Tiny_State *state) { return Tiny_GetToken(&state->l); }

static Tiny_Symbol *ParseTypeL(Tiny_State *state, Tiny_Lexer *l) {
// Nullable type (more consistent if we prefix)
if (l->lastTok == TINY_TOK_QUESTION) {
Tiny_GetToken(l);

Tiny_Symbol *inner = ParseTypeL(state, l);

if (inner->type == TINY_SYM_TAG_VOID) {
ReportErrorL(state, l,
"Attempted to make a nullable 'void' type which doesn't make any sense.");
}

return GetOrCreateNullable(state, inner);
}

ExpectTokenL(state, l, TINY_TOK_IDENT, "Expected identifier for typename.");

Tiny_Symbol *s = GetTagFromName(state, l->lexeme, true);
Expand Down Expand Up @@ -2536,10 +2499,6 @@ static bool IsTagAssignableTo(const Tiny_Symbol *src, const Tiny_Symbol *dest) {
return dest->type == TINY_SYM_TAG_ANY;
}

if (dest->type == TINY_SYM_TAG_NULLABLE) {
return IsTagAssignableTo(src, dest->nullableTag);
}

if (src->type == dest->type) {
return strcmp(src->name, dest->name) == 0;
}
Expand Down

0 comments on commit 7b4d038

Please sign in to comment.