mirror of
https://github.com/iritmaximus/ttk91-compiler.git
synced 2026-10-12 19:13:40 +03:00
implemented many unit tests
This commit is contained in:
+45
-3
@@ -1,6 +1,21 @@
|
||||
cmake_minimum_required(VERSION 4.0)
|
||||
project(ttk91_compiler C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
# creates compile_commands.json
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
|
||||
# Googletest (aka gtest)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||
)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# https://cmake.org/cmake/help/latest/module/FindBISON.html
|
||||
find_package(BISON)
|
||||
bison_target(
|
||||
@@ -20,7 +35,6 @@ flex_target(
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
src/main.c
|
||||
src/parser.c
|
||||
src/scanner.c
|
||||
src/program.c
|
||||
@@ -32,6 +46,34 @@ set(SOURCES
|
||||
src/comment.c
|
||||
)
|
||||
|
||||
add_executable(ttk91_compiler ${SOURCES})
|
||||
add_library(ttk91_compiler_lib ${SOURCES})
|
||||
add_executable(ttk91_compiler src/main.c)
|
||||
|
||||
target_include_directories(ttk91_compiler PRIVATE include)
|
||||
target_include_directories(ttk91_compiler PRIVATE include)
|
||||
target_include_directories(ttk91_compiler_lib PRIVATE include)
|
||||
target_link_libraries(ttk91_compiler ttk91_compiler_lib)
|
||||
|
||||
|
||||
# Testing
|
||||
enable_testing()
|
||||
|
||||
set(TESTING_SOURCES
|
||||
test/comment.cpp
|
||||
test/label.cpp
|
||||
test/value.cpp
|
||||
test/ttk_register.cpp
|
||||
test/oper.cpp
|
||||
test/expr.cpp
|
||||
${SOURCES}
|
||||
)
|
||||
|
||||
add_executable(tests ${TESTING_SOURCES})
|
||||
|
||||
target_link_libraries(
|
||||
tests
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
target_include_directories(tests PRIVATE include)
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(tests)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef LABEL_H
|
||||
#define LABEL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "expr.h"
|
||||
|
||||
typedef enum {
|
||||
@@ -15,6 +16,7 @@ struct label {
|
||||
};
|
||||
|
||||
struct label * label_create(label_t kind, char* name, int value);
|
||||
int label_to_string(char* buffer, const size_t size, struct label *l);
|
||||
int label_print_intel_asm(struct label *l);
|
||||
int label_print(struct label *l);
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef REGISTER_H
|
||||
#define REGISTER_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum {
|
||||
TTK_REGISTER,
|
||||
STACK_TTK_REGISTER
|
||||
@@ -17,6 +19,8 @@ int parse_register_num(char *name, ttk_register_t kind);
|
||||
struct ttk_register * ttk_register_create_register(char* name);
|
||||
struct ttk_register * ttk_register_create_stack_register(char* name);
|
||||
|
||||
int ttk_register_to_string(char* buffer, size_t size, struct ttk_register *ttk_reg);
|
||||
int ttk_register_to_intel_asm_string(char* buffer, size_t size, struct ttk_register *ttk_reg);
|
||||
int ttk_register_print(struct ttk_register *ttk_reg);
|
||||
int ttk_register_print_intel_asm(struct ttk_register *ttk_reg);
|
||||
|
||||
|
||||
+22
-7
@@ -23,6 +23,23 @@ struct label * label_create_const(char* name) { return label_create(LABEL_
|
||||
struct label * label_create_const_sys(char* name) { return label_create(LABEL_CONST, name, 0); } // FIXME value
|
||||
struct label * label_create_tag(char* name) { return label_create(LABEL_TAG, name, 0); } // FIXME also this
|
||||
|
||||
int label_to_string(char* buffer, size_t size, struct label *l) {
|
||||
if (size < 2) {
|
||||
printf("ERROR: Buffer size too small (label)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!l->name)
|
||||
{
|
||||
printf("ERROR: Label name doesn't exist.\n");
|
||||
snprintf(buffer, size, "???");
|
||||
return VARIABLE_NULL;
|
||||
}
|
||||
|
||||
snprintf(buffer, size, "%s", l->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int label_print_intel_asm(struct label *l)
|
||||
{
|
||||
return label_print(l);
|
||||
@@ -30,18 +47,16 @@ int label_print_intel_asm(struct label *l)
|
||||
|
||||
int label_print(struct label *l)
|
||||
{
|
||||
if (!l->name)
|
||||
{
|
||||
printf("ERROR: Label name doesn't exist.\n");
|
||||
return VARIABLE_NULL;
|
||||
}
|
||||
size_t size = 50;
|
||||
char buffer[size];
|
||||
|
||||
printf("%s", l->name);
|
||||
label_to_string(buffer, size, l);
|
||||
printf("%s", buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void label_free(struct label *l)
|
||||
{
|
||||
if (l->name) free(l->name);
|
||||
// if (l->name) free(l->name);
|
||||
free(l);
|
||||
}
|
||||
|
||||
+101
-50
@@ -1,6 +1,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include "error.h"
|
||||
#include "ttk_register.h"
|
||||
|
||||
@@ -37,8 +39,8 @@ struct ttk_register * ttk_register_create_stack_register(char* name)
|
||||
|
||||
int parse_register_num(char* name, ttk_register_t kind)
|
||||
{
|
||||
if (!name) {
|
||||
printf("Name null while parsing register name.\n");
|
||||
if (!name || strcmp(name, "") == 0) {
|
||||
printf("ERROR: Name null or empty while parsing register name.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -49,87 +51,136 @@ int parse_register_num(char* name, ttk_register_t kind)
|
||||
case TTK_REGISTER:
|
||||
char num = name[1]; // registers have the format RX, 'R' + X 0-7
|
||||
value = num - '0';
|
||||
break;
|
||||
case STACK_TTK_REGISTER:
|
||||
if (strcasecmp("sp", name) == 0)
|
||||
value = 6;
|
||||
if (0 <= value && value <= 8)
|
||||
break;
|
||||
else
|
||||
assert(false && "Incorrect register name value");
|
||||
|
||||
if (strcasecmp("fp", name) == 0)
|
||||
case STACK_TTK_REGISTER:
|
||||
value = -1;
|
||||
|
||||
if (strcasecmp("sp", name) == 0) {
|
||||
value = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
else if (strcasecmp("fp", name) == 0) {
|
||||
value = 7;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
else
|
||||
assert(false && "Stack register not 6 or 7");
|
||||
|
||||
default:
|
||||
free(name);
|
||||
printf("Register type not matched while parsing register name.\n");
|
||||
return -1;
|
||||
assert(false && "Register kind not matched while parsing register name.");
|
||||
break;
|
||||
}
|
||||
|
||||
free(name);
|
||||
return value;
|
||||
}
|
||||
|
||||
int ttk_register_print_intel_asm(struct ttk_register *ttk_reg)
|
||||
{
|
||||
// EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI
|
||||
if (!ttk_reg || !ttk_reg->id)
|
||||
int ttk_register_to_string(char* buffer, size_t size, struct ttk_register *ttk_reg) {
|
||||
if (size < 3) {
|
||||
printf("ERROR: Buffer size too small (ttk_reg_to_string)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ttk_reg)
|
||||
{
|
||||
printf("ttk_register missing while trying to print it.\n");
|
||||
printf("ERROR: ttk_register missing while trying to print it.\n");
|
||||
return VARIABLE_NULL;
|
||||
}
|
||||
|
||||
switch (ttk_reg->id)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
printf("eax");
|
||||
break;
|
||||
case 2:
|
||||
printf("ebx");
|
||||
break;
|
||||
case 3:
|
||||
printf("ecx");
|
||||
break;
|
||||
case 4:
|
||||
printf("edx");
|
||||
break;
|
||||
case 5:
|
||||
printf("esp");
|
||||
snprintf(buffer, size, "R%d", ttk_reg->id);
|
||||
break;
|
||||
case 6:
|
||||
printf("ebp");
|
||||
snprintf(buffer, size, "SP");
|
||||
break;
|
||||
case 7:
|
||||
printf("esi");
|
||||
break;
|
||||
case 0:
|
||||
printf("edi"); // TODO: this is possibly not correct
|
||||
snprintf(buffer, size, "FP");
|
||||
break;
|
||||
default:
|
||||
printf("ERROR: No matching register\n");
|
||||
return SWITCH_NOT_MATCHED;
|
||||
assert(false && "No register id matched\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ttk_register_to_intel_asm_string(char* buffer, size_t size, struct ttk_register *ttk_reg)
|
||||
{
|
||||
if (size < 5) {
|
||||
printf("ERROR: Buffer size too small (ttk_reg_to_string)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ttk_reg)
|
||||
{
|
||||
printf("ERROR: ttk_register missing while trying to print it.\n");
|
||||
return VARIABLE_NULL;
|
||||
}
|
||||
|
||||
// TODO: this is possibly not correct
|
||||
// EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI
|
||||
switch (ttk_reg->id)
|
||||
{
|
||||
case 1:
|
||||
snprintf(buffer, size, "eax");
|
||||
break;
|
||||
case 2:
|
||||
snprintf(buffer, size, "ebx");
|
||||
break;
|
||||
case 3:
|
||||
snprintf(buffer, size, "ecx");
|
||||
break;
|
||||
case 4:
|
||||
snprintf(buffer, size, "edx");
|
||||
break;
|
||||
case 5:
|
||||
snprintf(buffer, size, "esp");
|
||||
break;
|
||||
case 6:
|
||||
snprintf(buffer, size, "ebp");
|
||||
break;
|
||||
case 7:
|
||||
snprintf(buffer, size, "esi");
|
||||
break;
|
||||
case 0:
|
||||
snprintf(buffer, size, "edi");
|
||||
break;
|
||||
default:
|
||||
assert(false && "No matching register");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ttk_register_print_intel_asm(struct ttk_register *ttk_reg)
|
||||
{
|
||||
size_t size = 5;
|
||||
char buffer[size];
|
||||
|
||||
ttk_register_to_intel_asm_string(buffer, size, ttk_reg);
|
||||
printf("%s", buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ttk_register_print(struct ttk_register *ttk_reg)
|
||||
{
|
||||
if (!ttk_reg || !ttk_reg->id)
|
||||
{
|
||||
printf("ttk_register missing while trying to print it.\n");
|
||||
return VARIABLE_NULL;
|
||||
}
|
||||
switch (ttk_reg->id)
|
||||
{
|
||||
case 6:
|
||||
printf("SP");
|
||||
return 0;
|
||||
case 7:
|
||||
printf("FP");
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
size_t size = 3;
|
||||
char buffer[size];
|
||||
|
||||
printf("R%d", ttk_reg->id);
|
||||
ttk_register_to_string(buffer, size, ttk_reg);
|
||||
printf("%s", buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
extern "C" {
|
||||
#include "comment.h"
|
||||
}
|
||||
|
||||
TEST(Test_comments, Test_comments_TODO) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
extern "C" {
|
||||
#include "expr.h"
|
||||
}
|
||||
|
||||
TEST(Test_expressions, Test_expr_TODO) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
extern "C" {
|
||||
#include "label.h"
|
||||
}
|
||||
|
||||
TEST(Test_labels, Test_label_print_with_valid_parameter) {
|
||||
const size_t size = 10;
|
||||
char buffer[size];
|
||||
char label_name[] = "X";
|
||||
|
||||
struct label *l = label_create_const(label_name);
|
||||
label_to_string(buffer, size, l);
|
||||
|
||||
EXPECT_STREQ(label_name, buffer);
|
||||
|
||||
label_free(l);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
extern "C" {
|
||||
#include "oper.h"
|
||||
}
|
||||
|
||||
TEST(Test_opers, Test_opers_TODO) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
extern "C" {
|
||||
#include "ttk_register.h"
|
||||
#include "error.h"
|
||||
}
|
||||
|
||||
TEST(Test_ttk_registers, parse_register_num_fails_with_empty_name) {
|
||||
char empty_name[] = "";
|
||||
char* null_name = NULL;
|
||||
const ttk_register_t kind = TTK_REGISTER;
|
||||
|
||||
int result_empty = parse_register_num(empty_name, kind);
|
||||
int result_null = parse_register_num(null_name, kind);
|
||||
|
||||
EXPECT_EQ(-1, result_empty);
|
||||
EXPECT_EQ(-1, result_null);
|
||||
}
|
||||
|
||||
TEST(Test_ttk_registers, parse_register_num_returns_correct_value_ttk_reg) {
|
||||
char name0[] = "R0";
|
||||
char name3[] = "R3";
|
||||
char name6[] = "R6"; // also SP
|
||||
const ttk_register_t kind = TTK_REGISTER;
|
||||
|
||||
int result0 = parse_register_num(name0, kind);
|
||||
int result3 = parse_register_num(name3, kind);
|
||||
int result6 = parse_register_num(name6, kind);
|
||||
|
||||
EXPECT_EQ(0, result0);
|
||||
EXPECT_EQ(3, result3);
|
||||
EXPECT_EQ(6, result6);
|
||||
}
|
||||
|
||||
TEST(Test_ttk_registers, parse_register_num_returns_correct_value_stack_registers) {
|
||||
char name_sp[] = "SP";
|
||||
char name_fp[] = "FP";
|
||||
const ttk_register_t kind = STACK_TTK_REGISTER;
|
||||
|
||||
int result_sp = parse_register_num(name_sp, kind);
|
||||
int result_fp = parse_register_num(name_fp, kind);
|
||||
|
||||
EXPECT_EQ(result_sp, 6);
|
||||
EXPECT_EQ(result_fp, 7);
|
||||
}
|
||||
|
||||
|
||||
TEST(Test_ttk_registers, Test_ttk_register_to_string_valid_parameters) {
|
||||
const size_t size = 3;
|
||||
char buffer0[size];
|
||||
char buffer2[size];
|
||||
char buffer7[size];
|
||||
char reg_name0[] = "R0";
|
||||
char reg_name2[] = "R2";
|
||||
char reg_name7[] = "R7";
|
||||
|
||||
struct ttk_register *ttk_reg0 = ttk_register_create_register(reg_name0);
|
||||
struct ttk_register *ttk_reg2 = ttk_register_create_register(reg_name2);
|
||||
struct ttk_register *ttk_reg7 = ttk_register_create_register(reg_name7);
|
||||
|
||||
EXPECT_EQ(0, ttk_reg0->id);
|
||||
EXPECT_EQ(2, ttk_reg2->id);
|
||||
EXPECT_EQ(7, ttk_reg7->id);
|
||||
|
||||
int res0 = ttk_register_to_string(buffer0, size, ttk_reg0);
|
||||
int res2 = ttk_register_to_string(buffer2, size, ttk_reg2);
|
||||
int res7 = ttk_register_to_string(buffer7, size, ttk_reg7);
|
||||
|
||||
EXPECT_EQ(0, res0);
|
||||
EXPECT_EQ(0, res2);
|
||||
EXPECT_EQ(0, res7);
|
||||
|
||||
EXPECT_STREQ("R0", buffer0);
|
||||
EXPECT_STREQ("R2", buffer2);
|
||||
EXPECT_STREQ("FP", buffer7);
|
||||
|
||||
ttk_register_free(ttk_reg0);
|
||||
ttk_register_free(ttk_reg2);
|
||||
ttk_register_free(ttk_reg7);
|
||||
}
|
||||
|
||||
TEST(Test_ttk_registers, Test_ttk_register_to_string_too_small_buffer_size) {
|
||||
const size_t size = 2;
|
||||
char buffer0[size];
|
||||
char reg_name0[] = "R0";
|
||||
|
||||
struct ttk_register *ttk_reg0 = ttk_register_create_register(reg_name0);
|
||||
EXPECT_EQ(0, ttk_reg0->id);
|
||||
|
||||
// size and buffer too small
|
||||
int res0 = ttk_register_to_string(buffer0, size, ttk_reg0);
|
||||
EXPECT_EQ(-1, res0);
|
||||
|
||||
ttk_register_free(ttk_reg0);
|
||||
}
|
||||
|
||||
TEST(Test_ttk_registers, Test_ttk_register_to_intel_asm_string_too_small_buffer_size) {
|
||||
const size_t size = 4;
|
||||
char buffer[size];
|
||||
char reg_name[] = "R2";
|
||||
|
||||
struct ttk_register *ttk_reg = ttk_register_create_register(reg_name);
|
||||
EXPECT_EQ(2, ttk_reg->id);
|
||||
|
||||
int result = ttk_register_to_intel_asm_string(buffer, size, ttk_reg);
|
||||
EXPECT_EQ(-1, result);
|
||||
|
||||
ttk_register_free(ttk_reg);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
extern "C" {
|
||||
#include "value.h"
|
||||
}
|
||||
|
||||
TEST(Test_values, Test_value_TODO) {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user