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)),
|
"String": ir.PointerType(ir.IntType(8)),
|
||||||
"Nil": ir.VoidType()
|
"Nil": ir.VoidType()
|
||||||
}
|
}
|
||||||
self.py_type_map: dict[str, type] = {
|
|
||||||
"Int": int,
|
|
||||||
"Float": float
|
|
||||||
}
|
|
||||||
|
|
||||||
self.module: ir.Module = ir.Module("main")
|
self.module: ir.Module = ir.Module("main")
|
||||||
self.builder: ir.IRBuilder = ir.IRBuilder()
|
self.builder: ir.IRBuilder = ir.IRBuilder()
|
||||||
@@ -55,13 +51,14 @@ class Compiler:
|
|||||||
)
|
)
|
||||||
return ir.Function(self.module, fnty, "printf")
|
return ir.Function(self.module, fnty, "printf")
|
||||||
|
|
||||||
def __init_sqrt() -> ir.Function:
|
def __init_pow() -> ir.Function:
|
||||||
fnty: ir.FunctionType = ir.FunctionType(
|
fnty: ir.FunctionType = ir.FunctionType(
|
||||||
self.type_map["Float"],
|
self.type_map["Float"],
|
||||||
[ir.DoubleType()],
|
[ir.DoubleType(), ir.DoubleType()],
|
||||||
var_arg=False
|
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]:
|
def __init_booleans() -> tuple[ir.GlobalVariable, ir.GlobalVariable]:
|
||||||
bool_type: ir.Type = self.type_map["Bool"]
|
bool_type: ir.Type = self.type_map["Bool"]
|
||||||
@@ -74,14 +71,12 @@ class Compiler:
|
|||||||
false_var.initializer = ir.Constant(bool_type, 0)
|
false_var.initializer = ir.Constant(bool_type, 0)
|
||||||
false_var.global_constant = True
|
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("print", __init_print(), ir.IntType(32))
|
||||||
self.environment.define("sqrt", __init_sqrt(), ir.IntType(32))
|
__init_booleans()
|
||||||
|
__init_pow()
|
||||||
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 __increment_counter(self) -> int:
|
def __increment_counter(self) -> int:
|
||||||
self.counter += 1
|
self.counter += 1
|
||||||
@@ -138,19 +133,24 @@ class Compiler:
|
|||||||
def __visit_assignment_statement(self, node: AssignmentStatement) -> None:
|
def __visit_assignment_statement(self, node: AssignmentStatement) -> None:
|
||||||
name: str = node.name.value
|
name: str = node.name.value
|
||||||
value: Expression = node.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:
|
if self.environment.lookup(name) is None:
|
||||||
# Define and allocate the new variable
|
# Define and allocate the new variable
|
||||||
ptr = self.builder.alloca(Type)
|
ptr = self.builder.alloca(value_type)
|
||||||
|
|
||||||
# Storing the value to the ptr
|
# 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
|
# Add the variable to the environment
|
||||||
self.environment.define(name, ptr, Type)
|
self.environment.define(name, ptr, value_type)
|
||||||
else:
|
else:
|
||||||
ptr, _ = self.environment.lookup(name)
|
ptr, _ = self.environment.lookup(name)
|
||||||
self.builder.store(value, ptr)
|
self.builder.store(value, ptr)
|
||||||
@@ -226,11 +226,11 @@ class Compiler:
|
|||||||
var_ptr, _ = self.environment.lookup(name)
|
var_ptr, _ = self.environment.lookup(name)
|
||||||
orig_value = self.builder.load(var_ptr)
|
orig_value = self.builder.load(var_ptr)
|
||||||
|
|
||||||
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.FloatType):
|
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.DoubleType):
|
||||||
orig_value = self.builder.sitofp(orig_value, ir.FloatType())
|
orig_value = self.builder.sitofp(orig_value, ir.DoubleType())
|
||||||
|
|
||||||
if isinstance(orig_value.type, ir.FloatType) and isinstance(right_type, ir.IntType):
|
if isinstance(orig_value.type, ir.DoubleType) and isinstance(right_type, ir.IntType):
|
||||||
right_value = self.builder.sitofp(right_value, ir.FloatType())
|
right_value = self.builder.sitofp(right_value, ir.DoubleType())
|
||||||
|
|
||||||
value = None
|
value = None
|
||||||
Type = None
|
Type = None
|
||||||
@@ -396,6 +396,7 @@ class Compiler:
|
|||||||
|
|
||||||
value = None
|
value = None
|
||||||
Type = None
|
Type = None
|
||||||
|
|
||||||
if isinstance(right_type, ir.IntType) and isinstance(left_type, ir.IntType):
|
if isinstance(right_type, ir.IntType) and isinstance(left_type, ir.IntType):
|
||||||
Type = self.type_map["Int"]
|
Type = self.type_map["Int"]
|
||||||
match operator:
|
match operator:
|
||||||
@@ -409,9 +410,6 @@ class Compiler:
|
|||||||
value = self.builder.sdiv(left_value, right_value)
|
value = self.builder.sdiv(left_value, right_value)
|
||||||
case "%":
|
case "%":
|
||||||
value = self.builder.srem(left_value, right_value)
|
value = self.builder.srem(left_value, right_value)
|
||||||
case "^":
|
|
||||||
# TODO
|
|
||||||
pass
|
|
||||||
case "<":
|
case "<":
|
||||||
value = self.builder.icmp_signed('<', left_value, right_value)
|
value = self.builder.icmp_signed('<', left_value, right_value)
|
||||||
Type = ir.IntType(1)
|
Type = ir.IntType(1)
|
||||||
@@ -430,7 +428,7 @@ class Compiler:
|
|||||||
case "!=":
|
case "!=":
|
||||||
value = self.builder.icmp_signed('!=', left_value, right_value)
|
value = self.builder.icmp_signed('!=', left_value, right_value)
|
||||||
Type = ir.IntType(1)
|
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"]
|
Type = self.type_map["Float"]
|
||||||
match operator:
|
match operator:
|
||||||
case "+":
|
case "+":
|
||||||
@@ -443,9 +441,6 @@ class Compiler:
|
|||||||
value = self.builder.fdiv(left_value, right_value)
|
value = self.builder.fdiv(left_value, right_value)
|
||||||
case "%":
|
case "%":
|
||||||
value = self.builder.frem(left_value, right_value)
|
value = self.builder.frem(left_value, right_value)
|
||||||
case "^":
|
|
||||||
# TODO
|
|
||||||
pass
|
|
||||||
case "<":
|
case "<":
|
||||||
value = self.builder.fcmp_ordered('<', left_value, right_value)
|
value = self.builder.fcmp_ordered('<', left_value, right_value)
|
||||||
Type = ir.IntType(1)
|
Type = ir.IntType(1)
|
||||||
@@ -464,6 +459,68 @@ class Compiler:
|
|||||||
case "!=":
|
case "!=":
|
||||||
value = self.builder.fcmp_ordered('!=', left_value, right_value)
|
value = self.builder.fcmp_ordered('!=', left_value, right_value)
|
||||||
Type = ir.IntType(1)
|
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
|
return value, Type
|
||||||
|
|
||||||
@@ -483,8 +540,8 @@ class Compiler:
|
|||||||
case "print":
|
case "print":
|
||||||
ret = self.builtin_print(params=args, return_type=types[0])
|
ret = self.builtin_print(params=args, return_type=types[0])
|
||||||
ret_type = self.type_map["Int"]
|
ret_type = self.type_map["Int"]
|
||||||
case "sqrt":
|
case "pow":
|
||||||
ret = self.builtin_sqrt(params=args)
|
ret = self.builtin_pow(params=args)
|
||||||
ret_type = self.type_map["Float"]
|
ret_type = self.type_map["Float"]
|
||||||
case _:
|
case _:
|
||||||
if not self.environment.lookup(name):
|
if not self.environment.lookup(name):
|
||||||
@@ -505,11 +562,11 @@ class Compiler:
|
|||||||
Type = None
|
Type = None
|
||||||
value = None
|
value = None
|
||||||
|
|
||||||
if isinstance(right_type, ir.FloatType):
|
if isinstance(right_type, ir.DoubleType):
|
||||||
Type = ir.FloatType
|
Type = ir.DoubleType
|
||||||
match operator:
|
match operator:
|
||||||
case "-":
|
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 "!":
|
case "!":
|
||||||
value = ir.Constant(ir.IntType(1), 0)
|
value = ir.Constant(ir.IntType(1), 0)
|
||||||
elif isinstance(right_type, ir.IntType):
|
elif isinstance(right_type, ir.IntType):
|
||||||
@@ -538,13 +595,13 @@ class Compiler:
|
|||||||
case "++":
|
case "++":
|
||||||
if isinstance(orig_value.type, ir.IntType):
|
if isinstance(orig_value.type, ir.IntType):
|
||||||
value = self.builder.add(orig_value, ir.Constant(ir.IntType(32), 1))
|
value = self.builder.add(orig_value, ir.Constant(ir.IntType(32), 1))
|
||||||
elif isinstance(orig_value.type, ir.FloatType):
|
elif isinstance(orig_value.type, ir.DoubleType):
|
||||||
value = self.builder.fadd(orig_value, ir.Constant(ir.FloatType(), 1.0))
|
value = self.builder.fadd(orig_value, ir.Constant(ir.DoubleType(), 1.0))
|
||||||
case "--":
|
case "--":
|
||||||
if isinstance(orig_value.type, ir.IntType):
|
if isinstance(orig_value.type, ir.IntType):
|
||||||
value = self.builder.sub(orig_value, ir.Constant(ir.IntType(32), 1))
|
value = self.builder.sub(orig_value, ir.Constant(ir.IntType(32), 1))
|
||||||
elif isinstance(orig_value.type, ir.FloatType):
|
elif isinstance(orig_value.type, ir.DoubleType):
|
||||||
value = self.builder.fsub(orig_value, ir.Constant(ir.FloatType(), 1.0))
|
value = self.builder.fsub(orig_value, ir.Constant(ir.DoubleType(), 1.0))
|
||||||
|
|
||||||
self.builder.store(value, var_ptr)
|
self.builder.store(value, var_ptr)
|
||||||
# endregion
|
# endregion
|
||||||
@@ -564,7 +621,13 @@ class Compiler:
|
|||||||
return ir.Constant(Type, value), Type
|
return ir.Constant(Type, value), Type
|
||||||
case NodeType.IdentifierLiteral:
|
case NodeType.IdentifierLiteral:
|
||||||
node: IdentifierLiteral = node
|
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
|
return self.builder.load(ptr), Type
|
||||||
case NodeType.BooleanLiteral:
|
case NodeType.BooleanLiteral:
|
||||||
node: BooleanLiteral = node
|
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())
|
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])
|
return self.builder.call(func, [fmt_arg, *rest_params])
|
||||||
|
|
||||||
def builtin_sqrt(self, params: list[ir.Instruction]) -> None:
|
def builtin_pow(self, params: list[ir.Instruction]) -> None:
|
||||||
func, _ = self.environment.lookup("sqrt")
|
func, _ = self.environment.lookup("pow")
|
||||||
|
|
||||||
c_float = self.builder.alloca(self.type_map["Float"])
|
rest_params = params[1:]
|
||||||
self.builder.store(params[0], c_float)
|
|
||||||
|
|
||||||
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]
|
c_fmt: ir.LoadInstr = params[0]
|
||||||
g_var_ptr = c_fmt.operands[0]
|
g_var_ptr = c_fmt.operands[0]
|
||||||
float_val = self.builder.load(g_var_ptr)
|
val = self.builder.load(g_var_ptr)
|
||||||
return self.builder.call(func, [float_val])
|
return self.builder.call(func, [val, *rest_params])
|
||||||
else:
|
if isinstance(params[1], ir.LoadInstr) and not isinstance(params[0], ir.LoadInstr):
|
||||||
return self.builder.call(func, [params[0]])
|
# 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
|
||||||
# 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()
|
et = time.time()
|
||||||
|
|
||||||
#print(f"\n\nProgram returned: {result}\n=== Executed in {round((et - st) * 1000, 6)} ms. ===")
|
print(f"\n\nProgram returned: {result}\n=== Executed in {round((et - st) * 1000, 6)} ms. ===")
|
||||||
exit(result)
|
#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 {
|
main = Func(): Int {
|
||||||
$print("%f\n", $sqrt(9.0));
|
$print("%f\n", $sqrt(100.0));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user