diff --git a/compiler/include/AST/Def.h b/compiler/include/AST/Def.h index 23f9c3f..9fa74d6 100644 --- a/compiler/include/AST/Def.h +++ b/compiler/include/AST/Def.h @@ -11,9 +11,12 @@ #include "Stmt/ExprStmt.h" #include "Stmt/FnDecl.h" +#include "Stmt/TraitDecl.h" +#include "Stmt/TypeDecl.h" #include "Stmt/ValDecl.h" #include "Type/Function.h" +#include "Type/Generic.h" #include "Type/Named.h" #include "Type/Tuple.h" diff --git a/compiler/include/AST/Expr/Call.h b/compiler/include/AST/Expr/Call.h index 1f4a833..2d9cf7e 100644 --- a/compiler/include/AST/Expr/Call.h +++ b/compiler/include/AST/Expr/Call.h @@ -13,6 +13,7 @@ namespace ast ~CallExpr() { + delete callee; for (auto &arg : args) delete arg; } diff --git a/compiler/include/AST/Expr/Closure.h b/compiler/include/AST/Expr/Closure.h new file mode 100644 index 0000000..a8e6732 --- /dev/null +++ b/compiler/include/AST/Expr/Closure.h @@ -0,0 +1,19 @@ +#pragma once + +#include "AST/Base.h" +#include +#include + +namespace ast +{ + class Closure : public Expr + { + public: + Closure(const std::vector &args, const Expr *body) + : args(std::move(args)), body(body) {} + ~Closure() { delete body; } + + const std::vector args; + const Expr *body; + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TraitDecl.h b/compiler/include/AST/Stmt/TraitDecl.h new file mode 100644 index 0000000..2d0f20b --- /dev/null +++ b/compiler/include/AST/Stmt/TraitDecl.h @@ -0,0 +1,25 @@ +#pragma once + +#include "AST/Base.h" +#include +#include + +namespace ast +{ + class FnDecl; + + class TraitDecl : public Stmt + { + public: + TraitDecl(const std::string &name, const std::vector &traits) + : name(name), traits(std::move(traits)) {} + ~TraitDecl() + { + for (auto &trait : traits) + delete trait; + } + + const std::string name; + const std::vector traits; + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Stmt/TypeDecl.h b/compiler/include/AST/Stmt/TypeDecl.h new file mode 100644 index 0000000..1778fce --- /dev/null +++ b/compiler/include/AST/Stmt/TypeDecl.h @@ -0,0 +1,31 @@ +#pragma once + +#include "AST/Base.h" +#include +#include + +namespace ast +{ + class FnDecl; + + typedef std::pair TypeAttr; + + class TypeDecl : public Stmt + { + public: + TypeDecl(const std::string &name, const std::vector &attrs, const std::vector &members) + : name(name), attrs(std::move(attrs)), members(std::move(members)) {} + ~TypeDecl() + { + for (auto &attr : attrs) + delete attr.second; + + for (auto &member : members) + delete member; + } + + const std::string name; + const std::vector attrs; + const std::vector members; + }; +} \ No newline at end of file diff --git a/compiler/include/AST/Type/Generic.h b/compiler/include/AST/Type/Generic.h new file mode 100644 index 0000000..49b11e9 --- /dev/null +++ b/compiler/include/AST/Type/Generic.h @@ -0,0 +1,24 @@ +#pragma once + +#include "AST/Base.h" +#include +#include + +namespace ast +{ + class GenericType : public Type + { + public: + GenericType(const std::string &name, const std::vector &types) + : name(name), types(std::move(types)) {} + + ~GenericType() + { + for (auto &type : types) + delete type; + } + + const std::string name; + const std::vector types; + }; +} diff --git a/compiler/include/Parser.h b/compiler/include/Parser.h new file mode 100644 index 0000000..1a289a1 --- /dev/null +++ b/compiler/include/Parser.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "AST/Def.h" +#include "parser.gen.h" + +class Parser +{ +public: + Parser() {} + + ast::Module *parse(const std::string &file, const std::stringstream &input); + + std::string file; + yy::location location; + ast::Module *module; +}; diff --git a/compiler/include/ParserDriver.h b/compiler/include/ParserDriver.h deleted file mode 100644 index 4ee54f8..0000000 --- a/compiler/include/ParserDriver.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -#include "AST/Def.h" -#include "parser.gen.h" - -class ParserDriver -{ -public: - ParserDriver() {} - ~ParserDriver() { delete module; } - - int parse(const std::string &input); - - void startLexer(); - void stopLexer(); - - std::string file; - yy::location location; - ast::Module *module; -}; - -#define YY_DECL yy::parser::symbol_type yylex(ParserDriver &driver) -YY_DECL; diff --git a/compiler/lexer.ll b/compiler/lexer.ll index 16633e9..1afe54b 100644 --- a/compiler/lexer.ll +++ b/compiler/lexer.ll @@ -1,6 +1,9 @@ %{ #include "parser.gen.h" -#include "ParserDriver.h" +#include "Parser.h" + +#undef YY_DECL +#define YY_DECL yy::parser::symbol_type yylex(Parser &driver) #define yyterminate() yy::parser::make_END(yy::location()) @@ -16,7 +19,7 @@ hexdigit [0-9a-fA-F] letter [a-zA-Z] -opchar ("+"|"-"|"*"|"/"|"%"|"!"|"&"|"$"|"§"|"|"|"="|"<"|">"|"?"|"~"|"#"|":"|"^"|"\\") +opchar ("+"|"-"|"*"|"/"|"%"|"!"|"&"|"$"|"§"|"|"|"="|"<"|">"|"?"|"~"|"#"|":"|"^"|"\\"|".") whitespace [ \n\t\r\v]+ @@ -33,9 +36,9 @@ whitespace [ \n\t\r\v]+ {opchar}+ { std::string text = yytext; if (text == "=") return _token(EQUALS); if (text == "->") return _token(RARR); + if (text == ".") return _token(DOT); return _token(OPERATOR); } -"." { return _token(DOT); } "," { return _token(COMMA); } ";" { return _token(SEMI); } "(" { return _token(LPAREN); } @@ -62,9 +65,3 @@ whitespace [ \n\t\r\v]+ {whitespace} { ; } %% - -void ParserDriver::startLexer() { - yy_scan_string(this->file.data()); -} - -void ParserDriver::stopLexer() {} diff --git a/compiler/parser.yy b/compiler/parser.yy index f868a9c..3a9120f 100644 --- a/compiler/parser.yy +++ b/compiler/parser.yy @@ -19,14 +19,15 @@ %code requires { #include "AST/Def.h" -class ParserDriver; +class Parser; } -%lex-param { ParserDriver &driver } -%parse-param { ParserDriver &driver } +%lex-param { Parser &driver } +%parse-param { Parser &driver } %code { -#include "ParserDriver.h" +#include "Parser.h" +yy::parser::symbol_type yylex(Parser &driver); } %token INT "integer literal" @@ -70,7 +71,8 @@ class ParserDriver; blockStmt ; -%type extFnDecl fnDecl; +%type > fnDecls fnDecls0; +%type fnDecl fnDef; %type valDecl; %type > @@ -79,14 +81,9 @@ class ParserDriver; fnTypeArgs ; -%type - type -; +%type type type1; -%type > - exprs - args -; +%type > exprs args; %type expr @@ -98,10 +95,7 @@ class ParserDriver; ; %type fnArg; -%type > - fnArgs - fnArgs0 -; +%type > fnArgs fnArgs0; %type > lambdaArgs @@ -110,6 +104,7 @@ class ParserDriver; %type moduleName + type0 operator identifier keyword @@ -121,11 +116,14 @@ class ParserDriver; imports ; +%type traitDecl; +%type typeDecl; + %start module %% -module: imports topLevelStmts { driver.module = new ast::Module($2); } +module: imports topLevelStmts { driver.module = new ast::Module($1, $2); } ; @@ -144,14 +142,15 @@ moduleName: identifier { $$ = $1; } | moduleName "." identifier { $$ = $1 + $2 + $3; } ; - topLevelStmts: topLevelStmt { $$.push_back($1); } | topLevelStmts topLevelStmt { $1.push_back($2); $$ = std::move($1); } ; -topLevelStmt: fnDecl { $$ = $1; } - | extFnDecl { $$ = $1; } +topLevelStmt: fnDef { $$ = $1; } + | fnDecl { $$ = $1; } | valDecl { $$ = $1; } + | typeDecl { $$ = $1; } + | traitDecl { $$ = $1; } ; blockStmts: blockStmt { $$.push_back($1); } @@ -159,19 +158,33 @@ blockStmts: blockStmt { $$.push_back($1); } ; blockStmt: valDecl { $$ = $1; } - | fnDecl { $$ = $1; } + | fnDef { $$ = $1; } | expr ";" { $$ = new ast::ExprStmt($1); } ; +traitDecl: TRAIT identifier "=" "{" fnDecls "}" { $$ = new ast::TraitDecl($2, $5); } + ; + +typeDecl: TYPE identifier "=" "(" fnArgs ")" "{" fnDecls "}" { $$ = new ast::TypeDecl($2, $5, $8); } + ; + +fnDecls: %empty { ; } + | fnDecls0 { $$ = std::move($1); } + ; + +fnDecls0: fnDecl { $$.push_back($1); } + | fnDecls0 fnDecl { $1.push_back($2); $$ = std::move($1); } + ; + valDecl: VAL identifier "=" expr ";" { $$ = new ast::ValDecl($2, nullptr, $4); } | VAL identifier type "=" expr ";" { $$ = new ast::ValDecl($2, $3, $5); } ; -fnDecl: FN identifier "[" fnArgs "]" type "=" expr ";" { $$ = new ast::FnDecl($2, $4, $6, $8); } +fnDef : FN identifier "[" fnArgs "]" type "=" expr ";" { $$ = new ast::FnDecl($2, $4, $6, $8); } ; -extFnDecl: DECLARE FN identifier "[" fnArgs "]" type ";" { $$ = new ast::FnDecl($3, $5, $7, nullptr); } - ; +fnDecl: FN identifier "[" fnArgs "]" type ";" { $$ = new ast::FnDecl($2, $4, $6, nullptr); } + ; fnArgs: %empty { ; } | fnArgs0 { $$ = std::move($1); } @@ -188,12 +201,18 @@ types: type { $$.push_back($1); } | types "," type { $1.push_back($3); $$ = std::move($1); } ; -type: identifier { $$ = new ast::NamedType($1); } +type: type1 | "(" type ")" { $$ = $2; } | "(" tupleTypes ")" { $$ = new ast::TupleType($2); } | "[" fnTypeArgs "]" "->" type { $$ = new ast::FunctionType($2, $5); } ; +type1: type0 { $$ = new ast::NamedType($1); } + | type0 "{" types "}" { $$ = new ast::GenericType($1, $3); } + ; + +type0: identifier; + tupleTypes: type "," type { $$.push_back($1); $$.push_back($3); } | tupleTypes "," type { $1.push_back($3); $$ = std::move($1); } ; @@ -210,8 +229,8 @@ expr: expr3 { $$ = $1; } ; expr3: expr2 { $$ = $1; } - | "[" lambdaArgs "]" "->" expr { $$ = NULL; } - | "{" blockStmts "}" { $$ = new ast::BlockExpr($2); } + | "[" lambdaArgs "]" "->" expr { $$ = nullptr; } + | "{" blockStmts "}" { $$ = new ast::BlockExpr($2); } ; expr2: expr1 { $$ = $1; } @@ -226,6 +245,7 @@ expr0: literal { $$ = $1; } | identifier { $$ = new ast::Identifier($1); } | expr0 "[" args "]" { $$ = new ast::CallExpr($1, $3); } | "(" expr ")" { $$ = new ast::PrefExpr($2); } + | expr0 "." identifier { $$ = $1; } ; lambdaArgs: %empty { ; } diff --git a/compiler/src/Parser.cpp b/compiler/src/Parser.cpp new file mode 100644 index 0000000..b42ce60 --- /dev/null +++ b/compiler/src/Parser.cpp @@ -0,0 +1,20 @@ +#include "Parser.h" + +#include +#include + +void yy_scan_string(const char *); + +ast::Module *Parser::parse(const std::string &file, const std::stringstream &input) +{ + module = nullptr; + + this->file = file; + location.initialize(&file); + + yy_scan_string(input.str().data()); + + int res = yy::parser(*this)(); + + return module; +} diff --git a/compiler/src/ParserDriver.cpp b/compiler/src/ParserDriver.cpp deleted file mode 100644 index ecefb55..0000000 --- a/compiler/src/ParserDriver.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "ParserDriver.h" - -int ParserDriver::parse(const std::string &input) -{ - file = input; - location.initialize(&file); - - startLexer(); - yy::parser parse(*this); - int res = parse(); - stopLexer(); - - return res; -} diff --git a/compiler/src/main.cpp b/compiler/src/main.cpp index e2ede87..0b8326e 100644 --- a/compiler/src/main.cpp +++ b/compiler/src/main.cpp @@ -1,10 +1,10 @@ -#include "ParserDriver.h" +#include "Parser.h" #include #include #include -std::stringstream readFile(const std::string &path) +static std::stringstream readFile(const std::string &path) { std::ifstream t(path); std::stringstream buffer; @@ -21,10 +21,10 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - auto buf = readFile(argv[1]); - auto parser = ParserDriver(); - parser.parse(buf.str()); + auto module = Parser().parse(argv[1], readFile(argv[1])); - auto fn = (ast::FnDecl *)parser.module->stmts.at(0); + auto fn = (ast::FnDecl *)module->stmts.at(0); std::cout << fn->name << std::endl; + + delete module; } diff --git a/examples/42.plsm b/examples/42.plsm index 1c55ef4..0df96c2 100644 --- a/examples/42.plsm +++ b/examples/42.plsm @@ -3,7 +3,9 @@ import test.test; fn main[] Int = 42; fn test[b Int] Int = { - fn helper[] Int = 10; - 20 * b; + fn helper[] Int = b; + 20 * helper[]; }; +fn size[vals List{Int}] Int = vals.size[]; + diff --git a/lib/include/types/types.h b/lib/include/types/types.h index 199b1a4..6c5abd6 100644 --- a/lib/include/types/types.h +++ b/lib/include/types/types.h @@ -1,4 +1,4 @@ #pragma once #include "int.h" -#include "bool.h" \ No newline at end of file +#include "bool.h"