function arguments are getting added to the AST!

This commit is contained in:
SpookyDervish
2025-10-15 07:16:15 +11:00
parent 049db7c53a
commit 3c24b50a80
8 changed files with 123 additions and 25 deletions

22
AST.py
View File

@@ -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

View File

@@ -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
}
]
}
}
]

View File

@@ -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"()

View File

@@ -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 _:

View File

@@ -40,6 +40,7 @@ class TokenType(Enum):
RBRACE = "RBRACE"
COLON = "COLON"
SEMICOLON = "SEMICOLON"
COMMA = "COMMA"
# Keywords
RETURN = "RETURN"

View File

@@ -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__":

View File

@@ -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

View File

@@ -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);
}