diff --git a/furc/include/furc/ast/declaration.hpp b/furc/include/furc/ast/declaration.hpp index 7dd18d4..e018d2f 100644 --- a/furc/include/furc/ast/declaration.hpp +++ b/furc/include/furc/ast/declaration.hpp @@ -79,6 +79,12 @@ struct function_declaration_param { type type; }; +enum class function_declaration_node_t { + Normal = 0, + Import, + Native, +}; + /** * @brief Function declaration AST node. */ @@ -92,11 +98,16 @@ public: * @param type Return type of the function. */ template - function_declaration_node(struct location location, T&& name, std::optional&& returnType, ParamsFwd&& params) + function_declaration_node(struct location location, + T&& name, + std::optional&& returnType, + ParamsFwd&& params, + function_declaration_node_t type = function_declaration_node_t::Normal) : declaration_node(location), p_name(std::forward(name)), p_returnType(std::move(returnType)), - p_params(std::forward(params)) {} + p_params(std::forward(params)), + p_type(type) {} public: /** * @brief Returns this node's declaration type. @@ -125,6 +136,13 @@ public: * @return Function's parameters. */ const std::vector& params() const { return p_params; } + + /** + * @brief Returns function's type. + * + * @return Function's type. + */ + function_declaration_node_t type() const { return p_type; } public: void accept(visitor& visitor) const override; @@ -140,12 +158,17 @@ protected: /** * @brief Return type of the function. */ - std::optional p_returnType; + std::optional p_returnType; /** * @brief Parameters of the function. */ std::vector p_params; + + /** + * @brief Type of the function declaration. + */ + function_declaration_node_t p_type; }; /** @@ -164,7 +187,7 @@ public: template function_definition_node(struct location location, T&& name, - std::optional&& type, + std::optional&& type, ParamsFwd&& params, body&& body) : function_declaration_node(location, std::forward(name), std::move(type), std::forward(params)), diff --git a/furc/include/furc/front/token.hpp b/furc/include/furc/front/token.hpp index ff05de4..35bbc82 100644 --- a/furc/include/furc/front/token.hpp +++ b/furc/include/furc/front/token.hpp @@ -153,6 +153,8 @@ enum class keyword_token { If, /**< `if` */ Else, /**< `else` */ While, /**< `while` */ + Import, /**< `import` */ + Native, /**< `native` */ Int32, /**< `int32` */ }; @@ -165,6 +167,8 @@ static inline std::ostream& operator<<(std::ostream& os, keyword_token keyword) case keyword_token::If: return os << "if"; case keyword_token::Else: return os << "else"; case keyword_token::While: return os << "while"; + case keyword_token::Import: return os << "import"; + case keyword_token::Native: return os << "native"; case keyword_token::Int32: return os << "int32"; } return os; @@ -178,6 +182,8 @@ static inline std::string operator+(const std::string& str, keyword_token keywor case keyword_token::If: return str + "if"; case keyword_token::Else: return str + "else"; case keyword_token::While: return str + "while"; + case keyword_token::Import: return str + "import"; + case keyword_token::Native: return str + "native"; case keyword_token::Int32: return str + "int32"; } return str; diff --git a/furc/src/front/lexer.cpp b/furc/src/front/lexer.cpp index b7adee0..420fcc7 100644 --- a/furc/src/front/lexer.cpp +++ b/furc/src/front/lexer.cpp @@ -100,6 +100,8 @@ token_r lexer::next_token() { { "if", keyword_token::If }, { "else", keyword_token::Else }, { "while", keyword_token::While }, + { "import", keyword_token::Import }, + { "native", keyword_token::Native }, { "int32", keyword_token::Int32 }, }; diff --git a/furc/src/front/parser.cpp b/furc/src/front/parser.cpp index 4967df5..c53379e 100644 --- a/furc/src/front/parser.cpp +++ b/furc/src/front/parser.cpp @@ -38,14 +38,11 @@ ast::program_node_r parser::parse() & { while (peek_token().has_value()) { auto decl = parse_declaration(); - if (decl.has_error()) { - program = nullptr; - } else if (program != nullptr) { - program->push(std::move(decl.value())); - } + if (decl.has_error()) return ast::program_node_r(ast::error{ decl.error().location }); + program->push(std::move(decl.value())); } - return program != nullptr ? std::move(program) : ast::program_node_r(ast::error{ location{ m_filename } }); + return program; } ast::type_r parser::parse_type() { @@ -59,8 +56,20 @@ ast::declaration_node_r parser::parse_declaration() { const auto& first = peek_token(); switch (first->type) { case token_t::Keyword: { + ast::function_declaration_node_t funcDeclType{}; + auto first = next_token(); switch ((*first)->keyword) { + case keyword_token::Import: + case keyword_token::Native: { + funcDeclType = ((*first)->keyword == keyword_token::Import) ? ast::function_declaration_node_t::Import + : ast::function_declaration_node_t::Native; + + first = eat_token(token_t::Keyword); + if (first.has_error()) return ast::declaration_node_r(ast::error{ first.error().location }); + if (first->value.keyword != keyword_token::Func) + return ast::declaration_node_r(ast::error{ first->location }); + } case keyword_token::Func: { auto name = eat_token(token_t::Identifier); if (name.has_error()) return ast::declaration_node_r(ast::error{ name.error().location }); @@ -103,6 +112,8 @@ ast::declaration_node_r parser::parse_declaration() { case token_t::LBrace: { ast::body_r body = parse_body(); if (body.has_error()) return ast::declaration_node_r(ast::error{ body.error().location }); + if (funcDeclType != ast::function_declaration_node_t::Normal) + return ast::declaration_node_r(ast::error{ body->begin }); return m_arena->allocate_shared(first->location, name->value.string, std::move(returnType), @@ -114,7 +125,8 @@ ast::declaration_node_r parser::parse_declaration() { return m_arena->allocate_shared(first->location, name->value.string, std::move(returnType), - std::move(params)); + std::move(params), + funcDeclType); } default: return ast::declaration_node_r(ast::error{ tok->location }); } diff --git a/furc/src/main.cpp b/furc/src/main.cpp index 42c678d..abaac39 100644 --- a/furc/src/main.cpp +++ b/furc/src/main.cpp @@ -13,6 +13,8 @@ int main(void) { try { std::string programStr = R"( + native func print(value: int32); + func main() -> int32 { x = 0; y = 10;