Просмотр исходного кода

We can parse expressions

master
FelixBrendel 7 лет назад
Родитель
Сommit
db0318bb03
7 измененных файлов: 469 добавлений и 147 удалений
  1. +8
    -9
      build.bat
  2. +11
    -1
      src/ast.c
  3. +2
    -0
      src/error.c
  4. +9
    -4
      src/eval.c
  5. +254
    -9
      src/parse.c
  6. +184
    -124
      src/testing.c
  7. +1
    -0
      todo.org

+ 8
- 9
build.bat Просмотреть файл

@@ -1,26 +1,25 @@
@echo off
@setlocal
pushd %~dp0

set start=%time%

set exeName=lisp.exe
set binDir=bin

mkdir quickbuild
mkdir quickbuild 2>nul
pushd quickbuild

cl^
../src/main.c^
/Fe%exeName% /W3 /TC^
/nologo /EHsc /Z7^
/link /incremental /debug:fastlink
echo ---------- Compiling ----------
call timecmd cl ../src/main.c /Fe%exeName% /W3 /TC /nologo /EHsc /Z7 /link /incremental /debug:fastlink

if %errorlevel% == 0 (
echo.
if not exist ..\%binDir% mkdir ..\%binDir%
move %exeName% ..\%binDir%\ > NUL
pushd ..\%binDir%
echo ---------- Output start ----------
%exeName%
echo ---------- Output end ----------
echo ---------- Running ----------
call timecmd %exeName%
del %exeName% /S /Q > NUL
popd
) else (


+ 11
- 1
src/ast.c Просмотреть файл

@@ -27,6 +27,7 @@ typedef struct {

typedef struct {
char* value;
int length;
} String;

typedef struct {
@@ -42,6 +43,7 @@ typedef struct {
typedef struct {
Lambda_List* parameters;
Pair* form;
char* docstring;
} Function;

typedef struct {
@@ -79,11 +81,12 @@ Ast_Node* create_ast_node_number(double number) {
return node;
}

Ast_Node* create_ast_node_string(char* str) {
Ast_Node* create_ast_node_string(char* str, int length) {
Ast_Node* node = new(Ast_Node);
node->type = Ast_Node_Type_String;
node->value.string = new(String);
node->value.string->value = str;
node->value.string->length = length;
return node;
}

@@ -95,6 +98,13 @@ Ast_Node* create_ast_node_symbol(char* identifier) {
return node;
}

Ast_Node* create_ast_node_keyword(char* keyword) {
Ast_Node* node = new(Ast_Node);
node->type = Ast_Node_Type_Keyword;
node->value.keyword = new(Keyword);
node->value.keyword->identifier = keyword;
return node;
}

Ast_Node* create_ast_node_built_in_function(char* identifier) {
Ast_Node* node = new(Ast_Node);


+ 2
- 0
src/error.c Просмотреть файл

@@ -5,6 +5,7 @@ typedef enum {
Error_Type_Symbol_Not_Defined,
Error_Type_Not_A_Function,
Error_Type_Not_Yet_Implemented,
Error_Type_Syntax_Error,
Error_Type_Unknown_Error,
} Error_Type;

@@ -38,6 +39,7 @@ char* Error_Type_to_string(Error_Type type) {
case Error_Type_Wrong_Number_Of_Arguments: return "Wrong number of arguments";
case Error_Type_Type_Missmatch: return "Type Missmatch";
case Error_Type_Not_Yet_Implemented: return "Not yet implemented";
case Error_Type_Syntax_Error: return "Syntax Error";
default: return "Unknown Error";
}
}

+ 9
- 4
src/eval.c Просмотреть файл

@@ -81,7 +81,8 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
} else if (string_equal("if", operator_name)) {
int operands_length = list_length(operands);
if (operands_length != 2 && operands_length != 3) {
create_error(Error_Type_Wrong_Number_Of_Arguments, operands);
if (!error)
create_error(Error_Type_Wrong_Number_Of_Arguments, operands);
return nullptr;
}

@@ -124,10 +125,14 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
return create_ast_node_nil();
} else if (string_equal("not", operator_name)) {
if (list_length(operands) != 1) {
create_error(Error_Type_Wrong_Number_Of_Arguments, operands);
if (!error)
create_error(Error_Type_Wrong_Number_Of_Arguments, operands);
return nullptr;
}

bool truthy = is_truthy(operands->value.pair->first, env);
if (truthy)
return create_ast_node_nil();
return create_ast_node_number(1);
} else {
report_error(Error_Type_Not_Yet_Implemented);
}
@@ -148,7 +153,7 @@ bool is_truthy (Ast_Node* expression, Environment* env) {
Ast_Node* result = eval_expr(expression, env);
switch (result->type) {
case Ast_Node_Type_Nil: return false;
case Ast_Node_Type_Number: return result->value.number->value != 0;
/* case Ast_Node_Type_Number: return result->value.number->value != 0; */
default: return true;
}
}

+ 254
- 9
src/parse.c Просмотреть файл

@@ -1,12 +1,257 @@
Ast_Node* parse_expression(char* expr) {
typedef enum {
Parser_State_Code,
Parser_State_String,
Parser_State_Comment,
} Parser_State;
typedef struct {
Ast_Node** data;
int length;
int next_index;
} Ast_Node_Array_List;

// initial state is code
Parser_State current_parser_state = Parser_State_Code;
Ast_Node_Array_List* create_Ast_Node_Array_List() {
Ast_Node_Array_List* ret = new (Ast_Node_Array_List);

return nullptr;
// create one with 16 entries first
ret->length = 16;
ret->data = (Ast_Node**)malloc(ret->length * sizeof(Ast_Node));
ret->next_index = 0;

return ret;
}

void append_to_Ast_Node_Array_List(Ast_Node_Array_List* list, Ast_Node* node) {
if (list->next_index == list->length) {
list->length *= 2;
list->data =
(Ast_Node**)realloc(list->data, list->length * sizeof(Ast_Node));
}

list->data[list->next_index++] = node;
}

void eat_comment_line(char* text, int* index_in_text) {
// safety check if we are actually starting a comment here
if (text[*index_in_text] != ';')
return;

// eat the comment line
do {
++(*index_in_text);
} while (text[(*index_in_text)] != '\n' &&
text[(*index_in_text)] != '\0');
}

void eat_whitespace(char* text, int* index_in_text) {
// skip whitespaces
while (text[(*index_in_text)] == ' ' ||
text[(*index_in_text)] == '\t' ||
text[(*index_in_text)] == '\n') {
++(*index_in_text);
}
}

void eat_until_code(char* text, int* index_in_text) {
int position_before;
do {
position_before = *index_in_text;
eat_comment_line(text, index_in_text);
eat_whitespace(text, index_in_text);
} while (position_before != *index_in_text);
}

char* read_atom(char* text, int* index_in_text) {
int atom_length = 0;
while (text[*index_in_text+atom_length] != ' ' &&
text[*index_in_text+atom_length] != ')' &&
text[*index_in_text+atom_length] != '(' &&
text[*index_in_text+atom_length] != '\0' &&
text[*index_in_text+atom_length] != '\n' &&
text[*index_in_text+atom_length] != '\t')
{
++atom_length;
}

// let's mark the end of the atom there quickly, so the string can
// be copied from there easily and then put the char that was
// before there back
char before = text[*index_in_text+atom_length];
text[*index_in_text+atom_length] = '\0';

// get the atom
char* atom = (char*)malloc(atom_length*sizeof(char)+1); // plus null char
strcpy(atom, text+(*index_in_text));

// restore the original string
text[*index_in_text+atom_length] = before;

// update the index to point to the character after the atom
// ended
*index_in_text += atom_length;

return atom;
}

Ast_Node* parse_number(char* text, int* index_in_text) {
double number;
char* str_number = read_atom(text, index_in_text);
sscanf(str_number, "%lf", &number);
return create_ast_node_number(number);
}


Ast_Node* parse_keyword(char* text, int* index_in_text) {
// we are now on the colon
++(*index_in_text);
char* str_keyword = read_atom(text, index_in_text);
return create_ast_node_keyword(str_keyword);
}

Ast_Node* parse_symbol(char* text, int* index_in_text) {
// we are now at the first char of the symbol
char* str_symbol = read_atom(text, index_in_text);
return create_ast_node_symbol(str_symbol);
}

Ast_Node* parse_string(char* text, int* index_in_text) {
// the first character is the '"'
++(*index_in_text);

// now we are at the first letter, if this is the closing '"' then
// it's easy
if (text[*index_in_text] == '"') {
char* str = new(char);
*str = '\0';
return create_ast_node_string(str, 0);
}

// okay so the first letter was not actually closing the string...
int string_length = 0;
while (text[*index_in_text+string_length] != '"' ||
text[*index_in_text+string_length] == '\\')
{
++string_length;
}

// we found the end of the string
text[*index_in_text+string_length] = '\0';

char* string = (char*)malloc(string_length*sizeof(char)+1); // plus null char
strcpy(string, text+(*index_in_text));

text[*index_in_text+string_length] = '"';

*index_in_text += string_length +1; // plus one because we want to
// go after the quotes

return create_ast_node_string(string, string_length);
}

Ast_Node* parse_atom(char* text, int* index_in_text) {
// numbers
if ((text[*index_in_text] <= 57 && // if number
text[*index_in_text] >= 48)
||
((text[*index_in_text] == '+' || // or if sign and then number
text[*index_in_text] == '-')
&&
(text[*index_in_text +1] <= 57 &&
text[*index_in_text +1] >= 48))
||
((text[*index_in_text] == '.') // or if . and then number
&&
(text[*index_in_text +1] <= 57 &&
text[*index_in_text +1] >= 48)))
return parse_number(text, index_in_text);

// keywords
if (text[*index_in_text] == ':')
return parse_keyword(text, index_in_text);

// strings
if (text[*index_in_text] == '"')
return parse_string(text, index_in_text);

return parse_symbol(text, index_in_text);
}

Ast_Node* parse_expression(char* text, int* index_in_text) {
// okay we know the text under the index is '('
++(*index_in_text);

eat_whitespace(text, index_in_text);

// if there was actually nothing in the list return nil
if (text[(*index_in_text)] == ')') {
++(*index_in_text);
return create_ast_node_nil();
}

// okay there is something
Ast_Node* head = new(Ast_Node);
head->type = Ast_Node_Type_Pair;
head->value.pair = new(Pair);
Ast_Node* expression = head;

while (true) {
if (text[(*index_in_text)] == '(') {
head->value.pair->first = parse_expression(text, index_in_text);
} else {
head->value.pair->first = parse_atom(text, index_in_text);
}

eat_until_code(text, index_in_text);

if (text[(*index_in_text)] == ')') {
head->value.pair->rest = create_ast_node_nil();
++(*index_in_text);
break;
} else if (text[(*index_in_text)] == '.') {
++(*index_in_text);
eat_until_code(text, index_in_text);

if (text[(*index_in_text)] == '(')
head->value.pair->rest = parse_expression(text, index_in_text);
else
head->value.pair->rest = parse_atom(text, index_in_text);

eat_until_code(text, index_in_text);

if (text[(*index_in_text)] != ')')
create_error(Error_Type_Syntax_Error, nullptr);
++(*index_in_text);
break;
} else {
head->value.pair->rest = create_ast_node_pair(nullptr, nullptr);
head = head->value.pair->rest;
}
}
return expression;
}

Ast_Node* parse_single_expression(char* text) {
int index_in_text = 0;
return parse_expression(text, &index_in_text);
}

Ast_Node_Array_List* parse_program(char* text) {
Ast_Node_Array_List* program = create_Ast_Node_Array_List();

int index_in_text = 0;

while (text[index_in_text] != '\0') {
switch (text[index_in_text]) {
case '(': {
append_to_Ast_Node_Array_List(
program, parse_expression(text, &index_in_text));
} break;
case ';': {
eat_comment_line(text, &index_in_text);
} break;
case ' ':
case '\t':
case '\n': {
++index_in_text;
} break;
default:
create_error(Error_Type_Syntax_Error, nullptr);
/* syntax error */
}
}
return program;
}

+ 184
- 124
src/testing.c Просмотреть файл

@@ -4,16 +4,14 @@
#define pass 1
#define fail 0

#define print_assert_equal_fail(variable, value, type, format) \
printf("\nAssertion failed for '" #variable "'" \
"\n\t in %s:%d" \
"\n\texpected: " format \
"\n\tgot: " format "\n", \
__FILE__, __LINE__, (type)value, (type)variable)
#define print_assert_equal_fail(variable, value, type, format) \
printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
"\n\texpected: " format \
"\n\tgot: " format "\n", \
__FILE__, __LINE__, (type)value, (type)variable)

#define print_assert_not_equal_fail(variable, value, type, format) \
printf("\nAssertion failed for '" #variable "'" \
"\n\t in %s:%d" \
printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
"\n\texpected not: " format \
"\n\tgot anyways: " format "\n", \
__FILE__, __LINE__, (type)value, (type)variable)
@@ -50,6 +48,13 @@
return fail; \
}

#define assert_equal_string(variable, value) \
if (!string_equal(variable, value)) { \
print_assert_equal_fail(variable, value, char*, "%s"); \
return fail; \
}


#define assert_null(variable) \
assert_equal_int(variable, nullptr)

@@ -74,21 +79,121 @@
} \
} \

testresult test_parse_atom() {
int index_in_text = 0;
char string[] =
"123 -1.23e-2 " // numbers
"\"asd\" " // strings
":key1 :key:2 " // keywords
"sym +"; // symbols

// test numbers
Ast_Node* result = parse_atom(string, &index_in_text);
assert_equal_int(result->type, Ast_Node_Type_Number);
assert_equal_double(result->value.number->value, 123);

++index_in_text;

result = parse_atom(string, &index_in_text);
assert_equal_int(result->type, Ast_Node_Type_Number);
assert_equal_double(result->value.number->value, -1.23e-2);

// test strings
++index_in_text;

result = parse_atom(string, &index_in_text);
assert_equal_int(result->type, Ast_Node_Type_String);
assert_equal_string(result->value.string->value, "asd");

// test keywords
++index_in_text;

result = parse_atom(string, &index_in_text);
assert_equal_int(result->type, Ast_Node_Type_Keyword);
assert_equal_string(result->value.keyword->identifier, "key1");

++index_in_text;

result = parse_atom(string, &index_in_text);
assert_equal_int(result->type, Ast_Node_Type_Keyword);
assert_equal_string(result->value.keyword->identifier, "key:2");

// test symbols
++index_in_text;

result = parse_atom(string, &index_in_text);
assert_equal_int(result->type, Ast_Node_Type_Symbol);
assert_equal_string(result->value.symbol->identifier, "sym");

++index_in_text;

result = parse_atom(string, &index_in_text);
assert_equal_int(result->type, Ast_Node_Type_Symbol);
assert_equal_string(result->value.symbol->identifier, "+");

return pass;
}

testresult test_parse_expression() {
int index_in_text = 0;
char string[] = "(fun + 12)";

Ast_Node* result = parse_expression(string, &index_in_text);
assert_no_error(error);

assert_equal_int(result->type, Ast_Node_Type_Pair);
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Symbol);
assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun");

result = result->value.pair->rest;

assert_equal_int(result->type, Ast_Node_Type_Pair);
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Symbol);
assert_equal_string(result->value.pair->first->value.symbol->identifier, "+");

result = result->value.pair->rest;

assert_equal_int(result->type, Ast_Node_Type_Pair);
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Number);
assert_equal_double(result->value.pair->first->value.number->value, 12);

