Skip to content

Commit 3c115a1

Browse files
committed
Added a basic CLI interface using parametric.
1 parent 0dbc214 commit 3c115a1

File tree

15 files changed

+1210
-214
lines changed

15 files changed

+1210
-214
lines changed

premake5.lua

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,7 @@ project "compiler"
188188
kind "ConsoleApp"
189189
location "source/compiler"
190190

191-
-- debugargs { "compile", "-s", "test/main.s", "-o", "test/app.exe" }
192-
debugargs { "./test/main.s" }
191+
debugargs { "compile", "./test/main.s" }
193192

194193
files {
195194
"source/compiler/**.h",
@@ -226,6 +225,38 @@ project "compiler"
226225
"-lstdc++"
227226
}
228227

228+
workspace "tests"
229+
configurations { "Release", "Debug", "Profile" }
230+
startproject "tests"
231+
232+
architecture "x64"
233+
language "C++"
234+
cppdialect "C++latest"
235+
236+
flags {
237+
"MultiProcessorCompile"
238+
}
239+
240+
filter "configurations:Release"
241+
defines { "NDEBUG" }
242+
optimize "On"
243+
warnings "High"
244+
symbols "Off"
245+
246+
filter "configurations:Debug"
247+
symbols "On"
248+
optimize "Off"
249+
runtime "Debug"
250+
defines { "DEBUG", "_DEBUG" }
251+
warnings "Extra"
252+
253+
filter "configurations:Profile"
254+
defines { "NDEBUG" }
255+
optimize "On"
256+
warnings "High"
257+
symbols "On"
258+
259+
229260
project "tests"
230261
kind "ConsoleApp"
231262
location "source/tests"
@@ -235,6 +266,8 @@ project "tests"
235266
"source/tests/**.cpp"
236267
}
237268

269+
libdirs { "../sigma/output/compiler/bin/%{cfg.buildcfg}" }
270+
238271
includedirs {
239272
"source"
240273
}
@@ -257,4 +290,4 @@ project "tests"
257290

258291
linkoptions {
259292
"-lstdc++"
260-
}
293+
}

