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

Renamed cli.h into cli.hpp, used structured bindings, made cli and compiler more consistent #24

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
File renamed without changes.
2 changes: 1 addition & 1 deletion src/cli.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <cli.h>
#include <cli.hpp>

CommandLineArguments ParseCommandLineArgs(int argc, char **argv)
{
Expand Down
59 changes: 34 additions & 25 deletions src/compiler.cpp
Original file line number Diff line number Diff line change
@@ -1,69 +1,78 @@
#include <fstream>
#include <iostream>

#include "cli.h"
#include "cli.hpp"
#include "ast.hpp"

using ast::NodePtr;

NodePtr Parse(const CommandLineArguments& args);
// Wrapper for ParseAST defined in YACC
NodePtr Parse(const std::string& compile_source_path);
Copy link
Collaborator

@simon-staal simon-staal Mar 22, 2024

Choose a reason for hiding this comment

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

This might be a bit too extra, but it might be worth considering using std::filesystem::path rather than strings? This has the benefit of making it clear that this variable represents a file path from its type rather than its name, which is usually an improvement imo - but if you think it's not worth the complexity / overhead for students happy for you to keep it as is. I think that this coursework is a good opportunity for us to teach students about the features of modern C++, but defs think we need to pick our battles with what we want to include (and smart pointers might be enough of a step for them 😅)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Another interesting choice between teaching modern C++ vs not scaring students too much. I can see both points being made here and I'm slightly in favor of including this change as it doesn't look too complex and should be understandable from the type name itself. Any strong opinions @Jpnock?

Copy link
Collaborator

@Jpnock Jpnock Mar 25, 2024

Choose a reason for hiding this comment

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

but it might be worth considering using std::filesystem::path

Sounds good to me


// Output the pretty print version of what was parsed to the .printed output
// file.
void PrettyPrint(const NodePtr& root, const CommandLineArguments& args);
// Output the pretty print version of what was parsed to the .printed output file.
void PrettyPrint(const NodePtr& root, const std::string& compile_output_path);

// Compile from the root of the AST and output this to the
// args.compiledOutputPath file.
void Compile(const NodePtr& root, const CommandLineArguments& args);
// Compile from the root of the AST and output this to the compiledOutputPath file.
void Compile(const NodePtr& root, const std::string& compile_output_path);

int main(int argc, char **argv)
{
// Parse CLI arguments to fetch the source file to compile and the path to output to.
// This retrives [source-file.c] and [dest-file.s], when the compiler is invoked as follows:
// ./bin/c_compiler -S [source-file.c] -o [dest-file.s]
auto command_line_arguments = ParseCommandLineArgs(argc, argv);
const auto [compile_source_path, compile_output_path] = ParseCommandLineArgs(argc, argv);
Jpnock marked this conversation as resolved.
Show resolved Hide resolved

// Parse input and generate AST
auto ast_root = Parse(command_line_arguments);
// Parse input and generate AST.
auto ast_root = Parse(compile_source_path);

// Check something was actually returned by parseAST().
if (ast_root == nullptr)
{
// Check something was actually returned by parseAST().
std::cerr << "The root of the AST was a null pointer. Likely the root was never initialised correctly during parsing." << std::endl;
std::cerr << "The root of the AST is a null pointer. ";
std::cerr << "Likely the root was never initialised correctly during parsing." << std::endl;
return 3;
}

PrettyPrint(ast_root, command_line_arguments);
Compile(ast_root, command_line_arguments);
// Print AST in a human-readable way. It's not assessed, but exists for your convenience.
PrettyPrint(ast_root, compile_output_path);

// Compile to RISC-V assembly, the main goal of this project.
Compile(ast_root, compile_output_path);
}

NodePtr Parse(const CommandLineArguments& args)
NodePtr Parse(const std::string& compile_source_path)
{
std::cout << "Parsing: " << args.compile_source_path << std::endl;
NodePtr root = ParseAST(args.compile_source_path);
std::cout << "Parsing ..." << compile_source_path << std::endl;

NodePtr root = ParseAST(compile_source_path);

std::cout << "AST parsing complete" << std::endl;

return root;
}

void PrettyPrint(const NodePtr& root, const CommandLineArguments& args)
void PrettyPrint(const NodePtr& root, const std::string& compile_output_path)
{
auto output_path = args.compile_output_path + ".printed";
auto output_path = compile_output_path + ".printed";

std::cout << "Printing parsed AST..." << std::endl;

std::ofstream output(output_path, std::ios::trunc);
root->Print(output);
output.close();

std::cout << "Printed parsed AST to: " << output_path << std::endl;
}

void Compile(const NodePtr& root, const CommandLineArguments& args)
void Compile(const NodePtr& root, const std::string& compile_output_path)
{
// Create a Context. This can be used to pass around information about
// what's currently being compiled (e.g. function scope and variable names).
ast::Context ctx;

std::cout << "Compiling parsed AST..." << std::endl;
std::ofstream output(args.compile_output_path, std::ios::trunc);

std::ofstream output(compile_output_path, std::ios::trunc);
root->EmitRISC(output, ctx);
output.close();
std::cout << "Compiled to: " << args.compile_output_path << std::endl;

std::cout << "Compiled to: " << compile_output_path << std::endl;
}
Loading