From 26e1f3a1739755f814522bfaa7a5ab5459d03ea2 Mon Sep 17 00:00:00 2001 From: John Stefanelli Date: Fri, 30 May 2025 10:54:35 +0200 Subject: [PATCH] [libjlx] Parse function calls [libjlx] Add basic stdlib functions to type_checker --- jlx/src/main.cpp | 1 + libjlx/modules/ast.cppm | 53 ++++++++++++++++++++++++-------- libjlx/modules/type_checker.cppm | 46 +++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 13 deletions(-) diff --git a/jlx/src/main.cpp b/jlx/src/main.cpp index 66a5812..e68997f 100644 --- a/jlx/src/main.cpp +++ b/jlx/src/main.cpp @@ -64,6 +64,7 @@ int main(int argc, char** argv) { std::cout << "Parsed " << rt->statements.size() << " statements" << std::endl; auto type_checker = jlx::type_checker(rt->statements.begin(), rt->statements.end()); + type_checker.include_stdlib(); try { type_checker.check(); } catch (jlx::type_error& err) { diff --git a/libjlx/modules/ast.cppm b/libjlx/modules/ast.cppm index 0d698f0..1abcf4c 100644 --- a/libjlx/modules/ast.cppm +++ b/libjlx/modules/ast.cppm @@ -399,8 +399,6 @@ namespace jlx { } std::unique_ptr parse_expression(std::unique_ptr previous = nullptr) { - auto start = *current; - if (current == last) { if (previous != nullptr) { return previous; @@ -409,6 +407,9 @@ namespace jlx { fail_invalid_eof(); } + auto start = *current; + + switch(current->type) { case Identifier: if (previous != nullptr) { @@ -445,19 +446,47 @@ namespace jlx { case Punctuation: { if (current->content == "(") { + identifier_expression* identifier = nullptr; if (previous != nullptr) { - return previous; + auto* id = dynamic_cast(previous.get()); + + if (id == nullptr) { + return previous; + } + + identifier = id; } - auto ex = parse_expression(); + next(); - if (current->type != Punctuation || current->content != ")") { - fail_invalid_token(*current); + if (identifier != nullptr) { + std::vector> args; + bool first = true; + while (current->type != Punctuation || current->content != ")") { + if (!first) { + if (current->type != Punctuation || current->content != ",") { + fail_invalid_token(*current); + } + next(); + } + first = false; + + args.emplace_back(parse_expression()); + } + next(false); + + return std::make_unique(identifier->t, identifier->name, std::move(args)); + } else { + auto ex = parse_expression(); + + if (current->type != Punctuation || current->content != ")") { + fail_invalid_token(*current); + } + + next(false); + + return parse_expression(std::move(ex)); } - - next(false); - - return ex; } else if (current->content == ";") { if (previous == nullptr) { fail_invalid_token(*current); @@ -476,14 +505,12 @@ namespace jlx { } fail_invalid_token(*current); break; - case Keyword: + default: if (previous != nullptr) { return previous; } fail_invalid_token(*current); break; - default: - fail_invalid_token(*current); } } diff --git a/libjlx/modules/type_checker.cppm b/libjlx/modules/type_checker.cppm index 18d2303..14f5771 100644 --- a/libjlx/modules/type_checker.cppm +++ b/libjlx/modules/type_checker.cppm @@ -440,6 +440,7 @@ namespace jlx { init_type = decl->initial_expression->evaluated_type; } + auto type = decl->type; if (init_type.has_value()) { @@ -450,6 +451,13 @@ namespace jlx { } } + + if (type == "comptime_int") { + type = "i64"; + } else if (type == "comptime_float") { + type = "f64"; + } + if (!type.has_value()) { throw std::runtime_error("Cannot infer variable declaration type"); } @@ -567,5 +575,43 @@ namespace jlx { throw std::runtime_error("Missing function"); } + + type_checker_scope& get_global_scope() { + return scopes.front(); + } + + void include_stdlib() { + auto& glob = get_global_scope(); + + constexpr std::array stringable_types = { + "i8", + "i16", + "i32", + "i64", + "u8", + "u16", + "u32", + "u64", + "f32", + "f64", + "boolean" + }; + + for (const auto& type : stringable_types) { + glob.functions.insert_or_assign(std::format("{}_to_string", type), runtime_function{ + "string", + { + type + } + }); + } + + glob.functions.insert_or_assign("print", runtime_function{ + "void", + { + "string" + } + }); + } }; } \ No newline at end of file