function calls work!!!

This commit is contained in:
SpookyDervish
2025-10-15 06:59:29 +11:00
parent 170146ee7e
commit 049db7c53a
6 changed files with 119 additions and 15 deletions

16
AST.py
View File

@@ -16,6 +16,7 @@ class NodeType(Enum):
# Expressions # Expressions
InfixExpression = "InfixExpression" InfixExpression = "InfixExpression"
CallExpression = "CallExpression"
# Literals # Literals
IntegerLiteral = "IntegerLiteral" IntegerLiteral = "IntegerLiteral"
@@ -231,4 +232,19 @@ class InfixExpression(Expression):
"operator": self.operator, "operator": self.operator,
"right_node": self.right_node.json() "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 # endregion

View File

@@ -2,7 +2,7 @@ from llvmlite import ir
from AST import Node, NodeType, Program, Expression from AST import Node, NodeType, Program, Expression
from AST import ExpressionStatement, AssignmentStatement, BlockStatement, ReturnStatement, FunctionStatement, ReassignStatement, IfStatement 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 AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral
from environment import Environment from environment import Environment
@@ -69,6 +69,8 @@ class Compiler:
# Expressions # Expressions
case NodeType.InfixExpression: case NodeType.InfixExpression:
self.__visit_infix_expression(node) self.__visit_infix_expression(node)
case NodeType.CallExpression:
self.__visit_call_expression(node)
# region Visit Methods # region Visit Methods
def __visit_program(self, node: Program) -> None: def __visit_program(self, node: Program) -> None:
@@ -257,6 +259,21 @@ class Compiler:
Type = ir.IntType(1) Type = ir.IntType(1)
return value, Type 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
# endregion # endregion
@@ -283,4 +300,6 @@ class Compiler:
# expression value # expression value
case NodeType.InfixExpression: case NodeType.InfixExpression:
return self.__visit_infix_expression(node) return self.__visit_infix_expression(node)
case NodeType.CallExpression:
return self.__visit_call_expression(node)
# endregion # endregion

55
debug/ast.json Normal file
View File

@@ -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": []
}
}
]
}
}
}
]
}

View File

@@ -4,18 +4,19 @@ target datalayout = ""
@"true" = constant i1 1 @"true" = constant i1 1
@"false" = constant i1 0 @"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"() define i32 @"main"()
{ {
main_entry: main_entry:
%".2" = alloca float %".2" = call i32 @"test"()
store float 0x4014000000000000, float* %".2" ret i32 %".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
} }

View File

@@ -5,7 +5,7 @@ from enum import Enum, auto
from AST import Statement, Expression, Program from AST import Statement, Expression, Program
from AST import ExpressionStatement, AssignmentStatement, FunctionStatement, ReturnStatement, BlockStatement, ReassignStatement, IfStatement 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 from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral
class PrecedenceType(Enum): class PrecedenceType(Enum):
@@ -31,7 +31,8 @@ PRECEDENCES: dict[TokenType, PrecedenceType] = {
TokenType.LT: PrecedenceType.P_LESSGREATER, TokenType.LT: PrecedenceType.P_LESSGREATER,
TokenType.GT: PrecedenceType.P_LESSGREATER, TokenType.GT: PrecedenceType.P_LESSGREATER,
TokenType.LT_EQ: 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: class Parser:
@@ -65,6 +66,7 @@ class Parser:
TokenType.GT: self.__parse_infix_expression, TokenType.GT: self.__parse_infix_expression,
TokenType.LT_EQ: self.__parse_infix_expression, TokenType.LT_EQ: self.__parse_infix_expression,
TokenType.GT_EQ: self.__parse_infix_expression, TokenType.GT_EQ: self.__parse_infix_expression,
TokenType.LPAREN: self.__parse_call_expression
} }
self.__next_token() self.__next_token()
@@ -305,6 +307,16 @@ class Parser:
return None return None
return expr 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 # endregion
# region Prefix Methods # region Prefix Methods

View File

@@ -1,5 +1,6 @@
test = Func(): Int { test = Func(): Int {
return 123; x: Int = 3;
return x + 2;
} }
main = Func(): Int { main = Func(): Int {