source/compiler/compiler/compiler.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ namespace sigma {
2121

2222
auto compiler::compile() const -> utility::result<void> {
2323
utility::console::println("compiling file: {}", m_description.path.string());
24+
25+
ASSERT(m_description.emit != emit_target::EXECUTABLE, "executable support not implemented");
2426
TRY(verify_file(m_description.path));
2527

2628
// frontend
@@ -48,8 +50,11 @@ namespace sigma {
4850
backend.module.compile();
4951

5052
// emit as an object file
51-
const filepath object_path = get_object_file_path();
52-
emit_object_file(backend.module, object_path);
53+
if(m_description.emit == OBJECT) {
54+
const filepath object_path = get_object_file_path();
55+
emit_object_file(backend.module, object_path);
56+
}
57+
5358
return SUCCESS;
5459
}
5560

source/compiler/compiler/compiler.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#pragma once
1414
#include <intermediate_representation/target/target.h>
15+
#include <utility/parametric/parametric.h>
1516
#include <utility/diagnostics.h>
1617
#include <utility/macros.h>
1718

@@ -22,9 +23,16 @@ namespace sigma {
2223
class module;
2324
} // namespace sigma::ir
2425

26+
enum emit_target : u8 {
27+
OBJECT,
28+
EXECUTABLE
29+
};
30+
2531
struct compiler_description {
2632
filepath path;
2733
ir::target target;
34+
35+
emit_target emit;
2836
};
2937

3038
class compiler {
@@ -42,3 +50,51 @@ namespace sigma {
4250
compiler_description m_description;
4351
};
4452
} // namespace sigma
53+
54+
template<>
55+
struct parametric::options_parser<sigma::filepath> {
56+
static auto parse(const std::string& value) -> sigma::filepath {
57+
return value;
58+
}
59+
};
60+
61+
template<>
62+
struct parametric::options_parser<sigma::ir::arch> {
63+
static auto parse(const std::string& value) -> sigma::ir::arch {
64+
if (value == "x64") {
65+
return sigma::ir::arch::X64;
66+
}
67+
68+
throw std::invalid_argument("invalid argument");
69+
}
70+
};
71+
72+
template<>
73+
struct parametric::options_parser<sigma::ir::system> {
74+
static auto parse(const std::string& value) -> sigma::ir::system {
75+
if (value == "windows") {
76+
return sigma::ir::system::WINDOWS;
77+
}
78+
79+
if (value == "linux") {
80+
return sigma::ir::system::WINDOWS;
81+
}
82+
83+
throw std::invalid_argument("invalid argument");
84+
}
85+
};
86+
87+
template<>
88+
struct parametric::options_parser<sigma::emit_target> {
89+
static auto parse(const std::string& value) -> sigma::emit_target {
90+
if (value == "object") {
91+
return sigma::emit_target::OBJECT;
92+
}
93+
94+
if (value == "executable") {
95+
return sigma::emit_target::EXECUTABLE;
96+
}
97+
98+
throw std::invalid_argument("invalid argument");
99+
}
100+
};

source/compiler/main.cpp

Lines changed: 45 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,56 @@
11
#include "compiler/compiler.h"
2-
#include <intermediate_representation/builder.h>
3-
4-
#include "utility/filesystem/file.h"
2+
#include <utility/shell.h>
53

64
using namespace utility::types;
75

8-
auto main(i32 argc, char* argv[]) -> i32 {
9-
SUPPRESS_C4100(argc);
10-
6+
i32 compile(const parametric::parameters& params) {
117
const sigma::compiler_description description {
12-
.path = argv[1],
13-
.target = { sigma::ir::arch::X64, sigma::ir::system::WINDOWS }
8+
.path = params.get<filepath>("file"),
9+
// default to x64 win for now
10+
.target = { sigma::ir::arch::X64, sigma::ir::system::WINDOWS },
11+
.emit = params.get<sigma::emit_target>("emit")
1412
};
1513

1614
// compile the specified description, check for errors after we finish
17-
PRINT_ERROR(sigma::compiler::compile(description));
18-
return 0;
15+
const auto result = sigma::compiler::compile(description);
16+
17+
if (result.has_error()) {
18+
utility::console::println(result.get_error_message());
19+
return 1;
20+
}
1921

20-
//sigma::ir::target target(sigma::ir::arch::X64, sigma::ir::system::WINDOWS);
21-
//sigma::ir::module module(target);
22-
//sigma::ir::builder builder(module);
23-
24-
//// printf
25-
//const sigma::ir::function_signature printf_func_ty{
26-
// .identifier = "printf",
27-
// .parameters = { PTR_TYPE },
28-
// .returns = { I32_TYPE },
29-
// .has_var_args = true
30-
//};
31-
32-
//const auto printf_external = builder.create_external(printf_func_ty, sigma::ir::linkage::SO_LOCAL);
33-
34-
//// test
35-
//const sigma::ir::function_signature test_func_ty {
36-
// .identifier = "test",
37-
// .parameters = { },
38-
// .returns = { I32_TYPE },
39-
// .has_var_args = false
40-
//};
41-
42-
//const auto test = builder.create_function(test_func_ty, sigma::ir::linkage::PUBLIC);
43-
//const auto message = builder.create_string("test\n");
44-
//builder.create_call(printf_external, printf_func_ty, { message });
45-
//builder.create_return({ builder.create_signed_integer(0, 32) });
46-
47-
//// main
48-
//const sigma::ir::function_signature main_func_ty{
49-
//.identifier = "main",
50-
//.returns = { I32_TYPE }
51-
//};
52-
53-
//builder.create_function(main_func_ty, sigma::ir::linkage::PUBLIC);
54-
//builder.create_call(test, {});
55-
//builder.create_return({ builder.create_signed_integer(0, 32) });
56-
57-
//module.compile();
58-
59-
//auto object_file = module.generate_object_file();
60-
//utility::file::write(object_file, "./test/a.obj");
6122
return 0;
6223
}
24+
25+
i32 show_docs(const parametric::parameters& params) {
26+
SUPPRESS_C4100(params);
27+
28+
// TODO: add a link to the relevant github wiki
29+
const std::string link = "https://github.com/Goubermouche/sigma";
30+
31+
if(utility::shell::open_link(link) == 0) {
32+
return 0;
33+
}
34+
35+
std::cout << std::format("error: unable to open the documentation link ({})\n", link);
36+
return 1;
37+
}
38+
39+
auto main(i32 argc, char* argv[]) -> i32 {
40+
parametric::program program;
41+
42+
// compilation
43+
auto& compile_command = program.add_command("compile", "compile the specified source file", compile);
44+
45+
compile_command.add_positional_argument<filepath>("file", "source file to compile");
46+
compile_command.add_flag<sigma::ir::arch>("arch", "CPU architecture to compile for [x64]");
47+
compile_command.add_flag<sigma::ir::system>("system", "operating system to compile for [windows, linux]");
48+
compile_command.add_flag<sigma::emit_target>("emit", "file the compiler should emit [object, executable]", "e", sigma::emit_target::OBJECT);
49+
50+
// TODO: add support for emitting multiple files at once
51+
52+
// documentation
53+
program.add_command("docs", "show project documentation", show_docs);
54+
55+
return program.parse(argc, argv);
56+
}

source/compiler/test/main.s

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
// - linking: link /OUT:a.exe a.obj /LIBPATH:C:\dev\projects\sigma\source\compiler\test\libraries libcmt.lib libvcruntime.lib libucrt.lib
33

44
// TODO:
5-
// - stack scope system
6-
// - typechecker
7-
// - convert values into IR types ?
85
// - parser
96
// - check for memory oversteps
107
// - IR translator

source/tests/main.cpp

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,68 @@
11
#include <utility/diagnostics.h>
22
#include <utility/filesystem/file.h>
3-
#include <utility/containers/stack.h>
3+
#include <utility/string_helper.h>
44

55
// Runs all tests in sigma/tests and checks against a database of expected results. Should only
66
// be invoked via the run_tests.bat file.
77

8-
#define WIN_COMPILER_PATH utility::fs::get_canonical_path("./output/compiler/bin/Debug/compiler.exe").string()
9-
#define ERR_FILE_PATH "err.txt"
10-
8+
//#define WIN_COMPILER_PATH utility::fs::get_canonical_path("../../../../output/compiler/bin/Debug/compiler.exe").string()
9+
//#define ERR_FILE_PATH "err.txt"
10+
//
1111
using namespace utility::types;
12+
//
13+
//auto compile_file(const filepath& path) -> utility::result<bool> {
14+
// const std::string command = WIN_COMPILER_PATH + " " + utility::fs::get_canonical_path(path).string() + " NO_EMIT" + " 1> err.txt";
15+
// const bool has_error = system(command.c_str());
16+
//
17+
// if(has_error) {
18+
// TRY(std::string message, utility::file::read_text_file(ERR_FILE_PATH));
19+
//
20+
// // message = utility::detail::remove_first_line(message);
21+
// // message.erase(message.size() - 1); // remove the trailing newline
22+
// // utility::console::println("\033[31m'{}'\033[0m", message);
23+
// }
24+
//
25+
// return has_error;
26+
//}
1227

13-
auto compile_file(const filepath& path) -> bool {
14-
const std::string command = WIN_COMPILER_PATH + " " + utility::fs::get_canonical_path(path).string() + " 1> err.txt";
15-
const bool error = system(command.c_str());
16-
17-
if(error) {
18-
// std::string message = utility::file::read_text_file(ERR_FILE_PATH);
19-
// message.erase(message.size() - 1); // remove the trailing newline
20-
// utility::console::println("\033[31m'{}'\033[0m", message);
21-
}
22-
23-
return error;
24-
}
25-
26-
i32 main() {
27-
std::queue<filepath> paths({ utility::fs::get_canonical_path("./tests") });
28-
29-
utility::console::println("running tests...");
30-
utility::console::println("{}", std::string(32, '-'));
31-
32-
while(!paths.empty()) {
33-
const filepath current = paths.front();
34-
paths.pop();
35-
36-
utility::directory::for_all_directory_items(current, [&](const filepath& path) {
37-
if(utility::fs::is_directory(path)) {
38-
paths.push(path);
39-
return;
40-
}
41-
42-
static const char* result_codes[] = {
43-
"OK",
44-
"ERROR",
45-
};
46-
47-
const bool error = compile_file(path);
48-
utility::console::println("{:<30}{}", path.stem().string(), result_codes[error]);
49-
});
50-
}
28+
//i32 main() {
29+
// std::queue<filepath> paths({ utility::fs::get_canonical_path("../../../../tests") });
30+
//
31+
// std::cout << paths.front() << '\n';
32+
//
33+
// utility::console::println("running tests...");
34+
// utility::console::println("{}", std::string(32, '-'));
35+
//
36+
// while(!paths.empty()) {
37+
// const filepath current = paths.front();
38+
// paths.pop();
39+
//
40+
// utility::directory::for_all_directory_items(current, [&](const filepath& path) {
41+
// if(utility::fs::is_directory(path)) {
42+
// paths.push(path);
43+
// return;
44+
// }
45+
//
46+
// static const char* result_codes[] = {
47+
// "OK",
48+
// "ERROR",
49+
// };
50+
//
51+
// const auto result = compile_file(path);
52+
//
53+
// if(result.has_error()) {
54+
// utility::console::println(result.get_error_message());
55+
// return;
56+
// }
57+
//
58+
// utility::console::println("{:<30}{}", path.stem().string(), result_codes[result.get_value()]);
59+
// });
60+
// }
61+
//
62+
// utility::fs::remove(ERR_FILE_PATH);
63+
// return 0;
64+
//}
5165

52-
utility::fs::remove(ERR_FILE_PATH);
53-
return 0;
54-
}
66+
i32 main(i32 argc, char* argv[]) {
67+
//
68+
}

0 commit comments

Comments
 (0)