diff --git a/AST.py b/AST.py index 3b81ae2..274c3c6 100644 --- a/AST.py +++ b/AST.py @@ -16,6 +16,7 @@ class NodeType(Enum): # Expressions InfixExpression = "InfixExpression" + CallExpression = "CallExpression" # Literals IntegerLiteral = "IntegerLiteral" @@ -231,4 +232,19 @@ class InfixExpression(Expression): "operator": self.operator, "right_node": self.right_node.json() } + +class CallExpression(Expression): + def __init__(self, function: Expression = None, arguments: list[Expression] = None) -> None: + self.function = function + self.arguments = arguments + + def type(self) -> NodeType: + return NodeType.CallExpression + + def json(self) -> dict: + return { + "type": self.type().value, + "function": self.function.json(), + "arguments": [arg.json() for arg in self.arguments] + } # endregion \ No newline at end of file diff --git a/compiler.py b/compiler.py index 38ec926..3b98da0 100644 --- a/compiler.py +++ b/compiler.py @@ -2,7 +2,7 @@ from llvmlite import ir from AST import Node, NodeType, Program, Expression from AST import ExpressionStatement, AssignmentStatement, BlockStatement, ReturnStatement, FunctionStatement, ReassignStatement, IfStatement -from AST import InfixExpression +from AST import InfixExpression, CallExpression from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral from environment import Environment @@ -69,6 +69,8 @@ class Compiler: # Expressions case NodeType.InfixExpression: self.__visit_infix_expression(node) + case NodeType.CallExpression: + self.__visit_call_expression(node) # region Visit Methods def __visit_program(self, node: Program) -> None: @@ -257,6 +259,21 @@ class Compiler: Type = ir.IntType(1) return value, Type + + def __visit_call_expression(self, node: CallExpression) -> None: + name: str = node.function.value + params: list[Expression] = node.arguments + + args = [] + types = [] + # TODO + + match name: + case _: + func, ret_type = self.environment.lookup(name) + ret = self.builder.call(func, args) + + return ret, ret_type # endregion # endregion @@ -283,4 +300,6 @@ class Compiler: # expression value case NodeType.InfixExpression: return self.__visit_infix_expression(node) + case NodeType.CallExpression: + return self.__visit_call_expression(node) # endregion \ No newline at end of file diff --git a/debug/ast.json b/debug/ast.json new file mode 100644 index 0000000..71abf69 --- /dev/null +++ b/debug/ast.json @@ -0,0 +1,55 @@ +{ + "type": "Program", + "statements": [ + { + "FunctionStatement": { + "type": "FunctionStatement", + "name": { + "type": "IdentifierLiteral", + "value": "test" + }, + "return_type": "Int", + "parameters": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "return_value": { + "type": "IntegerLiteral", + "value": 123 + } + } + ] + } + } + }, + { + "FunctionStatement": { + "type": "FunctionStatement", + "name": { + "type": "IdentifierLiteral", + "value": "main" + }, + "return_type": "Int", + "parameters": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "ReturnStatement", + "return_value": { + "type": "CallExpression", + "function": { + "type": "IdentifierLiteral", + "value": "test" + }, + "arguments": [] + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/debug/ir.ll b/debug/ir.ll index 7e40bfa..ae0c3d0 100644 --- a/debug/ir.ll +++ b/debug/ir.ll @@ -4,18 +4,19 @@ target datalayout = "" @"true" = constant i1 1 @"false" = constant i1 0 +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" +} + define i32 @"main"() { main_entry: - %".2" = alloca float - store float 0x4014000000000000, float* %".2" - %".4" = load float, float* %".2" - %".5" = fcmp oeq float %".4", 0x4014000000000000 - br i1 %".5", label %"main_entry.if", label %"main_entry.else" -main_entry.if: - ret i32 1 -main_entry.else: - ret i32 0 -main_entry.endif: - ret i32 0 + %".2" = call i32 @"test"() + ret i32 %".2" } diff --git a/plasma_parser.py b/plasma_parser.py index b638116..fc9dc4c 100644 --- a/plasma_parser.py +++ b/plasma_parser.py @@ -5,7 +5,7 @@ from enum import Enum, auto from AST import Statement, Expression, Program from AST import ExpressionStatement, AssignmentStatement, FunctionStatement, ReturnStatement, BlockStatement, ReassignStatement, IfStatement -from AST import InfixExpression +from AST import InfixExpression, CallExpression from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral class PrecedenceType(Enum): @@ -31,7 +31,8 @@ PRECEDENCES: dict[TokenType, PrecedenceType] = { TokenType.LT: PrecedenceType.P_LESSGREATER, TokenType.GT: PrecedenceType.P_LESSGREATER, TokenType.LT_EQ: PrecedenceType.P_LESSGREATER, - TokenType.GT_EQ: PrecedenceType.P_LESSGREATER + TokenType.GT_EQ: PrecedenceType.P_LESSGREATER, + TokenType.LPAREN: PrecedenceType.P_CALL } class Parser: @@ -65,6 +66,7 @@ class Parser: TokenType.GT: self.__parse_infix_expression, TokenType.LT_EQ: self.__parse_infix_expression, TokenType.GT_EQ: self.__parse_infix_expression, + TokenType.LPAREN: self.__parse_call_expression } self.__next_token() @@ -305,6 +307,16 @@ class Parser: return None return expr + + 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 + + return expr + # endregion # region Prefix Methods diff --git a/tests/test.pla b/tests/test.pla index 015bf21..ac31582 100644 --- a/tests/test.pla +++ b/tests/test.pla @@ -1,5 +1,6 @@ test = Func(): Int { - return 123; + x: Int = 3; + return x + 2; } main = Func(): Int {