Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat) code generator addition #7

Merged
merged 17 commits into from
Oct 29, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions src/code_generator.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "code_generator.h"

#include <stdio.h>
#include <stdbool.h>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Includes should be placed in .h file. The only .h file which should be included in .c file - is the header file. In your case - code_generator.h.


// Assign a value to a variable
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look here:

Functions should be commented in Doxygen style.

For example this function declaration should be commented like

/**
 * Creates tree node with value
 * @param value value in the node
 * @return pointer to the tree node
 */
tree_node *create_node(int value);

It is enough to comment just function declarations, without commenting implementation in C files. Your IDE will probably automatically highlight such a comment as a function comment. First and next lines contain function description. There may be some keywords starting with @ sign after them. IDE may also suggest some keywords. Probably will be needed only @param which is used to describe function parameter and @return which is used to describe what is returned from function.

So don't write any comments in .c files. It is better to move them to .h files and follow Doxygen format

void generate_move(char *parameter_frame, char *parameter, char *variable_frame, char *variable) {
fprintf(fd, "MOVE %s%s %s%s\n", parameter_frame, parameter, variable_frame, variable);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the task, there must be @ signs between frame and variable name in the MOVE instruction

By the way, maybe it would be better to name function parameters according to the task - first and second are variable frame and variable, third and fourth - symbol frame and symbol.

}

// Create a new temporary frame
void generate_create_frame() {
fprintf(fd, "CREATEFRAME\n");
}

// Push a frame to the stack
void generate_push_frame() {
fprintf(fd, "PUSHFRAME\n");
}

// Pop a frame from the stack
void generate_pop_frame() {
fprintf(fd, "POPFRAME\n");
}

// Define a new variable in the frame
void generate_declaration(char *variable_frame, char *variable) {
fprintf(fd, "DEFVAR %s%s\n", variable_frame, variable);
}

// Jump on a sign with return support
void generate_call(char *label) {
fprintf(fd, "CALL $%s\n", label);
}

// Put the value on the top of the stack
void generate_push(char *variable_frame, char *variable) {
fprintf(fd, "PUSHS %s%s\n", variable_frame, variable);
}

// Sum of two numerical values
void generate_add(char *result, char *symbol1, char *symbol2) {
fprintf(fd, "ADD LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the following instructions always contains LF as a frame. Can this frame be changed or there is always used LF as a frame in these instructions?

}

// Subtraction of two numerical values
void generate_sub(char *result, char *symbol1, char *symbol2) {
fprintf(fd, "SUB LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
}

// Multiplication of two numerical values
void generate_mul(char *result, char *symbol1, char *symbol2) {
fprintf(fd, "MUL LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
}

// Division of two numerical values
void generate_idiv(char *result, char *symbol1, char *symbol2) {
fprintf(fd, "IDIV LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
}

// Compare two values for lower that
void generate_lt(char *result, char *symbol1, char *symbol2) {
fprintf(fd, "LT LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
}

// Compare two values for greater than
void generate_gt(char *result, char *symbol1, char *symbol2) {
fprintf(fd, "GT LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
}

// Compare two values for equality
void generate_eq(char *result, char *symbol1, char *symbol2) {
fprintf(fd, "EQ LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
}

// Compare two values with logical AND
void generate_and(char *result, char *symbol1, char *symbol2) {
fprintf(fd, "AND LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
}

// Compare two values with logical OR
void generate_or(char *result, char *symbol1, char *symbol2) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many functions are repeating in their arguments. Maybe it might be useful to union them into one universal function? For passing instruction keyword to this function can be used predefined enum with all instructions of similar type.

fprintf(fd, "OR LF@%s LF@%s LF@%s\n", result, symbol1, symbol2);
}

// Compare two values with logical NOT
void generate_not(char *result, char *symbol) {
fprintf(fd, "NOT LF@%s LF@%s\n", result, symbol);
}

void generate_end() {
printf("\nPOPFRAME");
printf("\nRETURN");
}

int test_code_generator() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should not exist, when tests with googletest will be added

fd = fopen("test.txt", "w");
generate_move("GF", "a", "GF", "b");
generate_create_frame();
generate_push_frame();
generate_pop_frame();
generate_declaration("GF", "c");
generate_call("test");
generate_push("GF", "a");
generate_add("c", "a", "b");
generate_sub("c", "a", "b");
generate_mul("c", "a", "b");
generate_idiv("c", "a", "b");
generate_lt("c", "a", "b");
generate_gt("c", "a", "b");
generate_eq("c", "a", "b");
generate_and("c", "a", "b");
generate_or("c", "a", "b");
generate_not("c", "a");
fclose(fd);
return 0;
}





NickSettler marked this conversation as resolved.
Show resolved Hide resolved
21 changes: 21 additions & 0 deletions src/code_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef IFJ_PROJ_2022_CODE_GENERATOR_H
NickSettler marked this conversation as resolved.
Show resolved Hide resolved
#define IFJ_PROJ_2022_CODE_GENERATOR_H

FILE* fd; //file for testing
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For testing you can use GoogleTest framework. Take a look at the tests directory. The LexicalAnalyzerTest for now is the largest test. You can use it as an example for writing own tests. IMHO, it maybe enough to add a test for each function and tests, which will have more than a one function - just to check line breaks and stuff like that.


void generate_move(char *parameter_frame, char *parameter, char *variable_frame, char *variable);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we should add to every function a parameter. String to which function will append instruction string. So these functions can be easily used for tests. For this purpose is appropriate to use string_t type. Its function string_append_string can be used to append a custom char*.

void generate_create_frame();
void generate_push_frame();
void generate_pop_frame();
void generate_declaration(char* variable_frame, char* variable);
void generate_call(char *label);
void generate_push(char* variable_frame, char* variable);
void generate_add(char* result, char* symbol1, char* symbol2);
void generate_sub (char* result, char* symbol1, char* symbol2);
void generate_mul (char* result, char* symbol1, char* symbol2);
void generate_idiv (char* result, char* symbol1, char* symbol2);
void generate_lt (char* result, char* symbol1, char* symbol2);
void generate_gt (char* result, char* symbol1, char* symbol2);
void generate_eq (char* result, char* symbol1, char* symbol2);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some functions are missing. Instruction set in the task file contains about 40 instructions. I've counted 14 here


#endif //IFJ_PROJ_2022_CODE_GENERATOR_H