Compare commits
5 Commits
b38b5d220a
...
347512e599
Author | SHA1 | Date | |
---|---|---|---|
347512e599 | |||
abf5e3063a | |||
ac45c1ea84 | |||
b514f5d78b | |||
2710784872 |
@ -1,5 +1,6 @@
|
||||
#include "symbols.h"
|
||||
#include "../error.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -59,12 +60,19 @@ error_t *symbol_table_get_node_info(ast_node_t *node, symbol_kind_t *kind,
|
||||
case NODE_LABEL:
|
||||
*kind = SYMBOL_LOCAL;
|
||||
*name = node->children[0]->token_entry->token.value;
|
||||
break;
|
||||
return nullptr;
|
||||
case NODE_LABEL_REFERENCE:
|
||||
*kind = SYMBOL_REFERENCE;
|
||||
*name = node->token_entry->token.value;
|
||||
break;
|
||||
// TODO: when .import and .export directives are created add them here
|
||||
return nullptr;
|
||||
case NODE_IMPORT_DIRECTIVE:
|
||||
*kind = SYMBOL_IMPORT;
|
||||
*name = node->children[1]->token_entry->token.value;
|
||||
return nullptr;
|
||||
case NODE_EXPORT_DIRECTIVE:
|
||||
*kind = SYMBOL_EXPORT;
|
||||
*name = node->children[1]->token_entry->token.value;
|
||||
return nullptr;
|
||||
default:
|
||||
return err_symbol_table_invalid_node;
|
||||
}
|
||||
@ -117,6 +125,8 @@ error_t *symbol_table_add(symbol_table_t *table, char *name, symbol_kind_t kind,
|
||||
.node = node,
|
||||
};
|
||||
|
||||
table->len += 1;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ parse_result_t parse_register_expression(tokenlist_entry_t *current) {
|
||||
}
|
||||
|
||||
parse_result_t parse_immediate(tokenlist_entry_t *current) {
|
||||
parser_t parsers[] = {parse_number, parse_identifier, nullptr};
|
||||
parser_t parsers[] = {parse_number, parse_label_reference, nullptr};
|
||||
parse_result_t result = parse_any(current, parsers);
|
||||
return parse_result_wrap(NODE_IMMEDIATE, result);
|
||||
}
|
||||
|
12
tests/input/symbols.asm
Normal file
12
tests/input/symbols.asm
Normal file
@ -0,0 +1,12 @@
|
||||
.import test
|
||||
.export test
|
||||
test:
|
||||
call test
|
||||
.import more
|
||||
.export more
|
||||
more:
|
||||
call more
|
||||
.import other
|
||||
.export other
|
||||
other:
|
||||
call other
|
@ -2,12 +2,14 @@
|
||||
|
||||
extern MunitTest ast_tests[];
|
||||
extern MunitTest lexer_tests[];
|
||||
extern MunitTest symbols_tests[];
|
||||
|
||||
int main(int argc, char *argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
|
||||
MunitSuite suites[] = {
|
||||
{"/ast", ast_tests, nullptr, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{"/lexer", lexer_tests, nullptr, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{nullptr, nullptr, nullptr, 0, MUNIT_SUITE_OPTION_NONE},
|
||||
{"/ast", ast_tests, nullptr, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{"/lexer", lexer_tests, nullptr, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{"/symbols", symbols_tests, nullptr, 1, MUNIT_SUITE_OPTION_NONE},
|
||||
{nullptr, nullptr, nullptr, 0, MUNIT_SUITE_OPTION_NONE},
|
||||
};
|
||||
|
||||
MunitSuite master_suite = {"/oas", nullptr, suites, 1, MUNIT_SUITE_OPTION_NONE};
|
||||
|
175
tests/symbols.c
Normal file
175
tests/symbols.c
Normal file
@ -0,0 +1,175 @@
|
||||
#include "../src/encoder/symbols.h"
|
||||
#include "../src/ast.h"
|
||||
#include "../src/error.h"
|
||||
#include "../src/lexer.h"
|
||||
#include "../src/parser/parser.h"
|
||||
#include "munit.h"
|
||||
#include <string.h>
|
||||
|
||||
void symbols_setup_test(ast_node_t **node, tokenlist_t **list, char *path) {
|
||||
lexer_t *lex = &(lexer_t){};
|
||||
lexer_open(lex, path);
|
||||
tokenlist_alloc(list);
|
||||
tokenlist_fill(*list, lex);
|
||||
parse_result_t result = parse((*list)->head);
|
||||
lexer_close(lex);
|
||||
|
||||
*node = result.node;
|
||||
}
|
||||
|
||||
MunitResult test_symbol_table_alloc(const MunitParameter params[], void *data) {
|
||||
(void)params;
|
||||
(void)data;
|
||||
|
||||
symbol_table_t *table = nullptr;
|
||||
error_t *err = symbol_table_alloc(&table);
|
||||
|
||||
munit_assert_ptr_not_null(table);
|
||||
munit_assert_ptr_null(err);
|
||||
munit_assert_size(table->cap, ==, 64); // Default capacity
|
||||
munit_assert_size(table->len, ==, 0);
|
||||
munit_assert_ptr_not_null(table->symbols);
|
||||
|
||||
symbol_table_free(table);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MunitResult test_symbol_table_lookup_empty(const MunitParameter params[], void *data) {
|
||||
(void)params;
|
||||
(void)data;
|
||||
|
||||
symbol_table_t *table = nullptr;
|
||||
symbol_table_alloc(&table);
|
||||
|
||||
symbol_t *symbol = symbol_table_lookup(table, "nonexistent");
|
||||
munit_assert_ptr_null(symbol);
|
||||
|
||||
symbol_table_free(table);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MunitResult test_symbol_add_reference(const MunitParameter params[], void *data) {
|
||||
(void)params;
|
||||
(void)data;
|
||||
ast_node_t *root;
|
||||
tokenlist_t *list;
|
||||
symbol_table_t *table = nullptr;
|
||||
symbols_setup_test(&root, &list, "tests/input/symbols.asm");
|
||||
symbol_table_alloc(&table);
|
||||
|
||||
ast_node_t *reference = root->children[3]->children[1]->children[0]->children[0];
|
||||
munit_assert_int(reference->id, ==, NODE_LABEL_REFERENCE);
|
||||
munit_assert_size(table->len, ==, 0);
|
||||
|
||||
error_t *err = symbol_table_update(table, reference);
|
||||
munit_assert_null(err);
|
||||
munit_assert_size(table->len, ==, 1);
|
||||
|
||||
symbol_t *symbol = symbol_table_lookup(table, "test");
|
||||
munit_assert_not_null(symbol);
|
||||
munit_assert_int(SYMBOL_REFERENCE, ==, symbol->kind);
|
||||
munit_assert_ptr_equal(reference, symbol->node);
|
||||
munit_assert_string_equal(symbol->name, "test");
|
||||
|
||||
symbol_table_free(table);
|
||||
ast_node_free(root);
|
||||
tokenlist_free(list);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MunitResult test_symbol_add_label(const MunitParameter params[], void *data) {
|
||||
(void)params;
|
||||
(void)data;
|
||||
ast_node_t *root;
|
||||
tokenlist_t *list;
|
||||
symbol_table_t *table = nullptr;
|
||||
symbols_setup_test(&root, &list, "tests/input/symbols.asm");
|
||||
symbol_table_alloc(&table);
|
||||
|
||||
ast_node_t *label = root->children[2];
|
||||
munit_assert_int(label->id, ==, NODE_LABEL);
|
||||
munit_assert_size(table->len, ==, 0);
|
||||
|
||||
error_t *err = symbol_table_update(table, label);
|
||||
munit_assert_null(err);
|
||||
munit_assert_size(table->len, ==, 1);
|
||||
|
||||
symbol_t *symbol = symbol_table_lookup(table, "test");
|
||||
munit_assert_not_null(symbol);
|
||||
munit_assert_int(SYMBOL_LOCAL, ==, symbol->kind);
|
||||
munit_assert_ptr_equal(label, symbol->node);
|
||||
munit_assert_string_equal(symbol->name, "test");
|
||||
|
||||
symbol_table_free(table);
|
||||
ast_node_free(root);
|
||||
tokenlist_free(list);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MunitResult test_symbol_add_import(const MunitParameter params[], void *data) {
|
||||
(void)params;
|
||||
(void)data;
|
||||
ast_node_t *root;
|
||||
tokenlist_t *list;
|
||||
symbol_table_t *table = nullptr;
|
||||
symbols_setup_test(&root, &list, "tests/input/symbols.asm");
|
||||
symbol_table_alloc(&table);
|
||||
|
||||
ast_node_t *import_directive = root->children[0]->children[1];
|
||||
munit_assert_int(import_directive->id, ==, NODE_IMPORT_DIRECTIVE);
|
||||
munit_assert_size(table->len, ==, 0);
|
||||
|
||||
error_t *err = symbol_table_update(table, import_directive);
|
||||
munit_assert_null(err);
|
||||
munit_assert_size(table->len, ==, 1);
|
||||
|
||||
symbol_t *symbol = symbol_table_lookup(table, "test");
|
||||
munit_assert_not_null(symbol);
|
||||
munit_assert_int(SYMBOL_IMPORT, ==, symbol->kind);
|
||||
munit_assert_ptr_equal(import_directive, symbol->node);
|
||||
munit_assert_string_equal(symbol->name, "test");
|
||||
|
||||
symbol_table_free(table);
|
||||
ast_node_free(root);
|
||||
tokenlist_free(list);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MunitResult test_symbol_add_export(const MunitParameter params[], void *data) {
|
||||
(void)params;
|
||||
(void)data;
|
||||
ast_node_t *root;
|
||||
tokenlist_t *list;
|
||||
symbol_table_t *table = nullptr;
|
||||
symbols_setup_test(&root, &list, "tests/input/symbols.asm");
|
||||
symbol_table_alloc(&table);
|
||||
|
||||
ast_node_t *export_directive = root->children[1]->children[1];
|
||||
munit_assert_int(export_directive->id, ==, NODE_EXPORT_DIRECTIVE);
|
||||
munit_assert_size(table->len, ==, 0);
|
||||
|
||||
error_t *err = symbol_table_update(table, export_directive);
|
||||
munit_assert_null(err);
|
||||
munit_assert_size(table->len, ==, 1);
|
||||
|
||||
symbol_t *symbol = symbol_table_lookup(table, "test");
|
||||
munit_assert_not_null(symbol);
|
||||
munit_assert_int(SYMBOL_EXPORT, ==, symbol->kind);
|
||||
munit_assert_ptr_equal(export_directive, symbol->node);
|
||||
munit_assert_string_equal(symbol->name, "test");
|
||||
|
||||
symbol_table_free(table);
|
||||
ast_node_free(root);
|
||||
tokenlist_free(list);
|
||||
return MUNIT_OK;
|
||||
}
|
||||
|
||||
MunitTest symbols_tests[] = {
|
||||
{"/table_alloc", test_symbol_table_alloc, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr},
|
||||
{"/table_lookup_empty", test_symbol_table_lookup_empty, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr},
|
||||
{"/add_reference", test_symbol_add_reference, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr},
|
||||
{"/add_label", test_symbol_add_label, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr},
|
||||
{"/add_import", test_symbol_add_import, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr},
|
||||
{"/add_export", test_symbol_add_export, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr},
|
||||
{nullptr, nullptr, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user