Add booleans
This commit is contained in:
parent
68b32c3799
commit
8581abcc0c
9 changed files with 219 additions and 200 deletions
|
@ -293,7 +293,7 @@ struct Object *func_display(struct Object *const args)
|
|||
printf(")");
|
||||
break;
|
||||
case TYPE_BOOLEAN:
|
||||
printf("%s", object->boolean ? "#t" : "#f");
|
||||
printf("%s", object->boolean ? "#true" : "#false");
|
||||
break;
|
||||
case TYPE_CHAR:
|
||||
printf("#\\TODO"); // TODO
|
||||
|
|
13
src/ctype.c
13
src/ctype.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <ctype.h>
|
||||
|
||||
bool is_space(char chr)
|
||||
bool is_space(const char chr)
|
||||
{
|
||||
// ' ' (space)
|
||||
// '\f' (form-feed)
|
||||
|
@ -13,7 +13,12 @@ bool is_space(char chr)
|
|||
return isspace(chr);
|
||||
}
|
||||
|
||||
bool is_ident_head(char chr)
|
||||
bool is_tag(const char chr)
|
||||
{
|
||||
return isalnum(chr);
|
||||
}
|
||||
|
||||
bool is_ident_head(const char chr)
|
||||
{
|
||||
return isalpha(chr) ||
|
||||
chr == '!' ||
|
||||
|
@ -36,12 +41,12 @@ bool is_ident_head(char chr)
|
|||
chr == '~';
|
||||
}
|
||||
|
||||
bool is_ident_tail(char chr)
|
||||
bool is_ident_tail(const char chr)
|
||||
{
|
||||
return is_ident_head(chr) || isdigit(chr);
|
||||
}
|
||||
|
||||
bool is_number(char chr)
|
||||
bool is_number(const char chr)
|
||||
{
|
||||
return isdigit(chr);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
bool is_space(char chr);
|
||||
bool is_tag(char chr);
|
||||
bool is_ident_head(char chr);
|
||||
bool is_ident_tail(char chr);
|
||||
bool is_number(char chr);
|
||||
|
|
63
src/lexer.c
63
src/lexer.c
|
@ -17,6 +17,8 @@ enum State {
|
|||
STATE_CURLY_OPEN,
|
||||
STATE_CURLY_CLOSE,
|
||||
STATE_QUOTE,
|
||||
STATE_SHARP,
|
||||
STATE_TAG,
|
||||
STATE_IDENT,
|
||||
STATE_NUM,
|
||||
};
|
||||
|
@ -58,6 +60,7 @@ State_to_token_type(const enum State state, enum TokenType *const token_type)
|
|||
case STATE_CURLY_CLOSE: *token_type = TOKEN_CURLY_CLOSE; break;
|
||||
case STATE_QUOTE: *token_type = TOKEN_QUOTE; break;
|
||||
case STATE_IDENT: *token_type = TOKEN_IDENT; break;
|
||||
case STATE_TAG: *token_type = TOKEN_TAG; break;
|
||||
case STATE_NUM: *token_type = TOKEN_NUM; break;
|
||||
default: return false;
|
||||
}
|
||||
|
@ -112,6 +115,8 @@ void Lexer_lex(const Lexer self, const char chr)
|
|||
} else if (chr == '\'') {
|
||||
state = STATE_QUOTE;
|
||||
buffer_add(chr);
|
||||
} else if (chr == '#') {
|
||||
state = STATE_SHARP;
|
||||
} else if (is_space(chr)) {
|
||||
state = STATE_WHITESPACE;
|
||||
buffer_add(chr);
|
||||
|
@ -161,6 +166,10 @@ void Lexer_lex(const Lexer self, const char chr)
|
|||
buffer_clean();
|
||||
state = STATE_QUOTE;
|
||||
buffer_add(chr);
|
||||
} else if (chr == '#') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_SHARP;
|
||||
} else if (is_space(chr)) {
|
||||
buffer_add(chr);
|
||||
} else if (is_ident_head(chr)) {
|
||||
|
@ -219,6 +228,10 @@ void Lexer_lex(const Lexer self, const char chr)
|
|||
buffer_clean();
|
||||
state = STATE_QUOTE;
|
||||
buffer_add(chr);
|
||||
} else if (chr == '#') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_SHARP;
|
||||
} else if (is_space(chr)) {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
|
@ -238,6 +251,56 @@ void Lexer_lex(const Lexer self, const char chr)
|
|||
abort();
|
||||
}
|
||||
break;
|
||||
case STATE_SHARP:
|
||||
if (is_tag(chr)) {
|
||||
state = STATE_TAG;
|
||||
buffer_add(chr);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case STATE_TAG:
|
||||
if (chr == '(') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_ROUND_OPEN;
|
||||
buffer_add(chr);
|
||||
} else if (chr == ')') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_ROUND_CLOSE;
|
||||
buffer_add(chr);
|
||||
} else if (chr == '[') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_SQUARE_OPEN;
|
||||
buffer_add(chr);
|
||||
} else if (chr == ']') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_SQUARE_CLOSE;
|
||||
buffer_add(chr);
|
||||
} else if (chr == '{') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_CURLY_OPEN;
|
||||
buffer_add(chr);
|
||||
} else if (chr == '}') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_CURLY_CLOSE;
|
||||
buffer_add(chr);
|
||||
} else if (is_space(chr)) {
|
||||
token_add(self->tokens, state, buffer);
|
||||
buffer_clean();
|
||||
state = STATE_WHITESPACE;
|
||||
buffer_add(chr);
|
||||
} else if (is_tag(chr)) {
|
||||
buffer_add(chr);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
case STATE_IDENT:
|
||||
if (chr == '(') {
|
||||
token_add(self->tokens, state, buffer);
|
||||
|
|
320
src/main.c
320
src/main.c
|
@ -260,8 +260,8 @@ void test()
|
|||
struct Object *const sharp_true = Object_new_boolean(true);
|
||||
struct Object *const num_123 = Object_new_number(123);
|
||||
|
||||
// #t
|
||||
// #t
|
||||
// #true
|
||||
// #true
|
||||
assert(eval(sharp_true) == sharp_true);
|
||||
|
||||
// 123
|
||||
|
@ -276,8 +276,8 @@ void test()
|
|||
) == sym_foo
|
||||
);
|
||||
|
||||
// (quote #t)
|
||||
// #t
|
||||
// (quote #true)
|
||||
// #true
|
||||
assert(
|
||||
eval(
|
||||
Object_build_list(2, Object_new_symbol("quote"), sharp_true)
|
||||
|
@ -306,7 +306,7 @@ void test_if()
|
|||
struct Object *const num_123 = Object_new_number(123);
|
||||
struct Object *const num_456 = Object_new_number(456);
|
||||
|
||||
// (if #t 123 456)
|
||||
// (if #true 123 456)
|
||||
assert(eval(Object_build_list(
|
||||
4,
|
||||
Object_new_symbol("if"),
|
||||
|
@ -324,7 +324,7 @@ void test_if()
|
|||
num_456
|
||||
)) == num_123);
|
||||
|
||||
// (if #f 123 456)
|
||||
// (if #false 123 456)
|
||||
assert(eval(Object_build_list(
|
||||
4,
|
||||
Object_new_symbol("if"),
|
||||
|
@ -419,31 +419,23 @@ void test_list()
|
|||
void test_booleanQN()
|
||||
{
|
||||
// (boolean? +)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(boolean? +)")));
|
||||
|
||||
// (boolean? '())
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(boolean? '())")));
|
||||
|
||||
// (boolean? #t)
|
||||
// #t
|
||||
assert(Object_is_true(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("boolean?"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (boolean? #true)
|
||||
// #true
|
||||
assert(Object_is_true(eval_str("(boolean? #true)")));
|
||||
|
||||
// (boolean? #f)
|
||||
// #t
|
||||
assert(Object_is_true(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("boolean?"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (boolean? #false)
|
||||
// #true
|
||||
assert(Object_is_true(eval_str("(boolean? #false)")));
|
||||
|
||||
// (boolean? #\n)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("boolean?"),
|
||||
|
@ -451,11 +443,11 @@ void test_booleanQN()
|
|||
))));
|
||||
|
||||
// (boolean? 'foo)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(boolean? 'foo)")));
|
||||
|
||||
// (boolean? "foo")
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("boolean?"),
|
||||
|
@ -463,42 +455,34 @@ void test_booleanQN()
|
|||
))));
|
||||
|
||||
// (boolean? 123)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(boolean? 123)")));
|
||||
|
||||
// (boolean? (cons 123 456))
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(boolean? (cons 123 456))")));
|
||||
}
|
||||
|
||||
void test_charQN()
|
||||
{
|
||||
// (char? +)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(char? +)")));
|
||||
|
||||
// (char? '())
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(char? '())")));
|
||||
|
||||
// (char? #t)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("char?"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (char? #true)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(char? #true)")));
|
||||
|
||||
// (char? #f)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("char?"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (char? #false)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(char? #false)")));
|
||||
|
||||
// (char? #\n)
|
||||
// #t
|
||||
// #true
|
||||
assert(Object_is_true(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("char?"),
|
||||
|
@ -506,11 +490,11 @@ void test_charQN()
|
|||
))));
|
||||
|
||||
// (char? 'foo)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(char? 'foo)")));
|
||||
|
||||
// (char? "foo")
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("char?"),
|
||||
|
@ -518,42 +502,34 @@ void test_charQN()
|
|||
))));
|
||||
|
||||
// (char? 123)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(char? 123)")));
|
||||
|
||||
// (char? (cons 123 456))
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(char? (cons 123 456))")));
|
||||
}
|
||||
|
||||
void test_nullQN()
|
||||
{
|
||||
// (null? +)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(null? +)")));
|
||||
|
||||
// (null? '())
|
||||
// #t
|
||||
// #true
|
||||
assert(Object_is_true(eval_str("(null? '())")));
|
||||
|
||||
// (null? #t)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("null?"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (null? #true)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(null? #true)")));
|
||||
|
||||
// (null? #f)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("null?"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (null? #false)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(null? #false)")));
|
||||
|
||||
// (null? #\n)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("null?"),
|
||||
|
@ -561,11 +537,11 @@ void test_nullQN()
|
|||
))));
|
||||
|
||||
// (null? 'foo)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(null? 'foo)")));
|
||||
|
||||
// (null? "foo")
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("null?"),
|
||||
|
@ -573,42 +549,34 @@ void test_nullQN()
|
|||
))));
|
||||
|
||||
// (null? 123)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(null? 123)")));
|
||||
|
||||
// (null? (cons 123 456))
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(null? (cons 123 456))")));
|
||||
}
|
||||
|
||||
void test_numberQN()
|
||||
{
|
||||
// (number? +)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(number? +)")));
|
||||
|
||||
// (number? '())
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(number? '())")));
|
||||
|
||||
// (number? #t)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("number?"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (number? #true)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(number? #true)")));
|
||||
|
||||
// (number? #f)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("number?"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (number? #false)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(number? #false)")));
|
||||
|
||||
// (number? #\n)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("number?"),
|
||||
|
@ -616,11 +584,11 @@ void test_numberQN()
|
|||
))));
|
||||
|
||||
// (number? 'foo)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(number? 'foo)")));
|
||||
|
||||
// (number? "foo")
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("number?"),
|
||||
|
@ -628,42 +596,34 @@ void test_numberQN()
|
|||
))));
|
||||
|
||||
// (number? 123)
|
||||
// #t
|
||||
// #true
|
||||
assert(Object_is_true(eval_str("(number? 123)")));
|
||||
|
||||
// (number? (cons 123 456))
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(number? (cons 123 456))")));
|
||||
}
|
||||
|
||||
void test_pairQN()
|
||||
{
|
||||
// (pair? +)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(pair? +)")));
|
||||
|
||||
// (pair? '())
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(pair? '())")));
|
||||
|
||||
// (pair? #t)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("pair?"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (pair? #true)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(pair? #true)")));
|
||||
|
||||
// (pair? #f)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("pair?"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (pair? #false)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(pair? #false)")));
|
||||
|
||||
// (pair? #\n)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("pair?"),
|
||||
|
@ -671,11 +631,11 @@ void test_pairQN()
|
|||
))));
|
||||
|
||||
// (pair? 'foo)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(pair? 'foo)")));
|
||||
|
||||
// (pair? "foo")
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("pair?"),
|
||||
|
@ -683,42 +643,34 @@ void test_pairQN()
|
|||
))));
|
||||
|
||||
// (pair? 123)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(pair? 123)")));
|
||||
|
||||
// (pair? (cons 123 456))
|
||||
// #t
|
||||
// #true
|
||||
assert(Object_is_true(eval_str("(pair? (cons 123 456))")));
|
||||
}
|
||||
|
||||
void test_procedureQN()
|
||||
{
|
||||
// (procedure? +)
|
||||
// #t
|
||||
// #true
|
||||
assert(Object_is_true(eval_str("(procedure? +)")));
|
||||
|
||||
// (procedure? '())
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(procedure? '())")));
|
||||
|
||||
// (procedure? #t)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("procedure?"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (procedure? #true)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(procedure? #true)")));
|
||||
|
||||
// (procedure? #f)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("procedure?"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (procedure? #false)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(procedure? #false)")));
|
||||
|
||||
// (procedure? #\n)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("procedure?"),
|
||||
|
@ -726,11 +678,11 @@ void test_procedureQN()
|
|||
))));
|
||||
|
||||
// (procedure? 'foo)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(procedure? 'foo)")));
|
||||
|
||||
// (procedure? "foo")
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("procedure?"),
|
||||
|
@ -738,42 +690,34 @@ void test_procedureQN()
|
|||
))));
|
||||
|
||||
// (procedure? 123)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(procedure? 123)")));
|
||||
|
||||
// (procedure? (cons 123 456))
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(procedure? (cons 123 456))")));
|
||||
}
|
||||
|
||||
void test_stringQN()
|
||||
{
|
||||
// (string? +)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(string? +)")));
|
||||
|
||||
// (string? '())
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(string? '())")));
|
||||
|
||||
// (string? #t)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("string?"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (string? #true)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(string? #true)")));
|
||||
|
||||
// (string? #f)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("string?"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (string? #false)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(string? #false)")));
|
||||
|
||||
// (string? #\n)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("string?"),
|
||||
|
@ -781,11 +725,11 @@ void test_stringQN()
|
|||
))));
|
||||
|
||||
// (string? 'foo)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(string? 'foo)")));
|
||||
|
||||
// (string? "foo")
|
||||
// #t
|
||||
// #true
|
||||
assert(Object_is_true(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("string?"),
|
||||
|
@ -793,42 +737,34 @@ void test_stringQN()
|
|||
))));
|
||||
|
||||
// (string? 123)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(string? 123)")));
|
||||
|
||||
// (string? (cons 123 456))
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(string? (cons 123 456))")));
|
||||
}
|
||||
|
||||
void test_symbolQN()
|
||||
{
|
||||
// (symbol? +)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(symbol? +)")));
|
||||
|
||||
// (symbol? '())
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(symbol? '())")));
|
||||
|
||||
// (symbol? #t)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("symbol?"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (symbol? #true)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(symbol? #true)")));
|
||||
|
||||
// (symbol? #f)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("symbol?"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (symbol? #false)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(symbol? #false)")));
|
||||
|
||||
// (symbol? #\n)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("symbol?"),
|
||||
|
@ -836,11 +772,11 @@ void test_symbolQN()
|
|||
))));
|
||||
|
||||
// (symbol? 'foo)
|
||||
// #t
|
||||
// #true
|
||||
assert(Object_is_true(eval_str("(symbol? 'foo)")));
|
||||
|
||||
// (symbol? "foo")
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("symbol?"),
|
||||
|
@ -848,11 +784,11 @@ void test_symbolQN()
|
|||
))));
|
||||
|
||||
// (symbol? 123)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(symbol? 123)")));
|
||||
|
||||
// (symbol? (cons 123 456))
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(symbol? (cons 123 456))")));
|
||||
}
|
||||
|
||||
|
@ -887,30 +823,26 @@ void test_numberTOstring()
|
|||
assert(strcmp(result->s, "1e240") == 0);
|
||||
}
|
||||
|
||||
/*********************
|
||||
* Logical operators *
|
||||
*********************/
|
||||
|
||||
void test_not()
|
||||
{
|
||||
// (not '())
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(not '())")));
|
||||
|
||||
// (not #t)
|
||||
// #f
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("not"),
|
||||
Object_new_boolean(true)
|
||||
))));
|
||||
// (not #true)
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(not #true)")));
|
||||
|
||||
// (not #f)
|
||||
// #t
|
||||
assert(Object_is_true(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("not"),
|
||||
Object_new_boolean(false)
|
||||
))));
|
||||
// (not #false)
|
||||
// #true
|
||||
assert(Object_is_true(eval_str("(not #false)")));
|
||||
|
||||
// (not #\n)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("not"),
|
||||
|
@ -918,11 +850,11 @@ void test_not()
|
|||
))));
|
||||
|
||||
// (not 'foo)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(not 'foo)")));
|
||||
|
||||
// (not "foo")
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval(Object_build_list(
|
||||
2,
|
||||
Object_new_symbol("not"),
|
||||
|
@ -930,10 +862,10 @@ void test_not()
|
|||
))));
|
||||
|
||||
// (not 123)
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(not 123)")));
|
||||
|
||||
// (not (cons 123 456))
|
||||
// #f
|
||||
// #false
|
||||
assert(Object_is_false(eval_str("(not (cons 123 456))")));
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ void Object_print(struct Object *const self, const unsigned indent)
|
|||
Object_print(self->pair.b, indent + 1);
|
||||
break;
|
||||
case TYPE_BOOLEAN:
|
||||
printf("%s\n", self->boolean ? "#t" : "#f");
|
||||
printf("%s\n", self->boolean ? "#true" : "#false");
|
||||
break;
|
||||
case TYPE_CHAR:
|
||||
printf("%c\n", self->chr);
|
||||
|
|
16
src/parser.c
16
src/parser.c
|
@ -6,6 +6,7 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void expect(Tokens tokens, enum TokenType token_type);
|
||||
|
||||
|
@ -35,6 +36,21 @@ struct Object *expr(const Tokens tokens)
|
|||
case TOKEN_QUOTE:
|
||||
Tokens_pop(tokens);
|
||||
return Object_build_list(2, Object_new_symbol("quote"), expr(tokens));
|
||||
case TOKEN_TAG:
|
||||
{
|
||||
struct Object *object = NULL;
|
||||
const char *const val = Tokens_top(tokens)->val;
|
||||
assert(val);
|
||||
if (strcmp(val, "f") == 0 || strcmp(val, "false") == 0) {
|
||||
object = Object_new_boolean(false);
|
||||
} else if (strcmp(val, "t") == 0 || strcmp(val, "true") == 0) {
|
||||
object = Object_new_boolean(true);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
Tokens_pop(tokens);
|
||||
return object;
|
||||
}
|
||||
case TOKEN_IDENT:
|
||||
{
|
||||
struct Object *const object = Object_new_symbol(Tokens_top(tokens)->val);
|
||||
|
|
|
@ -16,6 +16,7 @@ const char *TokenType_to_str(const enum TokenType token_type)
|
|||
case TOKEN_CURLY_OPEN: return "TOKEN_CURLY_OPEN";
|
||||
case TOKEN_CURLY_CLOSE: return "TOKEN_CURLY_CLOSE";
|
||||
case TOKEN_QUOTE: return "TOKEN_QUOTE";
|
||||
case TOKEN_TAG: return "TOKEN_TAG";
|
||||
case TOKEN_IDENT: return "TOKEN_IDENT";
|
||||
case TOKEN_NUM: return "TOKEN_NUM";
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ enum TokenType {
|
|||
TOKEN_CURLY_OPEN,
|
||||
TOKEN_CURLY_CLOSE,
|
||||
TOKEN_QUOTE,
|
||||
TOKEN_TAG,
|
||||
TOKEN_IDENT,
|
||||
TOKEN_NUM,
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue