if statements work
This commit is contained in:
84
compiler.py
84
compiler.py
@@ -1,9 +1,9 @@
|
||||
from llvmlite import ir
|
||||
|
||||
from AST import Node, NodeType, Program, Expression
|
||||
from AST import ExpressionStatement, AssignmentStatement, BlockStatement, ReturnStatement, FunctionStatement, ReassignStatement
|
||||
from AST import ExpressionStatement, AssignmentStatement, BlockStatement, ReturnStatement, FunctionStatement, ReassignStatement, IfStatement
|
||||
from AST import InfixExpression
|
||||
from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral
|
||||
from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral
|
||||
|
||||
from environment import Environment
|
||||
|
||||
@@ -25,6 +25,26 @@ class Compiler:
|
||||
self.environment: Environment = Environment()
|
||||
self.errors: list[str] = []
|
||||
|
||||
self.__initialize_builtins()
|
||||
|
||||
def __initialize_builtins(self) -> None:
|
||||
def __init_booleans() -> tuple[ir.GlobalVariable, ir.GlobalVariable]:
|
||||
bool_type: ir.Type = self.type_map["Bool"]
|
||||
|
||||
true_var = ir.GlobalVariable(self.module, bool_type, "true")
|
||||
true_var.initializer = ir.Constant(bool_type, 1)
|
||||
true_var.global_constant = True
|
||||
|
||||
false_var = ir.GlobalVariable(self.module, bool_type, "false")
|
||||
false_var.initializer = ir.Constant(bool_type, 0)
|
||||
false_var.global_constant = True
|
||||
|
||||
return true_var, false_var
|
||||
|
||||
true_var, false_var = __init_booleans()
|
||||
self.environment.define("true", true_var, true_var.type)
|
||||
self.environment.define("false", false_var, false_var.type)
|
||||
|
||||
def compile(self, node: Node) -> None:
|
||||
match node.type():
|
||||
case NodeType.Program:
|
||||
@@ -43,6 +63,8 @@ class Compiler:
|
||||
self.__visit_return_statement(node)
|
||||
case NodeType.ReassignStatement:
|
||||
self.__visit_reassign_statement(node)
|
||||
case NodeType.IfStatement:
|
||||
self.__visit_if_statement(node)
|
||||
|
||||
# Expressions
|
||||
case NodeType.InfixExpression:
|
||||
@@ -129,6 +151,31 @@ class Compiler:
|
||||
else:
|
||||
ptr, _ = self.environment.lookup(name)
|
||||
self.builder.store(value, ptr)
|
||||
|
||||
def __visit_if_statement(self, node: IfStatement) -> None:
|
||||
condition = node.condition
|
||||
consequence = node.consequence
|
||||
alternative = node.alternative
|
||||
|
||||
test, _ = self.__resolve_value(condition)
|
||||
|
||||
if alternative is None:
|
||||
with self.builder.if_then(test):
|
||||
self.compile(consequence)
|
||||
else:
|
||||
with self.builder.if_else(test) as (true, otherwise):
|
||||
# Creating a condition branch
|
||||
# condition
|
||||
# / \
|
||||
# true false
|
||||
# / \
|
||||
# / \
|
||||
# if block else block
|
||||
with true:
|
||||
self.compile(consequence)
|
||||
|
||||
with otherwise:
|
||||
self.compile(alternative)
|
||||
# endregion
|
||||
|
||||
# region Expressions
|
||||
@@ -156,6 +203,21 @@ class Compiler:
|
||||
case "^":
|
||||
# TODO
|
||||
pass
|
||||
case "<":
|
||||
value = self.builder.icmp_signed('<', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
case "<=":
|
||||
value = self.builder.icmp_signed('<=', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
case ">":
|
||||
value = self.builder.icmp_signed('>', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
case ">=":
|
||||
value = self.builder.icmp_signed('>=', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
case "==":
|
||||
value = self.builder.icmp_signed('==', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
elif isinstance(right_type, ir.FloatType) and isinstance(left_type, ir.FloatType):
|
||||
Type = self.type_map["Float"]
|
||||
match operator:
|
||||
@@ -172,6 +234,21 @@ class Compiler:
|
||||
case "^":
|
||||
# TODO
|
||||
pass
|
||||
case "<":
|
||||
value = self.builder.fcmp_ordered('<', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
case "<=":
|
||||
value = self.builder.fcmp_ordered('<=', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
case ">":
|
||||
value = self.builder.fcmp_ordered('>', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
case ">=":
|
||||
value = self.builder.fcmp_ordered('>=', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
case "==":
|
||||
value = self.builder.fcmp_ordered('==', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
|
||||
return value, Type
|
||||
# endregion
|
||||
@@ -193,6 +270,9 @@ class Compiler:
|
||||
node: IdentifierLiteral = node
|
||||
ptr, Type = self.environment.lookup(node.value)
|
||||
return self.builder.load(ptr), Type
|
||||
case NodeType.BooleanLiteral:
|
||||
node: BooleanLiteral = node
|
||||
return ir.Constant(ir.IntType(1), 1 if node.value else 0), ir.IntType(1)
|
||||
|
||||
# expression value
|
||||
case NodeType.InfixExpression:
|
||||
|
||||
Reference in New Issue
Block a user