diff --git a/compiler.py b/compiler.py index 2e85c61..051a4d3 100644 --- a/compiler.py +++ b/compiler.py @@ -3,7 +3,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, CallExpression -from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral +from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral, StringLiteral from AST import FunctionParameter from environment import Environment @@ -18,7 +18,9 @@ class Compiler: "Int": ir.IntType(32), "Long": ir.IntType(64), "Float": ir.FloatType(), - "Double": ir.DoubleType() + "Double": ir.DoubleType(), + "String": ir.PointerType(ir.IntType(8)), + "Nil": ir.VoidType() } self.module: ir.Module = ir.Module("main") @@ -29,6 +31,14 @@ class Compiler: self.__initialize_builtins() def __initialize_builtins(self) -> None: + def __init_print() -> ir.Function: + fnty: ir.FunctionType = ir.FunctionType( + self.type_map["Int"], + [ir.IntType(8).as_pointer()], + var_arg=True + ) + return ir.Function(self.module, fnty, "printf") + def __init_booleans() -> tuple[ir.GlobalVariable, ir.GlobalVariable]: bool_type: ir.Type = self.type_map["Bool"] @@ -42,6 +52,8 @@ class Compiler: return true_var, false_var + self.environment.define("print", __init_print(), ir.IntType(32)) + true_var, false_var = __init_booleans() self.environment.define("true", true_var, true_var.type) self.environment.define("false", false_var, false_var.type) @@ -315,10 +327,20 @@ class Compiler: case NodeType.BooleanLiteral: node: BooleanLiteral = node return ir.Constant(ir.IntType(1), 1 if node.value else 0), ir.IntType(1) + case NodeType.StringLiteral: + node: StringLiteral = node + string, Type = self.__convert_string(node.value) + return string, Type # expression value case NodeType.InfixExpression: return self.__visit_infix_expression(node) case NodeType.CallExpression: return self.__visit_call_expression(node) + + def __convert_string(self, string: str) -> tuple[ir.Constant, ir.ArrayType]: + string = string.replace("\\n", "\n\0") + + fmt: str = f"{string}\0" + c_fmt: ir.Constant = ir.Constant(ir.ArrayType(ir.IntType(8), len(fmt)), bytearray(fmt.encode("utf-8"))) # endregion \ No newline at end of file diff --git a/plasma_parser.py b/plasma_parser.py index 1ca19ec..b4178ea 100644 --- a/plasma_parser.py +++ b/plasma_parser.py @@ -6,7 +6,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, CallExpression -from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral +from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral, StringLiteral from AST import FunctionParameter class PrecedenceType(Enum): @@ -50,9 +50,12 @@ class Parser: TokenType.INT: self.__parse_int_literal, TokenType.FLOAT: self.__parse_float_literal, TokenType.LPAREN: self.__parse_grouped_expression, + TokenType.IF: self.__parse_if_statement, TokenType.TRUE: self.__parse_boolean, TokenType.FALSE: self.__parse_boolean, + + TokenType.STRING: self.__parse_string_literal, } self.infix_parse_functions: dict[Token, Callable] = { # 5 + 5 TokenType.PLUS: self.__parse_infix_expression, @@ -398,4 +401,7 @@ class Parser: def __parse_boolean(self) -> BooleanLiteral: return BooleanLiteral(value=self.__current_token_is(TokenType.TRUE)) + + def __parse_string_literal(self) -> StringLiteral: + return StringLiteral(value=self.current_token.literal) # endregion \ No newline at end of file