Skip to content

Commit

Permalink
Merge branch 'boolean-types'
Browse files Browse the repository at this point in the history
Lone has gained boolean register value types,
improving the expressiveness of the language
and simplifying the implementation.

Many functions that used to return nil now return false.
Tests have been updated to reflect this.

I'm still evaluating whether it is warranted
to add an undefined value in addition to nil.
  • Loading branch information
matheusmoreira committed Dec 26, 2024
2 parents 82edbad + d89543f commit 27f9e5c
Show file tree
Hide file tree
Showing 55 changed files with 183 additions and 127 deletions.
10 changes: 0 additions & 10 deletions include/lone/lisp/constants.h

This file was deleted.

14 changes: 10 additions & 4 deletions include/lone/lisp/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ enum lone_lisp_value_type {
LONE_LISP_TYPE_INTEGER = (0 << 2) | (0 << 1) | (1 << 0), /* ??1 */
LONE_LISP_TYPE_HEAP_VALUE = (0 << 2) | (0 << 1) | (0 << 0), /* 000 */
LONE_LISP_TYPE_NIL = (0 << 2) | (1 << 1) | (0 << 1), /* 010 */
LONE_LISP_TYPE_FALSE = (1 << 2) | (0 << 1) | (0 << 1), /* 100 */
LONE_LISP_TYPE_TRUE = (1 << 2) | (1 << 1) | (0 << 1), /* 110 */
};

