slowly fixing bugs and writing a math library
This commit is contained in:
176
compiler.py
176
compiler.py
@@ -27,10 +27,6 @@ class Compiler:
|
||||
"String": ir.PointerType(ir.IntType(8)),
|
||||
"Nil": ir.VoidType()
|
||||
}
|
||||
self.py_type_map: dict[str, type] = {
|
||||
"Int": int,
|
||||
"Float": float
|
||||
}
|
||||
|
||||
self.module: ir.Module = ir.Module("main")
|
||||
self.builder: ir.IRBuilder = ir.IRBuilder()
|
||||
@@ -55,13 +51,14 @@ class Compiler:
|
||||
)
|
||||
return ir.Function(self.module, fnty, "printf")
|
||||
|
||||
def __init_sqrt() -> ir.Function:
|
||||
def __init_pow() -> ir.Function:
|
||||
fnty: ir.FunctionType = ir.FunctionType(
|
||||
self.type_map["Float"],
|
||||
[ir.DoubleType()],
|
||||
[ir.DoubleType(), ir.DoubleType()],
|
||||
var_arg=False
|
||||
)
|
||||
return ir.Function(self.module, fnty, "sqrt")
|
||||
self.environment.define("pow", ir.Function(self.module, fnty, "pow"), ir.IntType(32))
|
||||
|
||||
|
||||
def __init_booleans() -> tuple[ir.GlobalVariable, ir.GlobalVariable]:
|
||||
bool_type: ir.Type = self.type_map["Bool"]
|
||||
@@ -74,14 +71,12 @@ class Compiler:
|
||||
false_var.initializer = ir.Constant(bool_type, 0)
|
||||
false_var.global_constant = True
|
||||
|
||||
return true_var, false_var
|
||||
self.environment.define("true", true_var, true_var.type)
|
||||
self.environment.define("false", false_var, false_var.type)
|
||||
|
||||
self.environment.define("print", __init_print(), ir.IntType(32))
|
||||
self.environment.define("sqrt", __init_sqrt(), 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)
|
||||
__init_booleans()
|
||||
__init_pow()
|
||||
|
||||
def __increment_counter(self) -> int:
|
||||
self.counter += 1
|
||||
@@ -138,19 +133,24 @@ class Compiler:
|
||||
def __visit_assignment_statement(self, node: AssignmentStatement) -> None:
|
||||
name: str = node.name.value
|
||||
value: Expression = node.value
|
||||
value_type: str = node.value_type # TODO: implemented
|
||||
value_type = self.type_map[node.value_type] # TODO: implemented
|
||||
|
||||
value, Type = self.__resolve_value(node=value)
|
||||
print(value.json())
|
||||
value, Type = self.__resolve_value(value)
|
||||
|
||||
if self.environment.lookup(name) is None:
|
||||
# Define and allocate the new variable
|
||||
ptr = self.builder.alloca(Type)
|
||||
ptr = self.builder.alloca(value_type)
|
||||
|
||||
# Storing the value to the ptr
|
||||
self.builder.store(value, ptr)
|
||||
if isinstance(value_type, ir.DoubleType) and isinstance(Type, ir.IntType):
|
||||
self.builder.store(self.builder.sitofp(value, value_type), ptr)
|
||||
else:
|
||||
print(value_type, Type, value_type)
|
||||
self.builder.store(value, ptr)
|
||||
|
||||
# Add the variable to the environment
|
||||
self.environment.define(name, ptr, Type)
|
||||
self.environment.define(name, ptr, value_type)
|
||||
else:
|
||||
ptr, _ = self.environment.lookup(name)
|
||||
self.builder.store(value, ptr)
|
||||
@@ -226,11 +226,11 @@ class Compiler:
|
||||
var_ptr, _ = self.environment.lookup(name)
|
||||
orig_value = self.builder.load(var_ptr)
|
||||
|
||||
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.FloatType):
|
||||
orig_value = self.builder.sitofp(orig_value, ir.FloatType())
|
||||
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.DoubleType):
|
||||
orig_value = self.builder.sitofp(orig_value, ir.DoubleType())
|
||||
|
||||
if isinstance(orig_value.type, ir.FloatType) and isinstance(right_type, ir.IntType):
|
||||
right_value = self.builder.sitofp(right_value, ir.FloatType())
|
||||
if isinstance(orig_value.type, ir.DoubleType) and isinstance(right_type, ir.IntType):
|
||||
right_value = self.builder.sitofp(right_value, ir.DoubleType())
|
||||
|
||||
value = None
|
||||
Type = None
|
||||
@@ -396,6 +396,7 @@ class Compiler:
|
||||
|
||||
value = None
|
||||
Type = None
|
||||
|
||||
if isinstance(right_type, ir.IntType) and isinstance(left_type, ir.IntType):
|
||||
Type = self.type_map["Int"]
|
||||
match operator:
|
||||
@@ -409,9 +410,6 @@ class Compiler:
|
||||
value = self.builder.sdiv(left_value, right_value)
|
||||
case "%":
|
||||
value = self.builder.srem(left_value, right_value)
|
||||
case "^":
|
||||
# TODO
|
||||
pass
|
||||
case "<":
|
||||
value = self.builder.icmp_signed('<', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
@@ -430,7 +428,7 @@ class Compiler:
|
||||
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):
|
||||
elif isinstance(right_type, ir.DoubleType) and isinstance(left_type, ir.DoubleType):
|
||||
Type = self.type_map["Float"]
|
||||
match operator:
|
||||
case "+":
|
||||
@@ -443,9 +441,6 @@ class Compiler:
|
||||
value = self.builder.fdiv(left_value, right_value)
|
||||
case "%":
|
||||
value = self.builder.frem(left_value, right_value)
|
||||
case "^":
|
||||
# TODO
|
||||
pass
|
||||
case "<":
|
||||
value = self.builder.fcmp_ordered('<', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
@@ -464,6 +459,68 @@ class Compiler:
|
||||
case "!=":
|
||||
value = self.builder.fcmp_ordered('!=', left_value, right_value)
|
||||
Type = ir.IntType(1)
|
||||
elif isinstance(right_type, ir.IntType) and isinstance(left_type, ir.DoubleType):
|
||||
Type = self.type_map["Float"]
|
||||
match operator:
|
||||
case "+":
|
||||
value = self.builder.fadd(left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
case "-":
|
||||
value = self.builder.fsub(left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
case "*":
|
||||
value = self.builder.fmul(left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
case "/":
|
||||
value = self.builder.fdiv(left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
case "%":
|
||||
value = self.builder.frem(left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
case "<":
|
||||
value = self.builder.fcmp_ordered('<', left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
Type = ir.IntType(1)
|
||||
case "<=":
|
||||
value = self.builder.fcmp_ordered('<=', left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
Type = ir.IntType(1)
|
||||
case ">":
|
||||
value = self.builder.fcmp_ordered('>', left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
Type = ir.IntType(1)
|
||||
case ">=":
|
||||
value = self.builder.fcmp_ordered('>=', left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
Type = ir.IntType(1)
|
||||
case "==":
|
||||
value = self.builder.fcmp_ordered('==', left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
Type = ir.IntType(1)
|
||||
case "!=":
|
||||
value = self.builder.fcmp_ordered('!=', left_value, self.builder.sitofp(right_value, ir.DoubleType()))
|
||||
Type = ir.IntType(1)
|
||||
elif isinstance(right_type, ir.DoubleType) and isinstance(left_type, ir.IntType):
|
||||
Type = self.type_map["Float"]
|
||||
match operator:
|
||||
case "+":
|
||||
value = self.builder.fadd(self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
case "-":
|
||||
value = self.builder.fsub(self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
case "*":
|
||||
value = self.builder.fmul(self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
case "/":
|
||||
value = self.builder.fdiv(self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
case "%":
|
||||
value = self.builder.frem(self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
case "<":
|
||||
value = self.builder.fcmp_ordered('<', self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
Type = ir.IntType(1)
|
||||
case "<=":
|
||||
value = self.builder.fcmp_ordered('<=', self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
Type = ir.IntType(1)
|
||||
case ">":
|
||||
value = self.builder.fcmp_ordered('>', self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
Type = ir.IntType(1)
|
||||
case ">=":
|
||||
value = self.builder.fcmp_ordered('>=', self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
Type = ir.IntType(1)
|
||||
case "==":
|
||||
value = self.builder.fcmp_ordered('==', self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
Type = ir.IntType(1)
|
||||
case "!=":
|
||||
value = self.builder.fcmp_ordered('!=', self.builder.sitofp(left_value, ir.DoubleType()), right_value)
|
||||
Type = ir.IntType(1)
|
||||
|
||||
return value, Type
|
||||
|
||||
@@ -483,8 +540,8 @@ class Compiler:
|
||||
case "print":
|
||||
ret = self.builtin_print(params=args, return_type=types[0])
|
||||
ret_type = self.type_map["Int"]
|
||||
case "sqrt":
|
||||
ret = self.builtin_sqrt(params=args)
|
||||
case "pow":
|
||||
ret = self.builtin_pow(params=args)
|
||||
ret_type = self.type_map["Float"]
|
||||
case _:
|
||||
if not self.environment.lookup(name):
|
||||
@@ -505,11 +562,11 @@ class Compiler:
|
||||
Type = None
|
||||
value = None
|
||||
|
||||
if isinstance(right_type, ir.FloatType):
|
||||
Type = ir.FloatType
|
||||
if isinstance(right_type, ir.DoubleType):
|
||||
Type = ir.DoubleType
|
||||
match operator:
|
||||
case "-":
|
||||
value = self.builder.fmul(right_value, ir.Constant(ir.FloatType(), -1.0))
|
||||
value = self.builder.fmul(right_value, ir.Constant(ir.DoubleType(), -1.0))
|
||||
case "!":
|
||||
value = ir.Constant(ir.IntType(1), 0)
|
||||
elif isinstance(right_type, ir.IntType):
|
||||
@@ -538,13 +595,13 @@ class Compiler:
|
||||
case "++":
|
||||
if isinstance(orig_value.type, ir.IntType):
|
||||
value = self.builder.add(orig_value, ir.Constant(ir.IntType(32), 1))
|
||||
elif isinstance(orig_value.type, ir.FloatType):
|
||||
value = self.builder.fadd(orig_value, ir.Constant(ir.FloatType(), 1.0))
|
||||
elif isinstance(orig_value.type, ir.DoubleType):
|
||||
value = self.builder.fadd(orig_value, ir.Constant(ir.DoubleType(), 1.0))
|
||||
case "--":
|
||||
if isinstance(orig_value.type, ir.IntType):
|
||||
value = self.builder.sub(orig_value, ir.Constant(ir.IntType(32), 1))
|
||||
elif isinstance(orig_value.type, ir.FloatType):
|
||||
value = self.builder.fsub(orig_value, ir.Constant(ir.FloatType(), 1.0))
|
||||
elif isinstance(orig_value.type, ir.DoubleType):
|
||||
value = self.builder.fsub(orig_value, ir.Constant(ir.DoubleType(), 1.0))
|
||||
|
||||
self.builder.store(value, var_ptr)
|
||||
# endregion
|
||||
@@ -564,7 +621,13 @@ class Compiler:
|
||||
return ir.Constant(Type, value), Type
|
||||
case NodeType.IdentifierLiteral:
|
||||
node: IdentifierLiteral = node
|
||||
ptr, Type = self.environment.lookup(node.value)
|
||||
|
||||
idk = self.environment.lookup(node.value)
|
||||
if not idk:
|
||||
print(f"\"{node.value}\" is not defined in the current scope.")
|
||||
exit(1)
|
||||
|
||||
ptr, Type = idk
|
||||
return self.builder.load(ptr), Type
|
||||
case NodeType.BooleanLiteral:
|
||||
node: BooleanLiteral = node
|
||||
@@ -616,18 +679,35 @@ class Compiler:
|
||||
fmt_arg = self.builder.bitcast(self.module.get_global(f"__str_{self.counter}"), ir.IntType(8).as_pointer())
|
||||
return self.builder.call(func, [fmt_arg, *rest_params])
|
||||
|
||||
def builtin_sqrt(self, params: list[ir.Instruction]) -> None:
|
||||
func, _ = self.environment.lookup("sqrt")
|
||||
def builtin_pow(self, params: list[ir.Instruction]) -> None:
|
||||
func, _ = self.environment.lookup("pow")
|
||||
|
||||
c_float = self.builder.alloca(self.type_map["Float"])
|
||||
self.builder.store(params[0], c_float)
|
||||
rest_params = params[1:]
|
||||
|
||||
if isinstance(params[0], ir.LoadInstr):
|
||||
if isinstance(params[0], ir.LoadInstr) and not isinstance(params[1], ir.LoadInstr):
|
||||
# printing from a variable load instruction
|
||||
c_fmt: ir.LoadInstr = params[0]
|
||||
g_var_ptr = c_fmt.operands[0]
|
||||
float_val = self.builder.load(g_var_ptr)
|
||||
return self.builder.call(func, [float_val])
|
||||
else:
|
||||
return self.builder.call(func, [params[0]])
|
||||
val = self.builder.load(g_var_ptr)
|
||||
return self.builder.call(func, [val, *rest_params])
|
||||
if isinstance(params[1], ir.LoadInstr) and not isinstance(params[0], ir.LoadInstr):
|
||||
# printing from a variable load instruction
|
||||
c_fmt: ir.LoadInstr = params[1]
|
||||
g_var_ptr = c_fmt.operands[1]
|
||||
val = self.builder.load(g_var_ptr)
|
||||
return self.builder.call(func, [val, *rest_params])
|
||||
if isinstance(params[0], ir.LoadInstr) and isinstance(params[1], ir.LoadInstr):
|
||||
# printing from a variable load instruction
|
||||
c_fmt: ir.LoadInstr = params[0]
|
||||
g_var_ptr = c_fmt.operands[0]
|
||||
val = self.builder.load(g_var_ptr)
|
||||
|
||||
c_fmt2: ir.LoadInstr = params[1]
|
||||
g_var_ptr2 = c_fmt2.operands[1]
|
||||
val2 = self.builder.load(g_var_ptr2)
|
||||
|
||||
return self.builder.call(func, [val, val2])
|
||||
|
||||
return self.builder.call(func, params)
|
||||
# endregion
|
||||
# endregion
|
||||
27
ir.ll
27
ir.ll
@@ -1,27 +0,0 @@
|
||||
; ModuleID = "main"
|
||||
target triple = "x86_64-pc-windows-msvc"
|
||||
target datalayout = ""
|
||||
|
||||
declare i32 @"printf"(i8* %".1", ...)
|
||||
|
||||
declare double @"sqrt"(double %".1")
|
||||
|
||||
@"true" = constant i1 1
|
||||
@"false" = constant i1 0
|
||||
define i32 @"main"()
|
||||
{
|
||||
main_entry:
|
||||
%".2" = alloca double
|
||||
store double 0x4010000000000000, double* %".2"
|
||||
%".4" = call double @"sqrt"(double 0x4010000000000000)
|
||||
%".5" = alloca double
|
||||
store double %".4", double* %".5"
|
||||
%".7" = load double, double* %".5"
|
||||
%".8" = alloca [5 x i8]*
|
||||
store [5 x i8]* @"__str_1", [5 x i8]** %".8"
|
||||
%".10" = bitcast [5 x i8]* @"__str_1" to i8*
|
||||
%".11" = call i32 (i8*, ...) @"printf"(i8* %".10", double %".7")
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
@"__str_1" = internal constant [5 x i8] c"%f\0a\00\00"
|
||||
4
main.py
4
main.py
@@ -101,5 +101,5 @@ if __name__ == "__main__":
|
||||
|
||||
et = time.time()
|
||||
|
||||
#print(f"\n\nProgram returned: {result}\n=== Executed in {round((et - st) * 1000, 6)} ms. ===")
|
||||
exit(result)
|
||||
print(f"\n\nProgram returned: {result}\n=== Executed in {round((et - st) * 1000, 6)} ms. ===")
|
||||
#exit(result)
|
||||
@@ -0,0 +1,19 @@
|
||||
pi = Func(): Float {
|
||||
return 3.141592653589793;
|
||||
}
|
||||
|
||||
e = Func(): Float {
|
||||
return 2.718281828459045;
|
||||
}
|
||||
|
||||
rad = Func(degrees: Float): Float {
|
||||
return degrees * $pi() / 180;
|
||||
}
|
||||
|
||||
deg = Func(radians: Float): Float {
|
||||
return 180 * radians / $pi();
|
||||
}
|
||||
|
||||
sqrt = Func(n: Float): Float {
|
||||
return $pow(n, 0.5);
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
depend "tests/math.pla";
|
||||
|
||||
main = Func(): Int {
|
||||
$print("%f\n", $sqrt(9.0));
|
||||
$print("%f\n", $sqrt(100.0));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user