diff --git a/AST.py b/AST.py index 274c3c6..668d3f5 100644 --- a/AST.py +++ b/AST.py @@ -24,6 +24,9 @@ class NodeType(Enum): IdentifierLiteral = "IdentifierLiteral" BooleanLiteral = "BooleanLiteral" + # Helper + FunctionParameter = "FunctionParameter" + class Node: @abstractmethod def type(self) -> NodeType: @@ -52,6 +55,23 @@ class Program(Node): "statements": [{stmt.type().value: stmt.json()} for stmt in self.statements] } +# region Helpers +class FunctionParameter(Expression): + def __init__(self, name: str, value_type: str = None) -> None: + self.name = name + self.value_type = value_type + + def type(self) -> NodeType: + return NodeType.FunctionParameter + + def json(self) -> dict: + return { + "type": self.type().value, + "name": self.name, + "value_type": self.value_type + } +# endregion + # region Literals class IntegerLiteral(Expression): def __init__(self, value: int = None) -> None: @@ -164,7 +184,7 @@ class ReturnStatement(Statement): } class FunctionStatement(Statement): - def __init__(self, parameters: list = [], body: BlockStatement = None, name: IdentifierLiteral = None, return_type: str = None): + def __init__(self, parameters: list[FunctionParameter] = [], body: BlockStatement = None, name: IdentifierLiteral = None, return_type: str = None): self.parameters = parameters self.body = body self.name = name diff --git a/debug/ast.json b/debug/ast.json index 71abf69..2dc73bc 100644 --- a/debug/ast.json +++ b/debug/ast.json @@ -6,18 +6,37 @@ "type": "FunctionStatement", "name": { "type": "IdentifierLiteral", - "value": "test" + "value": "add" }, "return_type": "Int", - "parameters": [], + "parameters": [ + { + "type": "FunctionParameter", + "name": "a", + "value_type": "Int" + }, + { + "type": "FunctionParameter", + "name": "b", + "value_type": "Int" + } + ], "body": { "type": "BlockStatement", "statements": [ { "type": "ReturnStatement", "return_value": { - "type": "IntegerLiteral", - "value": 123 + "type": "InfixExpression", + "left_node": { + "type": "IdentifierLiteral", + "value": "a" + }, + "operator": "+", + "right_node": { + "type": "IdentifierLiteral", + "value": "b" + } } } ] @@ -42,9 +61,18 @@ "type": "CallExpression", "function": { "type": "IdentifierLiteral", - "value": "test" + "value": "add" }, - "arguments": [] + "arguments": [ + { + "type": "IntegerLiteral", + "value": 2 + }, + { + "type": "IntegerLiteral", + "value": 3 + } + ] } } ] diff --git a/debug/ir.ll b/debug/ir.ll index ae0c3d0..cdd6834 100644 --- a/debug/ir.ll +++ b/debug/ir.ll @@ -7,11 +7,8 @@ target datalayout = "" define i32 @"test"() { test_entry: - %".2" = alloca i32 - store i32 3, i32* %".2" - %".4" = load i32, i32* %".2" - %".5" = add i32 %".4", 2 - ret i32 %".5" + %".2" = add i32 77, 33 + ret i32 %".2" } define i32 @"main"() diff --git a/lexer.py b/lexer.py index f7111b7..5fb1d72 100644 --- a/lexer.py +++ b/lexer.py @@ -144,6 +144,8 @@ class Lexer: tok = self.__new_token(TokenType.SEMICOLON, self.current_char) case ":": tok = self.__new_token(TokenType.COLON, self.current_char) + case ",": + tok = self.__new_token(TokenType.COMMA, self.current_char) case None: tok = self.__new_token(TokenType.EOF, "") case _: diff --git a/lexer_token.py b/lexer_token.py index e7693c0..68d1315 100644 --- a/lexer_token.py +++ b/lexer_token.py @@ -40,6 +40,7 @@ class TokenType(Enum): RBRACE = "RBRACE" COLON = "COLON" SEMICOLON = "SEMICOLON" + COMMA = "COMMA" # Keywords RETURN = "RETURN" diff --git a/main.py b/main.py index ad60a43..b287b44 100644 --- a/main.py +++ b/main.py @@ -10,9 +10,9 @@ import llvmlite.binding as llvm from ctypes import CFUNCTYPE, c_int, c_float LEXER_DEBUG: bool = False -PARSER_DEBUG: bool = False -COMPILER_DEBUG: bool = True -RUN_CODE: bool = True +PARSER_DEBUG: bool = True +COMPILER_DEBUG: bool = False +RUN_CODE: bool = False if __name__ == "__main__": diff --git a/plasma_parser.py b/plasma_parser.py index fc9dc4c..1ca19ec 100644 --- a/plasma_parser.py +++ b/plasma_parser.py @@ -7,6 +7,7 @@ from AST import Statement, Expression, Program from AST import ExpressionStatement, AssignmentStatement, FunctionStatement, ReturnStatement, BlockStatement, ReassignStatement, IfStatement from AST import InfixExpression, CallExpression from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral +from AST import FunctionParameter class PrecedenceType(Enum): P_LOWEST = 0 @@ -164,10 +165,9 @@ class Parser: if not self.__expect_peek(TokenType.LPAREN): return None - func_stmt.parameters = [] + func_stmt.parameters = self.__parse_function_parameters() + - if not self.__expect_peek(TokenType.RPAREN): - return None if not self.__expect_peek(TokenType.COLON): return None @@ -217,6 +217,38 @@ class Parser: return stmt + def __parse_function_parameters(self) -> list[FunctionParameter]: + params: list[FunctionParameter] = [] + + if self.__peek_token_is(TokenType.RPAREN): + self.__next_token() + return params + + self.__next_token() + + first_param: FunctionParameter = FunctionParameter(name=self.current_token.literal) + if not self.__expect_peek(TokenType.COLON): + return None + self.__next_token() + first_param.value_type = self.current_token.literal + params.append(first_param) + + while self.__peek_token_is(TokenType.COMMA): + self.__next_token() + self.__next_token() + + param: FunctionParameter = FunctionParameter(name=self.current_token.literal) + if not self.__expect_peek(TokenType.COLON): + return None + self.__next_token() + param.value_type = self.current_token.literal + params.append(param) + + if not self.__expect_peek(TokenType.RPAREN): + return None + + return params + def __parse_return_statement(self) -> ReturnStatement: stmt: ReturnStatement = ReturnStatement() @@ -311,12 +343,31 @@ class Parser: def __parse_call_expression(self, function: Expression) -> CallExpression: expr: CallExpression = CallExpression(function=function) - expr.arguments = [] # TODO - if not self.__expect_peek(TokenType.RPAREN): - return None + expr.arguments = self.__parse_expression_list(TokenType.RPAREN) return expr + def __parse_expression_list(self, end: TokenType) -> list[Expression]: + e_list: list[Expression] = [] + + if self.__peek_token_is(end): + self.__next_token() + return e_list + + self.__next_token() + + e_list.append(self.__parse_expression(PrecedenceType.P_LOWEST)) + + while self.__peek_token_is(TokenType.COMMA): + self.__next_token() + self.__next_token() + + e_list.append(self.__parse_expression(PrecedenceType.P_LOWEST)) + + if not self.__expect_peek(end): + return None + + return e_list # endregion # region Prefix Methods diff --git a/tests/test.pla b/tests/test.pla index ac31582..d20dadc 100644 --- a/tests/test.pla +++ b/tests/test.pla @@ -1,8 +1,7 @@ -test = Func(): Int { - x: Int = 3; - return x + 2; +add = Func(a: Int, b: Int): Int { + return a + b; } main = Func(): Int { - return test(); + return add(2, 3); } \ No newline at end of file