struct lone_lisp_value {
Expand Down Expand Up @@ -184,7 +186,9 @@ typedef bool (*lone_lisp_comparator_function)(struct lone_lisp_value x, struct l
╰────────────────────────────────────────────────────────────────────────╯ */

struct lone_lisp_value lone_lisp_nil(void);
struct lone_lisp_value lone_lisp_boolean_for(struct lone_lisp *lisp, bool value);
struct lone_lisp_value lone_lisp_false(void);
struct lone_lisp_value lone_lisp_true(void);
struct lone_lisp_value lone_lisp_boolean_for(bool value);

/* ╭────────────────────────────────────────────────────────────────────────╮
│ │
Expand Down Expand Up @@ -215,6 +219,11 @@ bool lone_lisp_is_text(struct lone_lisp_value value);
bool lone_lisp_is_symbol(struct lone_lisp_value value);

bool lone_lisp_is_nil(struct lone_lisp_value value);
bool lone_lisp_is_false(struct lone_lisp_value value);
bool lone_lisp_is_true(struct lone_lisp_value value);
bool lone_lisp_is_falsy(struct lone_lisp_value value);
bool lone_lisp_is_truthy(struct lone_lisp_value value);

bool lone_lisp_is_integer(struct lone_lisp_value value);

/* ╭────────────────────────────────────────────────────────────────────────╮
Expand Down Expand Up @@ -246,9 +255,6 @@ struct lone_lisp {
void *native_stack;
struct lone_lisp_heap *heaps;
struct lone_lisp_value symbol_table;
struct {
struct lone_lisp_value truth;
} constants;
struct {
struct lone_lisp_value loaded;
struct lone_lisp_value embedded;
Expand Down
1 change: 0 additions & 1 deletion source/lone/lisp.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ void lone_lisp_initialize(struct lone_lisp *lone, struct lone_system *system, vo
*/

lone->symbol_table = lone_lisp_table_create(lone, 256, lone_lisp_nil());
lone->constants.truth = lone_lisp_intern_c_string(lone, "true");

lone->modules.loaded = lone_lisp_table_create(lone, 32, lone_lisp_nil());
lone->modules.embedded = lone_lisp_nil();
Expand Down
8 changes: 0 additions & 8 deletions source/lone/lisp/constants.c

This file was deleted.

8 changes: 8 additions & 0 deletions source/lone/lisp/evaluator.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ static struct lone_lisp_value lone_lisp_evaluate_form_index(struct lone_lisp *lo

switch (lone_lisp_type_of(collection)) {
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_INTEGER:
linux_exit(-1);
case LONE_LISP_TYPE_HEAP_VALUE:
Expand Down Expand Up @@ -84,6 +86,8 @@ static struct lone_lisp_value lone_lisp_evaluate_form(struct lone_lisp *lone,

switch (lone_lisp_type_of(first)) {
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_INTEGER:
/* first element not applicable */ linux_exit(-1);
case LONE_LISP_TYPE_HEAP_VALUE:
Expand Down Expand Up @@ -115,6 +119,8 @@ struct lone_lisp_value lone_lisp_evaluate(struct lone_lisp *lone,
{
switch (lone_lisp_type_of(value)) {
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_INTEGER:
return value;
case LONE_LISP_TYPE_HEAP_VALUE:
Expand Down Expand Up @@ -183,6 +189,8 @@ static struct lone_lisp_value lone_lisp_apply_function(struct lone_lisp *lone,
case LONE_LISP_TYPE_HEAP_VALUE:
break;
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_INTEGER:
/* unexpected value */ linux_exit(-1);
}
Expand Down
3 changes: 2 additions & 1 deletion source/lone/lisp/garbage_collector.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ static void lone_lisp_mark_value(struct lone_lisp_value value)
{
switch (lone_lisp_type_of(value)) {
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_INTEGER:
/* value types need not be marked */
return;
Expand Down Expand Up @@ -71,7 +73,6 @@ static void lone_lisp_mark_heap_value(struct lone_lisp_heap_value *value)
static void lone_lisp_mark_known_roots(struct lone_lisp *lone)
{
lone_lisp_mark_value(lone->symbol_table);
lone_lisp_mark_value(lone->constants.truth);
lone_lisp_mark_value(lone->modules.loaded);
lone_lisp_mark_value(lone->modules.embedded);
lone_lisp_mark_value(lone->modules.null);
Expand Down
2 changes: 2 additions & 0 deletions source/lone/lisp/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ static size_t lone_lisp_hash_value_recursively(struct lone_lisp_value value, uns

switch (type) {
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_FALSE:
return hash;
case LONE_LISP_TYPE_HEAP_VALUE:
return lone_lisp_hash_heap_value_recursively(lone_lisp_heap_value_of(value), hash);
Expand Down
4 changes: 4 additions & 0 deletions source/lone/lisp/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ static struct lone_lisp_value lone_lisp_module_name_to_key(struct lone_lisp *lon

switch (lone_lisp_type_of(name)) {
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_INTEGER:
/* invalid module name component */ linux_exit(-1);
case LONE_LISP_TYPE_HEAP_VALUE:
Expand Down Expand Up @@ -312,6 +314,8 @@ static void lone_lisp_primitive_import_form(struct lone_lisp *lone,
switch (lone_lisp_type_of(argument)) {
case LONE_LISP_TYPE_NIL:
/* nothing to import: (import ()) */ linux_exit(-1);
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_INTEGER:
/* not a supported import argument type */ linux_exit(-1);
case LONE_LISP_TYPE_HEAP_VALUE:
Expand Down
4 changes: 3 additions & 1 deletion source/lone/lisp/modules/intrinsic/bytes.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ LONE_LISP_PRIMITIVE(bytes_new)
allocation = lone_lisp_integer_of(count);
break;
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_HEAP_VALUE:
/* count not an integer: (new {}) */ linux_exit(-1);
}
Expand All @@ -120,7 +122,7 @@ LONE_LISP_PRIMITIVE(bytes_is_zero)
/* expected a bytes object: (zero? 0), (zero? "text") */ linux_exit(-1);
}

return lone_lisp_boolean_for(lone, lone_bytes_is_zero(lone_lisp_heap_value_of(bytes)->as.bytes));
return lone_lisp_boolean_for(lone_bytes_is_zero(lone_lisp_heap_value_of(bytes)->as.bytes));
}


Expand Down
7 changes: 7 additions & 0 deletions source/lone/lisp/modules/intrinsic/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ static inline long lone_lisp_value_to_linux_system_call_number(struct lone_lisp
case LONE_LISP_TYPE_INTEGER:
return lone_lisp_integer_of(value);
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
linux_exit(-1);
case LONE_LISP_TYPE_HEAP_VALUE:
break;
Expand All @@ -354,6 +356,8 @@ static inline long lone_lisp_value_to_linux_system_call_number(struct lone_lisp
case LONE_LISP_TYPE_INTEGER:
return lone_lisp_integer_of(number);
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_HEAP_VALUE:
break;
}
Expand All @@ -365,7 +369,10 @@ static inline long lone_lisp_value_to_linux_system_call_argument(struct lone_lis
{
switch (lone_lisp_type_of(value)) {
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
return 0;
case LONE_LISP_TYPE_TRUE:
return 1;
case LONE_LISP_TYPE_INTEGER:
return (long) lone_lisp_integer_of(value);
case LONE_LISP_TYPE_HEAP_VALUE:
Expand Down
7 changes: 3 additions & 4 deletions source/lone/lisp/modules/intrinsic/lone.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <lone/lisp/module.h>
#include <lone/lisp/evaluator.h>
#include <lone/lisp/printer.h>
#include <lone/lisp/constants.h>
#include <lone/lisp/utilities.h>

#include <lone/lisp/value/function.h>
Expand Down Expand Up @@ -110,7 +109,7 @@ LONE_LISP_PRIMITIVE(lone_when)
test = lone_lisp_list_first(arguments);
arguments = lone_lisp_list_rest(arguments);

if (!lone_lisp_is_nil(lone_lisp_evaluate(lone, module, environment, test))) {
if (lone_lisp_is_truthy(lone_lisp_evaluate(lone, module, environment, test))) {
return lone_lisp_primitive_lone_begin(lone, module, environment, arguments, closure);
}

Expand All @@ -125,7 +124,7 @@ LONE_LISP_PRIMITIVE(lone_unless)
test = lone_lisp_list_first(arguments);
arguments = lone_lisp_list_rest(arguments);

if (lone_lisp_is_nil(lone_lisp_evaluate(lone, module, environment, test))) {
if (lone_lisp_is_falsy(lone_lisp_evaluate(lone, module, environment, test))) {
return lone_lisp_primitive_lone_begin(lone, module, environment, arguments, closure);
}

Expand All @@ -152,7 +151,7 @@ LONE_LISP_PRIMITIVE(lone_if)
if (!lone_lisp_is_nil(arguments)) { /* too many values (if test consequent alternative extra) */ linux_exit(-1); }
}

if (!lone_lisp_is_nil(lone_lisp_evaluate(lone, module, environment, value))) {
if (lone_lisp_is_truthy(lone_lisp_evaluate(lone, module, environment, value))) {
return lone_lisp_evaluate(lone, module, environment, consequent);
} else {
return lone_lisp_evaluate(lone, module, environment, alternative);
Expand Down
17 changes: 11 additions & 6 deletions source/lone/lisp/modules/intrinsic/math.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,15 @@ static struct lone_lisp_value lone_lisp_primitive_integer_operation(struct lone_
}
break;
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_HEAP_VALUE:
/* accumulator is not a number */ linux_exit(-1);
}
break;
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_HEAP_VALUE:
/* argument is not a number */ linux_exit(-1);
}
Expand Down Expand Up @@ -165,6 +169,8 @@ LONE_LISP_PRIMITIVE(math_divide)
return lone_lisp_integer_create(lone_lisp_integer_of(dividend) / lone_lisp_integer_of(divisor));
}
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_HEAP_VALUE:
/* can't divide non-numbers: (/ "not a number") */ linux_exit(-1);
}
Expand Down Expand Up @@ -204,6 +210,8 @@ LONE_LISP_PRIMITIVE(math_sign)
else if (lone_lisp_integer_of(value) < 0) { return lone_lisp_minus_one(); }
else { return lone_lisp_zero(); }
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_HEAP_VALUE:
/* value is not a number */ linux_exit(-1);
}
Expand All @@ -212,20 +220,17 @@ LONE_LISP_PRIMITIVE(math_sign)
LONE_LISP_PRIMITIVE(math_is_zero)
{
struct lone_lisp_value value = lone_lisp_primitive_math_sign(lone, module, environment, arguments, closure);
if (lone_lisp_integer_of(value) == 0) { return value; }
else { return lone_lisp_nil(); }
return lone_lisp_boolean_for(lone_lisp_integer_of(value) == 0);
}

LONE_LISP_PRIMITIVE(math_is_positive)
{
struct lone_lisp_value value = lone_lisp_primitive_math_sign(lone, module, environment, arguments, closure);
if (lone_lisp_integer_of(value) > 0) { return value; }
else { return lone_lisp_nil(); }
return lone_lisp_boolean_for(lone_lisp_integer_of(value) > 0);
}

LONE_LISP_PRIMITIVE(math_is_negative)
{
struct lone_lisp_value value = lone_lisp_primitive_math_sign(lone, module, environment, arguments, closure);
if (lone_lisp_integer_of(value) < 0) { return value; }
else { return lone_lisp_nil(); }
return lone_lisp_boolean_for(lone_lisp_integer_of(value) < 0);
}
1 change: 0 additions & 1 deletion source/lone/lisp/modules/intrinsic/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <lone/lisp/value/integer.h>

#include <lone/lisp/module.h>
#include <lone/lisp/constants.h>
#include <lone/lisp/evaluator.h>

#include <lone/linux.h>
Expand Down
6 changes: 6 additions & 0 deletions source/lone/lisp/printer.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ void lone_lisp_print(struct lone_lisp *lone, struct lone_lisp_value value, int f
case LONE_LISP_TYPE_NIL:
linux_write(fd, "nil", 3);
return;
case LONE_LISP_TYPE_FALSE:
linux_write(fd, "false", 5);
return;
case LONE_LISP_TYPE_TRUE:
linux_write(fd, "true", 4);
return;
case LONE_LISP_TYPE_INTEGER:
lone_lisp_print_integer(fd, lone_lisp_integer_of(value));
return;
Expand Down
2 changes: 2 additions & 0 deletions source/lone/lisp/reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@ static struct lone_lisp_value lone_lisp_parse(struct lone_lisp *lone,
/* lexer has already parsed atoms */
switch (lone_lisp_type_of(token)) {
case LONE_LISP_TYPE_NIL:
case LONE_LISP_TYPE_FALSE:
case LONE_LISP_TYPE_TRUE:
case LONE_LISP_TYPE_INTEGER:
return token;
case LONE_LISP_TYPE_HEAP_VALUE:
Expand Down
Loading

0 comments on commit 27f9e5c

Please sign in to comment.