result = result->value.pair->rest;

assert_equal_int(result->type, Ast_Node_Type_Nil);

char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))";
index_in_text = 0;

result = parse_expression(string2, &index_in_text);
assert_no_error(error);

assert_equal_int(result->type, Ast_Node_Type_Pair);
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Symbol);
assert_equal_string(result->value.pair->first->value.symbol->identifier, "define");

result = result->value.pair->rest;

assert_equal_int(result->type, Ast_Node_Type_Pair);
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Symbol);
assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun");

result = result->value.pair->rest;

assert_equal_int(result->type, Ast_Node_Type_Pair);
assert_equal_int(result->value.pair->first->type, Ast_Node_Type_Pair);
assert_equal_int(result->value.pair->first->value.pair->first->type, Ast_Node_Type_Symbol);
assert_equal_string(result->value.pair->first->value.pair->first->value.symbol->identifier, "lambda");

result = result->value.pair->rest;


return pass;
}

testresult test_built_in_add() {
Ast_Node* plus = create_ast_node_symbol("+");
Ast_Node* ten = create_ast_node_number(10);
Ast_Node* four = create_ast_node_number(4);
Ast_Node* nil = create_ast_node_nil();
Ast_Node* form = create_ast_node_pair(
plus,
create_ast_node_pair(
ten,
create_ast_node_pair(
four,
nil)));

Ast_Node* result = eval_expr(form, create_empty_environment());
char exp_string[] = "(+ 10 4)";
Ast_Node* expression = parse_single_expression(exp_string);
Ast_Node* result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
@@ -99,19 +204,9 @@ testresult test_built_in_add() {
}

testresult test_built_in_substract() {
Ast_Node* minus = create_ast_node_symbol("-");
Ast_Node* ten = create_ast_node_number(10);
Ast_Node* four = create_ast_node_number(4);
Ast_Node* nil = create_ast_node_nil();
Ast_Node* form = create_ast_node_pair(
minus,
create_ast_node_pair(
ten,
create_ast_node_pair(
four,
nil)));

Ast_Node* result = eval_expr(form, create_empty_environment());
char exp_string[] = "(- 10 4)";
Ast_Node* expression = parse_single_expression(exp_string);
Ast_Node* result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
@@ -123,19 +218,9 @@ testresult test_built_in_substract() {


testresult test_built_in_multiply() {
Ast_Node* times = create_ast_node_symbol("*");
Ast_Node* ten = create_ast_node_number(10);
Ast_Node* four = create_ast_node_number(4);
Ast_Node* nil = create_ast_node_nil();
Ast_Node* form = create_ast_node_pair(
times,
create_ast_node_pair(
ten,
create_ast_node_pair(
four,
nil)));

Ast_Node* result = eval_expr(form, create_empty_environment());
char exp_string[] = "(* 10 4)";
Ast_Node* expression = parse_single_expression(exp_string);
Ast_Node* result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
@@ -147,19 +232,9 @@ testresult test_built_in_multiply() {


testresult test_built_in_divide() {
Ast_Node* over = create_ast_node_symbol("/");
Ast_Node* ten = create_ast_node_number(20);
Ast_Node* four = create_ast_node_number(4);
Ast_Node* nil = create_ast_node_nil();
Ast_Node* form = create_ast_node_pair(
over,
create_ast_node_pair(
ten,
create_ast_node_pair(
four,
nil)));

Ast_Node* result = eval_expr(form, create_empty_environment());
char exp_string[] = "(/ 20 4)";
Ast_Node* expression = parse_single_expression(exp_string);
Ast_Node* result = eval_expr(expression, create_empty_environment());

assert_null(error);
assert_not_null(result);
@@ -171,35 +246,20 @@ testresult test_built_in_divide() {


testresult test_built_in_if() {
Ast_Node* _if = create_ast_node_symbol("if");
Ast_Node* cond = create_ast_node_number(1);
Ast_Node* four = create_ast_node_number(4);
Ast_Node* five = create_ast_node_number(5);
Ast_Node* nil = create_ast_node_nil();
Ast_Node* form = create_ast_node_pair(
_if,
create_ast_node_pair(
cond,
create_ast_node_pair(
four,
create_ast_node_pair(
five,
nil))));
Ast_Node* result;

// test *then* case
result = eval_expr(form, create_empty_environment());
char exp_string1[] = "(if 1 4 5)";
Ast_Node* expression = parse_single_expression(exp_string1);
Ast_Node* result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
assert_equal_int(result->type, Ast_Node_Type_Number);
assert_equal_double(result->value.number->value, 4);

// test *else* case
cond->value.number->value = 0;
result = eval_expr(form, create_empty_environment());
char exp_string2[] = "(if () 4 5)";
expression = parse_single_expression(exp_string2);
result = eval_expr(expression, create_empty_environment());

assert_null(error);
assert_no_error(error);
assert_not_null(result);
assert_equal_int(result->type, Ast_Node_Type_Number);
assert_equal_double(result->value.number->value, 5);
@@ -208,24 +268,9 @@ testresult test_built_in_if() {
}

testresult test_built_in_and() {
Ast_Node* _and = create_ast_node_symbol("and");
Ast_Node* cond1 = create_ast_node_number(1);
Ast_Node* cond2 = create_ast_node_string("asd");
Ast_Node* cond3 = create_ast_node_number(4);
Ast_Node* nil = create_ast_node_nil();
Ast_Node* form = create_ast_node_pair(
_and,
create_ast_node_pair(
cond1,
create_ast_node_pair(
cond2,
create_ast_node_pair(
cond3,
nil))));
Ast_Node* result;

// a true case
result = eval_expr(form, create_empty_environment());
char exp_string1[] = "(and 1 \"asd\" 4)";
Ast_Node* expression = parse_single_expression(exp_string1);
Ast_Node* result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
@@ -233,8 +278,9 @@ testresult test_built_in_and() {
assert_equal_double(result->value.number->value, 1);

// a false case
cond1->value.number->value = 0;
result = eval_expr(form, create_empty_environment());
char exp_string2[] = "(and () \"asd\" 4)";
expression = parse_single_expression(exp_string2);
result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
@@ -244,20 +290,9 @@ testresult test_built_in_and() {
}

testresult test_built_in_or() {
Ast_Node* _or = create_ast_node_symbol("or");
Ast_Node* cond1 = create_ast_node_nil();
Ast_Node* cond2 = create_ast_node_string("asd");
Ast_Node* nil = create_ast_node_nil();
Ast_Node* form = create_ast_node_pair(
_or,
create_ast_node_pair(
cond1,
create_ast_node_pair(
cond2, nil)));
Ast_Node* result;

// a true case
result = eval_expr(form, create_empty_environment());
char exp_string1[] = "(or \"asd\" nil)";
Ast_Node* expression = parse_single_expression(exp_string1);
Ast_Node* result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
@@ -265,14 +300,9 @@ testresult test_built_in_or() {
assert_equal_double(result->value.number->value, 1);

// a false case
cond2 = create_ast_node_nil();
form = create_ast_node_pair(
_or,
create_ast_node_pair(
cond1,
create_ast_node_pair(
cond2, nil)));
result = eval_expr(form, create_empty_environment());
char exp_string2[] = "(or () ())";
expression = parse_single_expression(exp_string2);
result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
@@ -282,9 +312,37 @@ testresult test_built_in_or() {
}


testresult test_built_in_not() {
char exp_string1[] = "(not ())";
Ast_Node* expression = parse_single_expression(exp_string1);
Ast_Node* result = eval_expr(expression, create_empty_environment());

// a true case
assert_no_error(error);
assert_not_null(result);
assert_equal_int(result->type, Ast_Node_Type_Number);
assert_equal_double(result->value.number->value, 1);

// a false case
char exp_string2[] = "(not \"asd xD\")";
expression = parse_single_expression(exp_string2);
result = eval_expr(expression, create_empty_environment());

assert_no_error(error);
assert_not_null(result);
assert_equal_int(result->type, Ast_Node_Type_Nil);

return pass;
}

void run_all_tests() {
log_level = Log_Level_None;

printf("-- Parsing --\n");
invoke_test(test_parse_atom);
invoke_test(test_parse_expression);

printf("\n-- Built ins --\n");
invoke_test(test_built_in_add);
invoke_test(test_built_in_substract);
invoke_test(test_built_in_multiply);
@@ -292,5 +350,7 @@ void run_all_tests() {
invoke_test(test_built_in_if);
invoke_test(test_built_in_and);
invoke_test(test_built_in_or);
invoke_test(test_built_in_not);


}

+ 1
- 0
todo.org Просмотреть файл

@@ -1,3 +1,4 @@
* TODO =assert_equal_type= macro in testing
* Build-in forms

** DONE +


Загрузка…
Отмена
Сохранить