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