Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ jobs:
- name: Build docker image
run: docker build -t tlang-dev .
- name: Run tests inside container
run: docker run -v $(pwd):/tlang -w /tlang --entrypoint /bin/sh tlang-dev -c ./testing.sh
# tests must not run as root, look at tests/unit/sources/SourceManagerTests.cpp to learn more
run: docker run --user $(id -u):$(id -g) -e HOME=/tmp -v $(pwd):/tlang -w /tlang --entrypoint /bin/sh tlang-dev -c ./testing.sh
- name: Unit Test Report
uses: dorny/test-reporter@v3
if: always()
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ bin
files/grammar/grammar.lr
files/lexis/lexis.lx
src/syntax/BuildersRegistry.h
files/std/lib
files/std/include

examples/build
examples/exe
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_subdirectory(src/lexis)
add_subdirectory(src/syntax)

add_subdirectory(src)
add_subdirectory(std)

# add executables from cli directory
file(GLOB_RECURSE CLI_SOURCES
Expand Down
2 changes: 2 additions & 0 deletions cmake/load_libraries.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ llvm_map_components_to_libnames(llvm_libs support core irreader linker

# -- fmt --
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
set(FMT_INSTALL OFF)
add_subdirectory(lib/fmt EXCLUDE_FROM_ALL)
# -- fmt end --

Expand All @@ -30,5 +31,6 @@ add_subdirectory(lib/argparse EXCLUDE_FROM_ALL)
# -- argparse end --

# -- google test --
set(INSTALL_GTEST OFF)
add_subdirectory(lib/googletest EXCLUDE_FROM_ALL)
# -- google test end --
18 changes: 4 additions & 14 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
build/print.s : sources/print.cpp
build/main : sources/main.tea sources/rectangle.team sources/math.team
mkdir -p build
clang++ sources/print.cpp -S -o build/print.s
tlang main:sources/main.tea rectangle:sources/rectangle.team math:sources/math.team -o build/main

build/main.s : sources/main.tea sources/io.team sources/rectangle.team sources/math.team
mkdir -p build
tlang main:sources/main.tea io:sources/io.team rectangle:sources/rectangle.team math:sources/math.team -o build/main.ll
/opt/homebrew/Cellar/llvm/22.1.7_1/bin/llc build/main.ll -o build/main.s

exe/main: build/main.s build/print.s
mkdir -p exe
clang++ build/main.s build/print.s -o exe/main

run_code: exe/main
./exe/main
run_code: build/main
./build/main

clean:
rm -rf exe
rm -rf build
1 change: 0 additions & 1 deletion examples/sources/io.team

This file was deleted.

9 changes: 7 additions & 2 deletions examples/sources/main.tea
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import "rectangle"
import "io"

import "math"
import "rectangle"

main: () -> i64 = {
print(math::factorial(6));
println(math::factorial(6));

rect: geometry::Rectangle = geometry::make_rectangle(1 as! u64, 2 as! u64, 3, 4);

rect
.geometry::move(1, 2)
.geometry::print_rect();

println(1);
println(2);
println(3);

return 0;
}
23 changes: 0 additions & 23 deletions examples/sources/print.cpp

This file was deleted.

19 changes: 0 additions & 19 deletions files/std/reclib.asm

This file was deleted.

3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ target_include_directories(TeaLang PUBLIC ${LLVM_INCLUDE_DIRS})

# TeaLang requires grammar and lexis tables to work
add_dependencies(TeaLang run_grammar_tablegen run_lexis_tablegen)

# TeaLang comes with a standard library
add_dependencies(TeaLang std std_headers)
2 changes: 2 additions & 0 deletions src/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ extern const bool is_installed_build;

constexpr inline auto lexis_relative_filepath = "lexis/lexis.lx";
constexpr inline auto grammar_relative_filepath = "grammar/grammar.lr";
constexpr inline auto std_library_relative_filepath = "std/lib/libstd.a";
constexpr inline auto std_include_relative_path = "std/include";

inline std::filesystem::path GetRuntimeFilePath(
std::filesystem::path relative_path) {
Expand Down
78 changes: 49 additions & 29 deletions src/cli/ArgumentsReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@ namespace fs = std::filesystem;

namespace Cli {

SourcesList ArgumentsReader::parse_source_paths(
std::vector<std::string> sources) {
SourcesList result;
auto add_source = [&result](const std::string& name, const fs::path& path) {
auto [_, was_emplaced] = result.emplace(name, path);
if (!was_emplaced) {
throw std::runtime_error(fmt::format(
"File {} was already included with different name.", path.c_str()));
}
};
std::string ArgumentsReader::get_default_output_name(Front::EmitType type) {
switch (type) {
case Front::EmitType::AST:
case Front::EmitType::IR:
return "out.txt";
case Front::EmitType::OBJECT:
return "out.o";
case Front::EmitType::EXECUTABLE:
return "out";
}

unreachable("All output types should be enumerated above.");
}

void ArgumentsReader::parse_source_paths(
const std::vector<std::string>& sources,
Front::TeaFrontendConfiguration& config) {
std::string separator{fs::path::preferred_separator};

for (auto& include : sources) {
Expand All @@ -42,7 +48,7 @@ SourcesList ArgumentsReader::parse_source_paths(
"Named include \"{}\" must refer to regular file.", name));
}

add_source(name, path);
config.add_source(name, path);
} else {
// unnamed include
// for this type of include name is a stem part of path
Expand All @@ -60,7 +66,7 @@ SourcesList ArgumentsReader::parse_source_paths(
auto include_name = std::regex_replace(std::string{path_copy},
std::regex(separator), ".");

add_source(include_name, path);
config.add_source(include_name, path);

continue;
}
Expand All @@ -85,23 +91,36 @@ SourcesList ArgumentsReader::parse_source_paths(
auto include_name =
std::regex_replace(relative_path, std::regex(separator), ".");

add_source(include_name, subfile.path());
config.add_source(include_name, subfile.path());
}
}
}

return result;
}

std::filesystem::path ArgumentsReader::parse_output(const std::string& output) {
std::filesystem::path ArgumentsReader::parse_output(std::string output,
Front::EmitType emit_type) {
// empty output means that default value is used
if (output.empty()) {
switch (emit_type) {
case Front::EmitType::AST:
case Front::EmitType::IR:
// write to stdout
return {};
case Front::EmitType::OBJECT:
case Front::EmitType::EXECUTABLE:
output = get_default_output_name(emit_type);
break;
}
}

fs::path output_path = output;

// output must be directory or path
if (fs::is_directory(output)) {
output_path /= kDefaultOutputName;
output_path /= get_default_output_name(emit_type);
}

return output_path;
return fs::absolute(output_path).lexically_normal();
}

Front::EmitType ArgumentsReader::get_emit_type(std::string_view name) {
Expand All @@ -111,8 +130,11 @@ Front::EmitType ArgumentsReader::get_emit_type(std::string_view name) {
if (name == "ast") {
return Front::EmitType::AST;
}
if (name == "binary") {
return Front::EmitType::BINARY;
if (name == "obj") {
return Front::EmitType::OBJECT;
}
if (name == "exe") {
return Front::EmitType::EXECUTABLE;
}
throw std::runtime_error("unknown compiler emit type.");
}
Expand All @@ -129,14 +151,12 @@ Front::TeaFrontendConfiguration ArgumentsReader::read(int argc, char* argv[]) {
"automatically or <directory path> to include all files in "
"directory recursively.");

parser.add_argument("-o", "--output")
.default_value("")
.help("output file (stdout by default)");
parser.add_argument("-o", "--output").default_value("").help("output file");

parser.add_argument("--emit")
.choices("ir", "ast", "binary")
.default_value("ir")
.help("compiler output type: `ir` or `ast`");
.choices("ir", "ast", "obj", "exe")
.default_value("exe")
.help("compiler output type: ir, ast, obj, exe");

try {
parser.parse_args(argc, argv);
Expand All @@ -145,10 +165,10 @@ Front::TeaFrontendConfiguration ArgumentsReader::read(int argc, char* argv[]) {
}

Front::TeaFrontendConfiguration result;
result.sources =
parse_source_paths(parser.get<std::vector<std::string>>("sources"));

parse_source_paths(parser.get<std::vector<std::string>>("sources"), result);
result.emit_type = get_emit_type(parser.get<std::string>("emit"));
result.output_file = parse_output(parser.get("output"));
result.output_file = parse_output(parser.get("output"), result.emit_type);

return result;
}
Expand Down
12 changes: 7 additions & 5 deletions src/cli/ArgumentsReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@
#include "compilation/FrontendConfiguration.h"

namespace Cli {
// import name / filepath
using SourcesList = std::unordered_map<std::string, std::filesystem::path>;

class ArgumentsReader {
constexpr static auto kDefaultOutputName = "out";
constexpr static auto kSourceNamePathDelimiter = ":";

static SourcesList parse_source_paths(std::vector<std::string> sources);
static std::string get_default_output_name(Front::EmitType type);

static std::filesystem::path parse_output(const std::string& output);
static void parse_source_paths(const std::vector<std::string>& sources,
Front::TeaFrontendConfiguration& config);

static std::filesystem::path parse_output(std::string output,
Front::EmitType emit_type);

static Front::EmitType get_emit_type(std::string_view name);

public:
static Front::TeaFrontendConfiguration read(int argc, char* argv[]);
};

} // namespace Cli
Loading