diff --git a/README.md b/README.md index 8b336ad..da728bb 100644 --- a/README.md +++ b/README.md @@ -75,19 +75,19 @@ let @main in { ## Examples that actually work right now Exit with exit code 0 (success): ``` -let @main in { +let @main : i32 in { 0 } ``` Exit with non-zero exit code (failure): ``` -let @main in { +let @main : i32 in { 1 // or any other number } ``` Exit with calculated exit code (yes, this language is a glorified calculator right now): ``` -let @main in { +let @main : i32 in { 3 + 5 * 6 // It doesn't even support parentheses, what a failure } // the exit code is actually computed at compile time by LLVM (optimizations!!) ``` diff --git a/src/Parser.cpp b/src/Parser.cpp index 9e2ca94..ed3fcdc 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -8,6 +8,9 @@ Parser::Parser(const TokenStream& tokens) : tokens(tokens) { + m_type_map = {{"void", llvm::Type::getVoidTy(*globalContext)}, {"bool", llvm::Type::getInt1Ty(*globalContext)}, + {"i8", llvm::Type::getInt8Ty(*globalContext)}, {"i16", llvm::Type::getInt16Ty(*globalContext)}, + {"i32", llvm::Type::getInt32Ty(*globalContext)}, {"i64", llvm::Type::getInt64Ty(*globalContext)}}; } std::shared_ptr Parser::new_parser(const TokenStream& tokens) @@ -101,8 +104,8 @@ Result Parser::function() { FunctionPrototype proto; Token* start_token = current_token; - proto.returnType = llvm::IntegerType::getInt32Ty(*globalContext); // FIXME: allow specifying return type - proto.arguments = {}; // FIXME: allow specifying arguments + proto.returnType = m_type_map["void"]; // FIXME: allow specifying return type + proto.arguments = {}; // FIXME: allow specifying arguments if (current_token->type != TT_Let) return Err("Expected let", current_token); advance(); if (current_token->type != TT_At) return Err("Expected @", current_token); @@ -114,13 +117,37 @@ Result Parser::function() proto.name = current_token->string_value.value(); } advance(); - if (current_token->type != TT_In && current_token->type != TT_Semicolon) - return Err("Expected 'in' or semicolon", current_token); + if (current_token->type != TT_In && current_token->type != TT_Semicolon && current_token->type != TT_Colon) + return Err("Expected 'in', colon or semicolon", current_token); if (current_token->type == TT_Semicolon) { advance(); return Ok(new EmptyFunctionNode(proto), start_token); } + if (current_token->type == TT_Colon) + { + advance(); + if (current_token->type != TT_Identifier) + { + return Err("Expected type name", current_token); + } + try + { + proto.returnType = m_type_map.at(current_token->string_value.value()); + } + catch (std::out_of_range) + { + return Err("Expected type name", current_token); + } + advance(); + if (current_token->type != TT_In && current_token->type != TT_Semicolon) + return Err("Expected 'in' or semicolon", current_token); + if (current_token->type == TT_Semicolon) + { + advance(); + return Ok(new EmptyFunctionNode(proto), start_token); + } + } advance(); if (current_token->type != TT_LBracket) return Err("Invalid syntax", diff --git a/src/Parser.h b/src/Parser.h index 12ca99b..5b8acd2 100644 --- a/src/Parser.h +++ b/src/Parser.h @@ -6,6 +6,7 @@ #include "Lexer.h" #include "Result.h" #include "sapphirepch.h" +#include "llvm/IR/Type.h" /* Parser class for the Sapphire compiler. */ class Parser @@ -17,6 +18,8 @@ class Parser int advance(); Token* current_token; + std::unordered_map m_type_map; + Result factor(); Result expr(); Result term(); diff --git a/tests/calc.sp b/tests/calc.sp index 5656a54..5980bbd 100644 --- a/tests/calc.sp +++ b/tests/calc.sp @@ -1,3 +1,3 @@ -let @main in { +let @main : i32 in { 1 + 3 * 5 } \ No newline at end of file diff --git a/tests/wimport.json b/tests/wimport.json index e038d90..dfb4e6e 100644 --- a/tests/wimport.json +++ b/tests/wimport.json @@ -1,9 +1,7 @@ { "file": "wimport.sp", "compile": { - "flags": [ - "--wimport" - ], + "flags": [], "exit-code": 1, "stdout": "", "stderr": "\u001b[1;1mtests/wimport.sp:1:1: \u001b[31;49merror: \u001b[0;0mExpected let\n1 \n \u001b[31;49m^\u001b[0;0m\n"