about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <[email protected]>2025-07-15 23:50:35 +0200
committerBaitinq <[email protected]>2025-07-15 23:59:21 +0200
commit4e2ce1b6c484a60b1d9f0d6bb917ba51d6258e4e (patch)
treeaa374e4bd197e5b9d0482f363e8c30cbb3fe55b1
parentBoostrap: Regenerate stage 0 in script (diff)
downloadpry-lang-4e2ce1b6c484a60b1d9f0d6bb917ba51d6258e4e.tar.gz
pry-lang-4e2ce1b6c484a60b1d9f0d6bb917ba51d6258e4e.tar.bz2
pry-lang-4e2ce1b6c484a60b1d9f0d6bb917ba51d6258e4e.zip
Feature: Add support for and and or operators
-rw-r--r--bootstrap/output.ll2906
-rw-r--r--grammar.ebnf8
-rw-r--r--src/codegen.pry21
-rw-r--r--src/llvm.pry2
-rw-r--r--src/parser.pry208
-rw-r--r--src/tokenizer.pry16
6 files changed, 1692 insertions, 1469 deletions
diff --git a/bootstrap/output.ll b/bootstrap/output.ll
index a50ae85..c851172 100644
--- a/bootstrap/output.ll
+++ b/bootstrap/output.ll
@@ -36,6 +36,7 @@ source_filename = "module"
 %NODE_EQUALITY_EXPRESSION_DATA = type { ptr, ptr, i64 }
 %NODE_UNARY_EXPRESSION_DATA = type { i64, ptr }
 %NODE_MULTIPLICATIVE_EXPRESSION_DATA = type { ptr, ptr, i64 }
+%NODE_LOGICAL_EXPRESSION_DATA = type { ptr, ptr, i1 }
 %NODE_IMPORT_DECLARATION_DATA = type { ptr, ptr }
 %NODE_PROGRAM_DATA = type { ptr, i64 }
 %HashMap = type { ptr, i64, ptr }
@@ -290,6 +291,7 @@ source_filename = "module"
 @NODE_FUNCTION_CALL_STATEMENT = global i64 5
 @NODE_IF_STATEMENT = global i64 6
 @NODE_WHILE_STATEMENT = global i64 7
+@NODE_LOGICAL_EXPRESSION = global i64 31
 @NODE_EQUALITY_EXPRESSION = global i64 8
 @NODE_ADDITIVE_EXPRESSION = global i64 9
 @NODE_MULTIPLICATIVE_EXPRESSION = global i64 10
@@ -384,47 +386,49 @@ source_filename = "module"
 @207 = private unnamed_addr constant [13 x i8] c"unnamed_func\00", align 1
 @208 = private unnamed_addr constant [11 x i8] c"entrypoint\00", align 1
 @209 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@210 = private unnamed_addr constant [5 x i8] c"bool\00", align 1
-@211 = private unnamed_addr constant [4 x i8] c"i64\00", align 1
-@212 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@213 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+@210 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+@211 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+@212 = private unnamed_addr constant [5 x i8] c"bool\00", align 1
+@213 = private unnamed_addr constant [4 x i8] c"i64\00", align 1
 @214 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
 @215 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
 @216 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
 @217 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@218 = private unnamed_addr constant [5 x i8] c"bool\00", align 1
+@218 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
 @219 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
 @220 = private unnamed_addr constant [5 x i8] c"bool\00", align 1
 @221 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@222 = private unnamed_addr constant [4 x i8] c"i64\00", align 1
+@222 = private unnamed_addr constant [5 x i8] c"bool\00", align 1
 @223 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@224 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@225 = private unnamed_addr constant [4 x i8] c"i64\00", align 1
+@224 = private unnamed_addr constant [4 x i8] c"i64\00", align 1
+@225 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
 @226 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@227 = private unnamed_addr constant [14 x i8] c"ASSERT 1: %d\0A\00", align 1
+@227 = private unnamed_addr constant [4 x i8] c"i64\00", align 1
 @228 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@229 = private unnamed_addr constant [13 x i8] c"ASSERT 2 %d\0A\00", align 1
-@230 = private unnamed_addr constant [19 x i8] c"NO variable 2: %s\0A\00", align 1
-@231 = private unnamed_addr constant [19 x i8] c"NO variable 1: %s\0A\00", align 1
-@232 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@233 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@234 = private unnamed_addr constant [11 x i8] c"then_block\00", align 1
-@235 = private unnamed_addr constant [12 x i8] c"merge_block\00", align 1
-@236 = private unnamed_addr constant [12 x i8] c"while_block\00", align 1
-@237 = private unnamed_addr constant [12 x i8] c"inner_block\00", align 1
-@238 = private unnamed_addr constant [12 x i8] c"outer_block\00", align 1
-@239 = private unnamed_addr constant [13 x i8] c"ASSERT 3 %d\0A\00", align 1
-@240 = private unnamed_addr constant [10 x i8] c"output.ll\00", align 1
-@241 = private unnamed_addr constant [19 x i8] c"Target output: %s\0A\00", align 1
-@242 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@243 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
-@244 = private unnamed_addr constant [25 x i8] c"Verification output: %s\0A\00", align 1
-@245 = private unnamed_addr constant [19 x i8] c"bootstrap_output.o\00", align 1
-@246 = private unnamed_addr constant [27 x i8] c"Object file generated: %s\0A\00", align 1
-@247 = private unnamed_addr constant [2 x i8] c"r\00", align 1
-@248 = private unnamed_addr constant [16 x i8] c"Need filename!\0A\00", align 1
-@249 = private unnamed_addr constant [14 x i8] c"--generate-ir\00", align 1
-@250 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+@229 = private unnamed_addr constant [14 x i8] c"ASSERT 1: %d\0A\00", align 1
+@230 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+@231 = private unnamed_addr constant [13 x i8] c"ASSERT 2 %d\0A\00", align 1
+@232 = private unnamed_addr constant [19 x i8] c"NO variable 2: %s\0A\00", align 1
+@233 = private unnamed_addr constant [19 x i8] c"NO variable 1: %s\0A\00", align 1
+@234 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+@235 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+@236 = private unnamed_addr constant [11 x i8] c"then_block\00", align 1
+@237 = private unnamed_addr constant [12 x i8] c"merge_block\00", align 1
+@238 = private unnamed_addr constant [12 x i8] c"while_block\00", align 1
+@239 = private unnamed_addr constant [12 x i8] c"inner_block\00", align 1
+@240 = private unnamed_addr constant [12 x i8] c"outer_block\00", align 1
+@241 = private unnamed_addr constant [13 x i8] c"ASSERT 3 %d\0A\00", align 1
+@242 = private unnamed_addr constant [10 x i8] c"output.ll\00", align 1
+@243 = private unnamed_addr constant [19 x i8] c"Target output: %s\0A\00", align 1
+@244 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+@245 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
+@246 = private unnamed_addr constant [25 x i8] c"Verification output: %s\0A\00", align 1
+@247 = private unnamed_addr constant [19 x i8] c"bootstrap_output.o\00", align 1
+@248 = private unnamed_addr constant [27 x i8] c"Object file generated: %s\0A\00", align 1
+@249 = private unnamed_addr constant [2 x i8] c"r\00", align 1
+@250 = private unnamed_addr constant [16 x i8] c"Need filename!\0A\00", align 1
+@251 = private unnamed_addr constant [14 x i8] c"--generate-ir\00", align 1
+@252 = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
 
 declare void @printf(ptr, ...)
 
@@ -5732,32 +5736,8 @@ entrypoint:
   %p = alloca ptr, align 8
   store ptr %0, ptr %p, align 8
   %1 = load ptr, ptr %p, align 8
-  %2 = call ptr @parser_accept_parse(ptr %1, ptr @parser_parse_equality_expression)
-  %ex = alloca ptr, align 8
-  store ptr %2, ptr %ex, align 8
-  %3 = load ptr, ptr %ex, align 8
-  %4 = icmp ne ptr %3, null
-  br i1 %4, label %then_block, label %merge_block
-
-then_block:                                       ; preds = %entrypoint
-  %5 = load ptr, ptr %ex, align 8
-  ret ptr %5
-
-merge_block:                                      ; preds = %entrypoint
-  %6 = load ptr, ptr %p, align 8
-  %7 = call ptr @parser_accept_parse(ptr %6, ptr @parser_parse_additive_expression)
-  %ax = alloca ptr, align 8
-  store ptr %7, ptr %ax, align 8
-  %8 = load ptr, ptr %ax, align 8
-  %9 = icmp ne ptr %8, null
-  br i1 %9, label %then_block1, label %merge_block2
-
-then_block1:                                      ; preds = %merge_block
-  %10 = load ptr, ptr %ax, align 8
-  ret ptr %10
-
-merge_block2:                                     ; preds = %merge_block
-  ret ptr null
+  %2 = call ptr @parser_parse_logical_expression(ptr %1)
+  ret ptr %2
 }
 
 define ptr @parse_function_call_statement(ptr %0) {
@@ -5920,7 +5900,7 @@ then_block:                                       ; preds = %entrypoint
 merge_block:                                      ; preds = %entrypoint
   br label %while_block
 
-while_block:                                      ; preds = %merge_block6, %merge_block
+while_block:                                      ; preds = %merge_block4, %merge_block
   br i1 true, label %inner_block, label %outer_block
 
 inner_block:                                      ; preds = %while_block
@@ -5936,66 +5916,61 @@ inner_block:                                      ; preds = %while_block
   store ptr %10, ptr %minus, align 8
   %11 = load ptr, ptr %plus, align 8
   %12 = icmp eq ptr %11, null
-  br i1 %12, label %then_block1, label %merge_block4
+  %13 = load ptr, ptr %minus, align 8
+  %14 = icmp eq ptr %13, null
+  %15 = and i1 %12, %14
+  br i1 %15, label %then_block1, label %merge_block2
 
-outer_block:                                      ; preds = %then_block2, %while_block
-  %13 = load ptr, ptr %lhs, align 8
-  ret ptr %13
+outer_block:                                      ; preds = %then_block1, %while_block
+  %16 = load ptr, ptr %lhs, align 8
+  ret ptr %16
 
 then_block1:                                      ; preds = %inner_block
-  %14 = load ptr, ptr %minus, align 8
-  %15 = icmp eq ptr %14, null
-  br i1 %15, label %then_block2, label %merge_block3
-
-then_block2:                                      ; preds = %then_block1
   br label %outer_block
 
-merge_block3:                                     ; preds = %then_block1
-  br label %merge_block4
-
-merge_block4:                                     ; preds = %inner_block, %merge_block3
-  %16 = load ptr, ptr %p, align 8
-  %17 = call ptr @parser_parse_multiplicative_expression(ptr %16)
+merge_block2:                                     ; preds = %inner_block
+  %17 = load ptr, ptr %p, align 8
+  %18 = call ptr @parser_parse_multiplicative_expression(ptr %17)
   %rhs = alloca ptr, align 8
-  store ptr %17, ptr %rhs, align 8
-  %18 = load ptr, ptr %rhs, align 8
-  %19 = icmp eq ptr %18, null
-  br i1 %19, label %then_block5, label %merge_block6
+  store ptr %18, ptr %rhs, align 8
+  %19 = load ptr, ptr %rhs, align 8
+  %20 = icmp eq ptr %19, null
+  br i1 %20, label %then_block3, label %merge_block4
 
-then_block5:                                      ; preds = %merge_block4
+then_block3:                                      ; preds = %merge_block2
   ret ptr null
 
-merge_block6:                                     ; preds = %merge_block4
-  %20 = load ptr, ptr %p, align 8
-  %arena = getelementptr %parser, ptr %20, i32 0, i32 3
-  %21 = load ptr, ptr %arena, align 8
-  %22 = call ptr @arena_alloc(ptr %21, i64 24)
+merge_block4:                                     ; preds = %merge_block2
+  %21 = load ptr, ptr %p, align 8
+  %arena = getelementptr %parser, ptr %21, i32 0, i32 3
+  %22 = load ptr, ptr %arena, align 8
+  %23 = call ptr @arena_alloc(ptr %22, i64 24)
   %new_lhs_data = alloca ptr, align 8
-  store ptr %22, ptr %new_lhs_data, align 8
-  %23 = load ptr, ptr %new_lhs_data, align 8
-  %addition = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %23, i32 0, i32 0
-  %24 = load ptr, ptr %plus, align 8
-  %25 = icmp ne ptr %24, null
-  store i1 %25, ptr %addition, align 1
-  %26 = load ptr, ptr %new_lhs_data, align 8
-  %lhs7 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %26, i32 0, i32 1
-  %27 = load ptr, ptr %lhs, align 8
-  store ptr %27, ptr %lhs7, align 8
-  %28 = load ptr, ptr %new_lhs_data, align 8
-  %rhs8 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %28, i32 0, i32 2
-  %29 = load ptr, ptr %rhs, align 8
-  store ptr %29, ptr %rhs8, align 8
+  store ptr %23, ptr %new_lhs_data, align 8
+  %24 = load ptr, ptr %new_lhs_data, align 8
+  %addition = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %24, i32 0, i32 0
+  %25 = load ptr, ptr %plus, align 8
+  %26 = icmp ne ptr %25, null
+  store i1 %26, ptr %addition, align 1
+  %27 = load ptr, ptr %new_lhs_data, align 8
+  %lhs5 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %27, i32 0, i32 1
+  %28 = load ptr, ptr %lhs, align 8
+  store ptr %28, ptr %lhs5, align 8
+  %29 = load ptr, ptr %new_lhs_data, align 8
+  %rhs6 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %29, i32 0, i32 2
+  %30 = load ptr, ptr %rhs, align 8
+  store ptr %30, ptr %rhs6, align 8
   %new_lhs = alloca %Node, align 8
   %type = getelementptr %Node, ptr %new_lhs, i32 0, i32 0
-  %30 = load i64, ptr @NODE_ADDITIVE_EXPRESSION, align 4
-  store i64 %30, ptr %type, align 4
+  %31 = load i64, ptr @NODE_ADDITIVE_EXPRESSION, align 4
+  store i64 %31, ptr %type, align 4
   %data = getelementptr %Node, ptr %new_lhs, i32 0, i32 1
-  %31 = load ptr, ptr %new_lhs_data, align 8
-  store ptr %31, ptr %data, align 8
-  %32 = load ptr, ptr %p, align 8
-  %33 = load %Node, ptr %new_lhs, align 8
-  %34 = call ptr @create_node(ptr %32, %Node %33)
-  store ptr %34, ptr %lhs, align 8
+  %32 = load ptr, ptr %new_lhs_data, align 8
+  store ptr %32, ptr %data, align 8
+  %33 = load ptr, ptr %p, align 8
+  %34 = load %Node, ptr %new_lhs, align 8
+  %35 = call ptr @create_node(ptr %33, %Node %34)
+  store ptr %35, ptr %lhs, align 8
   br label %while_block
 }
 
@@ -7933,6 +7908,12 @@ then_block:                                       ; preds = %entrypoint
   ret ptr null
 
 merge_block:                                      ; preds = %entrypoint
+  br label %while_block
+
+while_block:                                      ; preds = %merge_block22, %merge_block
+  br i1 true, label %inner_block, label %outer_block
+
+inner_block:                                      ; preds = %while_block
   %typ = alloca i64, align 8
   store i64 -1, ptr %typ, align 4
   %5 = load ptr, ptr %p, align 8
@@ -7943,164 +7924,159 @@ merge_block:                                      ; preds = %entrypoint
   %8 = icmp ne ptr %7, null
   br i1 %8, label %then_block1, label %merge_block2
 
-then_block1:                                      ; preds = %merge_block
-  %9 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_EQ, align 4
-  store i64 %9, ptr %typ, align 4
+outer_block:                                      ; preds = %then_block19, %while_block
+  %9 = load ptr, ptr %lhs, align 8
+  ret ptr %9
+
+then_block1:                                      ; preds = %inner_block
+  %10 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_EQ, align 4
+  store i64 %10, ptr %typ, align 4
   br label %merge_block2
 
-merge_block2:                                     ; preds = %merge_block, %then_block1
-  %10 = load i64, ptr %typ, align 4
-  %11 = icmp eq i64 %10, -1
-  br i1 %11, label %then_block3, label %merge_block6
+merge_block2:                                     ; preds = %inner_block, %then_block1
+  %11 = load i64, ptr %typ, align 4
+  %12 = icmp eq i64 %11, -1
+  br i1 %12, label %then_block3, label %merge_block6
 
 then_block3:                                      ; preds = %merge_block2
-  %12 = load ptr, ptr %p, align 8
-  %13 = call ptr @parser_accept_parse(ptr %12, ptr @unnamed_func.46)
-  store ptr %13, ptr %ex, align 8
-  %14 = load ptr, ptr %ex, align 8
-  %15 = icmp ne ptr %14, null
-  br i1 %15, label %then_block4, label %merge_block5
+  %13 = load ptr, ptr %p, align 8
+  %14 = call ptr @parser_accept_parse(ptr %13, ptr @unnamed_func.46)
+  store ptr %14, ptr %ex, align 8
+  %15 = load ptr, ptr %ex, align 8
+  %16 = icmp ne ptr %15, null
+  br i1 %16, label %then_block4, label %merge_block5
 
 then_block4:                                      ; preds = %then_block3
-  %16 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_NE, align 4
-  store i64 %16, ptr %typ, align 4
+  %17 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_NE, align 4
+  store i64 %17, ptr %typ, align 4
   br label %merge_block5
 
 merge_block5:                                     ; preds = %then_block3, %then_block4
   br label %merge_block6
 
 merge_block6:                                     ; preds = %merge_block2, %merge_block5
-  %17 = load i64, ptr %typ, align 4
-  %18 = icmp eq i64 %17, -1
-  br i1 %18, label %then_block7, label %merge_block10
+  %18 = load i64, ptr %typ, align 4
+  %19 = icmp eq i64 %18, -1
+  br i1 %19, label %then_block7, label %merge_block10
 
 then_block7:                                      ; preds = %merge_block6
-  %19 = load ptr, ptr %p, align 8
-  %20 = call ptr @parser_accept_parse(ptr %19, ptr @unnamed_func.47)
-  store ptr %20, ptr %ex, align 8
-  %21 = load ptr, ptr %ex, align 8
-  %22 = icmp ne ptr %21, null
-  br i1 %22, label %then_block8, label %merge_block9
+  %20 = load ptr, ptr %p, align 8
+  %21 = call ptr @parser_accept_parse(ptr %20, ptr @unnamed_func.47)
+  store ptr %21, ptr %ex, align 8
+  %22 = load ptr, ptr %ex, align 8
+  %23 = icmp ne ptr %22, null
+  br i1 %23, label %then_block8, label %merge_block9
 
 then_block8:                                      ; preds = %then_block7
-  %23 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_LE, align 4
-  store i64 %23, ptr %typ, align 4
+  %24 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_LE, align 4
+  store i64 %24, ptr %typ, align 4
   br label %merge_block9
 
 merge_block9:                                     ; preds = %then_block7, %then_block8
   br label %merge_block10
 
 merge_block10:                                    ; preds = %merge_block6, %merge_block9
-  %24 = load i64, ptr %typ, align 4
-  %25 = icmp eq i64 %24, -1
-  br i1 %25, label %then_block11, label %merge_block14
+  %25 = load i64, ptr %typ, align 4
+  %26 = icmp eq i64 %25, -1
+  br i1 %26, label %then_block11, label %merge_block14
 
 then_block11:                                     ; preds = %merge_block10
-  %26 = load ptr, ptr %p, align 8
-  %27 = call ptr @parser_accept_parse(ptr %26, ptr @unnamed_func.48)
-  store ptr %27, ptr %ex, align 8
-  %28 = load ptr, ptr %ex, align 8
-  %29 = icmp ne ptr %28, null
-  br i1 %29, label %then_block12, label %merge_block13
+  %27 = load ptr, ptr %p, align 8
+  %28 = call ptr @parser_accept_parse(ptr %27, ptr @unnamed_func.48)
+  store ptr %28, ptr %ex, align 8
+  %29 = load ptr, ptr %ex, align 8
+  %30 = icmp ne ptr %29, null
+  br i1 %30, label %then_block12, label %merge_block13
 
 then_block12:                                     ; preds = %then_block11
-  %30 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_GE, align 4
-  store i64 %30, ptr %typ, align 4
+  %31 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_GE, align 4
+  store i64 %31, ptr %typ, align 4
   br label %merge_block13
 
 merge_block13:                                    ; preds = %then_block11, %then_block12
   br label %merge_block14
 
 merge_block14:                                    ; preds = %merge_block10, %merge_block13
-  %31 = load i64, ptr %typ, align 4
-  %32 = icmp eq i64 %31, -1
-  br i1 %32, label %then_block15, label %merge_block18
+  %32 = load i64, ptr %typ, align 4
+  %33 = icmp eq i64 %32, -1
+  %34 = load ptr, ptr %p, align 8
+  %35 = load i64, ptr @TOKEN_LESS.30, align 4
+  %36 = call ptr @parser_accept_token(ptr %34, i64 %35)
+  %37 = icmp ne ptr %36, null
+  %38 = and i1 %33, %37
+  br i1 %38, label %then_block15, label %merge_block16
 
 then_block15:                                     ; preds = %merge_block14
-  %33 = load ptr, ptr %p, align 8
-  %34 = load i64, ptr @TOKEN_LESS.30, align 4
-  %35 = call ptr @parser_accept_token(ptr %33, i64 %34)
-  %36 = icmp ne ptr %35, null
-  br i1 %36, label %then_block16, label %merge_block17
+  %39 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_LT, align 4
+  store i64 %39, ptr %typ, align 4
+  br label %merge_block16
 
-then_block16:                                     ; preds = %then_block15
-  %37 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_LT, align 4
-  store i64 %37, ptr %typ, align 4
-  br label %merge_block17
+merge_block16:                                    ; preds = %merge_block14, %then_block15
+  %40 = load i64, ptr %typ, align 4
+  %41 = icmp eq i64 %40, -1
+  %42 = load ptr, ptr %p, align 8
+  %43 = load i64, ptr @TOKEN_GREATER.31, align 4
+  %44 = call ptr @parser_accept_token(ptr %42, i64 %43)
+  %45 = icmp ne ptr %44, null
+  %46 = and i1 %41, %45
+  br i1 %46, label %then_block17, label %merge_block18
 
-merge_block17:                                    ; preds = %then_block15, %then_block16
+then_block17:                                     ; preds = %merge_block16
+  %47 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_GT, align 4
+  store i64 %47, ptr %typ, align 4
   br label %merge_block18
 
-merge_block18:                                    ; preds = %merge_block14, %merge_block17
-  %38 = load i64, ptr %typ, align 4
-  %39 = icmp eq i64 %38, -1
-  br i1 %39, label %then_block19, label %merge_block22
+merge_block18:                                    ; preds = %merge_block16, %then_block17
+  %48 = load i64, ptr %typ, align 4
+  %49 = icmp eq i64 %48, -1
+  br i1 %49, label %then_block19, label %merge_block20
 
 then_block19:                                     ; preds = %merge_block18
-  %40 = load ptr, ptr %p, align 8
-  %41 = load i64, ptr @TOKEN_GREATER.31, align 4
-  %42 = call ptr @parser_accept_token(ptr %40, i64 %41)
-  %43 = icmp ne ptr %42, null
-  br i1 %43, label %then_block20, label %merge_block21
-
-then_block20:                                     ; preds = %then_block19
-  %44 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_GT, align 4
-  store i64 %44, ptr %typ, align 4
-  br label %merge_block21
-
-merge_block21:                                    ; preds = %then_block19, %then_block20
-  br label %merge_block22
-
-merge_block22:                                    ; preds = %merge_block18, %merge_block21
-  %45 = load i64, ptr %typ, align 4
-  %46 = icmp eq i64 %45, -1
-  br i1 %46, label %then_block23, label %merge_block24
-
-then_block23:                                     ; preds = %merge_block22
-  ret ptr null
+  br label %outer_block
 
-merge_block24:                                    ; preds = %merge_block22
-  %47 = load ptr, ptr %p, align 8
-  %48 = call ptr @parser_parse_additive_expression(ptr %47)
+merge_block20:                                    ; preds = %merge_block18
+  %50 = load ptr, ptr %p, align 8
+  %51 = call ptr @parser_parse_additive_expression(ptr %50)
   %rhs = alloca ptr, align 8
-  store ptr %48, ptr %rhs, align 8
-  %49 = load ptr, ptr %rhs, align 8
-  %50 = icmp eq ptr %49, null
-  br i1 %50, label %then_block25, label %merge_block26
+  store ptr %51, ptr %rhs, align 8
+  %52 = load ptr, ptr %rhs, align 8
+  %53 = icmp eq ptr %52, null
+  br i1 %53, label %then_block21, label %merge_block22
 
-then_block25:                                     ; preds = %merge_block24
+then_block21:                                     ; preds = %merge_block20
   ret ptr null
 
-merge_block26:                                    ; preds = %merge_block24
-  %51 = load ptr, ptr %p, align 8
-  %arena = getelementptr %parser, ptr %51, i32 0, i32 3
-  %52 = load ptr, ptr %arena, align 8
-  %53 = call ptr @arena_alloc(ptr %52, i64 24)
+merge_block22:                                    ; preds = %merge_block20
+  %54 = load ptr, ptr %p, align 8
+  %arena = getelementptr %parser, ptr %54, i32 0, i32 3
+  %55 = load ptr, ptr %arena, align 8
+  %56 = call ptr @arena_alloc(ptr %55, i64 24)
   %d = alloca ptr, align 8
-  store ptr %53, ptr %d, align 8
-  %54 = load ptr, ptr %d, align 8
-  %lhs27 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %54, i32 0, i32 0
-  %55 = load ptr, ptr %lhs, align 8
-  store ptr %55, ptr %lhs27, align 8
-  %56 = load ptr, ptr %d, align 8
-  %rhs28 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %56, i32 0, i32 1
-  %57 = load ptr, ptr %rhs, align 8
-  store ptr %57, ptr %rhs28, align 8
-  %58 = load ptr, ptr %d, align 8
-  %typ29 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %58, i32 0, i32 2
-  %59 = load i64, ptr %typ, align 4
-  store i64 %59, ptr %typ29, align 4
+  store ptr %56, ptr %d, align 8
+  %57 = load ptr, ptr %d, align 8
+  %lhs23 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %57, i32 0, i32 0
+  %58 = load ptr, ptr %lhs, align 8
+  store ptr %58, ptr %lhs23, align 8
+  %59 = load ptr, ptr %d, align 8
+  %rhs24 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %59, i32 0, i32 1
+  %60 = load ptr, ptr %rhs, align 8
+  store ptr %60, ptr %rhs24, align 8
+  %61 = load ptr, ptr %d, align 8
+  %typ25 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %61, i32 0, i32 2
+  %62 = load i64, ptr %typ, align 4
+  store i64 %62, ptr %typ25, align 4
   %n = alloca %Node, align 8
   %type = getelementptr %Node, ptr %n, i32 0, i32 0
-  %60 = load i64, ptr @NODE_EQUALITY_EXPRESSION, align 4
-  store i64 %60, ptr %type, align 4
+  %63 = load i64, ptr @NODE_EQUALITY_EXPRESSION, align 4
+  store i64 %63, ptr %type, align 4
   %data = getelementptr %Node, ptr %n, i32 0, i32 1
-  %61 = load ptr, ptr %d, align 8
-  store ptr %61, ptr %data, align 8
-  %62 = load ptr, ptr %p, align 8
-  %63 = load %Node, ptr %n, align 8
-  %64 = call ptr @create_node(ptr %62, %Node %63)
-  ret ptr %64
+  %64 = load ptr, ptr %d, align 8
+  store ptr %64, ptr %data, align 8
+  %65 = load ptr, ptr %p, align 8
+  %66 = load %Node, ptr %n, align 8
+  %67 = call ptr @create_node(ptr %65, %Node %66)
+  store ptr %67, ptr %lhs, align 8
+  br label %while_block
 }
 
 define ptr @unnamed_func.45(ptr %0) {
@@ -8308,91 +8284,81 @@ then_block:                                       ; preds = %entrypoint
 merge_block:                                      ; preds = %entrypoint, %then_block
   %6 = load i64, ptr %typ, align 4
   %7 = icmp eq i64 %6, -1
-  br i1 %7, label %then_block1, label %merge_block4
-
-then_block1:                                      ; preds = %merge_block
   %8 = load ptr, ptr %p, align 8
   %9 = load i64, ptr @TOKEN_MINUS.25, align 4
   %10 = call ptr @parser_accept_token(ptr %8, i64 %9)
   %11 = icmp ne ptr %10, null
-  br i1 %11, label %then_block2, label %merge_block3
+  %12 = and i1 %7, %11
+  br i1 %12, label %then_block1, label %merge_block2
 
-then_block2:                                      ; preds = %then_block1
-  %12 = load i64, ptr @UNARY_EXPRESSION_TYPE_MINUS, align 4
-  store i64 %12, ptr %typ, align 4
-  br label %merge_block3
+then_block1:                                      ; preds = %merge_block
+  %13 = load i64, ptr @UNARY_EXPRESSION_TYPE_MINUS, align 4
+  store i64 %13, ptr %typ, align 4
+  br label %merge_block2
+
+merge_block2:                                     ; preds = %merge_block, %then_block1
+  %14 = load i64, ptr %typ, align 4
+  %15 = icmp eq i64 %14, -1
+  %16 = load ptr, ptr %p, align 8
+  %17 = load i64, ptr @TOKEN_MUL.26, align 4
+  %18 = call ptr @parser_accept_token(ptr %16, i64 %17)
+  %19 = icmp ne ptr %18, null
+  %20 = and i1 %15, %19
+  br i1 %20, label %then_block3, label %merge_block4
 
-merge_block3:                                     ; preds = %then_block1, %then_block2
+then_block3:                                      ; preds = %merge_block2
+  %21 = load i64, ptr @UNARY_EXPRESSION_TYPE_STAR, align 4
+  store i64 %21, ptr %typ, align 4
   br label %merge_block4
 
-merge_block4:                                     ; preds = %merge_block, %merge_block3
-  %13 = load i64, ptr %typ, align 4
-  %14 = icmp eq i64 %13, -1
-  br i1 %14, label %then_block5, label %merge_block8
+merge_block4:                                     ; preds = %merge_block2, %then_block3
+  %22 = load i64, ptr %typ, align 4
+  %23 = icmp eq i64 %22, -1
+  br i1 %23, label %then_block5, label %merge_block6
 
 then_block5:                                      ; preds = %merge_block4
-  %15 = load ptr, ptr %p, align 8
-  %16 = load i64, ptr @TOKEN_MUL.26, align 4
-  %17 = call ptr @parser_accept_token(ptr %15, i64 %16)
-  %18 = icmp ne ptr %17, null
-  br i1 %18, label %then_block6, label %merge_block7
-
-then_block6:                                      ; preds = %then_block5
-  %19 = load i64, ptr @UNARY_EXPRESSION_TYPE_STAR, align 4
-  store i64 %19, ptr %typ, align 4
-  br label %merge_block7
-
-merge_block7:                                     ; preds = %then_block5, %then_block6
-  br label %merge_block8
-
-merge_block8:                                     ; preds = %merge_block4, %merge_block7
-  %20 = load i64, ptr %typ, align 4
-  %21 = icmp eq i64 %20, -1
-  br i1 %21, label %then_block9, label %merge_block10
-
-then_block9:                                      ; preds = %merge_block8
-  %22 = load ptr, ptr %p, align 8
-  %23 = call ptr @parser_parse_postfix_expression(ptr %22)
-  ret ptr %23
-
-merge_block10:                                    ; preds = %merge_block8
   %24 = load ptr, ptr %p, align 8
-  %arena = getelementptr %parser, ptr %24, i32 0, i32 3
-  %25 = load ptr, ptr %arena, align 8
-  %26 = call ptr @arena_alloc(ptr %25, i64 16)
+  %25 = call ptr @parser_parse_postfix_expression(ptr %24)
+  ret ptr %25
+
+merge_block6:                                     ; preds = %merge_block4
+  %26 = load ptr, ptr %p, align 8
+  %arena = getelementptr %parser, ptr %26, i32 0, i32 3
+  %27 = load ptr, ptr %arena, align 8
+  %28 = call ptr @arena_alloc(ptr %27, i64 16)
   %new_lhs_data = alloca ptr, align 8
-  store ptr %26, ptr %new_lhs_data, align 8
-  %27 = load ptr, ptr %new_lhs_data, align 8
-  %typ11 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %27, i32 0, i32 0
-  %28 = load i64, ptr %typ, align 4
-  store i64 %28, ptr %typ11, align 4
-  %29 = load ptr, ptr %p, align 8
-  %30 = call ptr @parser_parse_unary_expression(ptr %29)
+  store ptr %28, ptr %new_lhs_data, align 8
+  %29 = load ptr, ptr %new_lhs_data, align 8
+  %typ7 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %29, i32 0, i32 0
+  %30 = load i64, ptr %typ, align 4
+  store i64 %30, ptr %typ7, align 4
+  %31 = load ptr, ptr %p, align 8
+  %32 = call ptr @parser_parse_unary_expression(ptr %31)
   %e = alloca ptr, align 8
-  store ptr %30, ptr %e, align 8
-  %31 = load ptr, ptr %e, align 8
-  %32 = icmp eq ptr %31, null
-  br i1 %32, label %then_block12, label %merge_block13
+  store ptr %32, ptr %e, align 8
+  %33 = load ptr, ptr %e, align 8
+  %34 = icmp eq ptr %33, null
+  br i1 %34, label %then_block8, label %merge_block9
 
-then_block12:                                     ; preds = %merge_block10
+then_block8:                                      ; preds = %merge_block6
   ret ptr null
 
-merge_block13:                                    ; preds = %merge_block10
-  %33 = load ptr, ptr %new_lhs_data, align 8
-  %expression = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %33, i32 0, i32 1
-  %34 = load ptr, ptr %e, align 8
-  store ptr %34, ptr %expression, align 8
+merge_block9:                                     ; preds = %merge_block6
+  %35 = load ptr, ptr %new_lhs_data, align 8
+  %expression = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %35, i32 0, i32 1
+  %36 = load ptr, ptr %e, align 8
+  store ptr %36, ptr %expression, align 8
   %new_lhs = alloca %Node, align 8
   %type = getelementptr %Node, ptr %new_lhs, i32 0, i32 0
-  %35 = load i64, ptr @NODE_UNARY_EXPRESSION, align 4
-  store i64 %35, ptr %type, align 4
+  %37 = load i64, ptr @NODE_UNARY_EXPRESSION, align 4
+  store i64 %37, ptr %type, align 4
   %data = getelementptr %Node, ptr %new_lhs, i32 0, i32 1
-  %36 = load ptr, ptr %new_lhs_data, align 8
-  store ptr %36, ptr %data, align 8
-  %37 = load ptr, ptr %p, align 8
-  %38 = load %Node, ptr %new_lhs, align 8
-  %39 = call ptr @create_node(ptr %37, %Node %38)
-  ret ptr %39
+  %38 = load ptr, ptr %new_lhs_data, align 8
+  store ptr %38, ptr %data, align 8
+  %39 = load ptr, ptr %p, align 8
+  %40 = load %Node, ptr %new_lhs, align 8
+  %41 = call ptr @create_node(ptr %39, %Node %40)
+  ret ptr %41
 }
 
 define ptr @parser_parse_multiplicative_expression(ptr %0) {
@@ -8511,6 +8477,98 @@ merge_block10:                                    ; preds = %merge_block8
   br label %while_block
 }
 
+define ptr @parser_parse_logical_expression(ptr %0) {
+entrypoint:
+  %p = alloca ptr, align 8
+  store ptr %0, ptr %p, align 8
+  %1 = load ptr, ptr %p, align 8
+  %2 = call ptr @parser_parse_equality_expression(ptr %1)
+  %lhs = alloca ptr, align 8
+  store ptr %2, ptr %lhs, align 8
+  %3 = load ptr, ptr %lhs, align 8
+  %4 = icmp eq ptr %3, null
+  br i1 %4, label %then_block, label %merge_block
+
+then_block:                                       ; preds = %entrypoint
+  ret ptr null
+
+merge_block:                                      ; preds = %entrypoint
+  br label %while_block
+
+while_block:                                      ; preds = %merge_block4, %merge_block
+  br i1 true, label %inner_block, label %outer_block
+
+inner_block:                                      ; preds = %while_block
+  %5 = load ptr, ptr %p, align 8
+  %6 = load i64, ptr @TOKEN_AND.15, align 4
+  %7 = call ptr @parser_accept_token(ptr %5, i64 %6)
+  %an = alloca ptr, align 8
+  store ptr %7, ptr %an, align 8
+  %8 = load ptr, ptr %p, align 8
+  %9 = load i64, ptr @TOKEN_OR.16, align 4
+  %10 = call ptr @parser_accept_token(ptr %8, i64 %9)
+  %o = alloca ptr, align 8
+  store ptr %10, ptr %o, align 8
+  %11 = load ptr, ptr %an, align 8
+  %12 = icmp eq ptr %11, null
+  %13 = load ptr, ptr %o, align 8
+  %14 = icmp eq ptr %13, null
+  %15 = and i1 %12, %14
+  br i1 %15, label %then_block1, label %merge_block2
+
+outer_block:                                      ; preds = %then_block1, %while_block
+  %16 = load ptr, ptr %lhs, align 8
+  ret ptr %16
+
+then_block1:                                      ; preds = %inner_block
+  br label %outer_block
+
+merge_block2:                                     ; preds = %inner_block
+  %17 = load ptr, ptr %p, align 8
+  %18 = call ptr @parser_parse_equality_expression(ptr %17)
+  %rhs = alloca ptr, align 8
+  store ptr %18, ptr %rhs, align 8
+  %19 = load ptr, ptr %rhs, align 8
+  %20 = icmp eq ptr %19, null
+  br i1 %20, label %then_block3, label %merge_block4
+
+then_block3:                                      ; preds = %merge_block2
+  ret ptr null
+
+merge_block4:                                     ; preds = %merge_block2
+  %21 = load ptr, ptr %p, align 8
+  %arena = getelementptr %parser, ptr %21, i32 0, i32 3
+  %22 = load ptr, ptr %arena, align 8
+  %23 = call ptr @arena_alloc(ptr %22, i64 24)
+  %new_lhs_data = alloca ptr, align 8
+  store ptr %23, ptr %new_lhs_data, align 8
+  %24 = load ptr, ptr %new_lhs_data, align 8
+  %an5 = getelementptr %NODE_LOGICAL_EXPRESSION_DATA, ptr %24, i32 0, i32 2
+  %25 = load ptr, ptr %an, align 8
+  %26 = icmp ne ptr %25, null
+  store i1 %26, ptr %an5, align 1
+  %27 = load ptr, ptr %new_lhs_data, align 8
+  %lhs6 = getelementptr %NODE_LOGICAL_EXPRESSION_DATA, ptr %27, i32 0, i32 0
+  %28 = load ptr, ptr %lhs, align 8
+  store ptr %28, ptr %lhs6, align 8
+  %29 = load ptr, ptr %new_lhs_data, align 8
+  %rhs7 = getelementptr %NODE_LOGICAL_EXPRESSION_DATA, ptr %29, i32 0, i32 1
+  %30 = load ptr, ptr %rhs, align 8
+  store ptr %30, ptr %rhs7, align 8
+  %new_lhs = alloca %Node, align 8
+  %type = getelementptr %Node, ptr %new_lhs, i32 0, i32 0
+  %31 = load i64, ptr @NODE_LOGICAL_EXPRESSION, align 4
+  store i64 %31, ptr %type, align 4
+  %data = getelementptr %Node, ptr %new_lhs, i32 0, i32 1
+  %32 = load ptr, ptr %new_lhs_data, align 8
+  store ptr %32, ptr %data, align 8
+  %33 = load ptr, ptr %p, align 8
+  %34 = load %Node, ptr %new_lhs, align 8
+  %35 = call ptr @create_node(ptr %33, %Node %34)
+  store ptr %35, ptr %lhs, align 8
+  br label %while_block
+}
+
 define ptr @parse_assignment_statement(ptr %0) {
 entrypoint:
   %p = alloca ptr, align 8
@@ -9682,6 +9740,10 @@ declare ptr @LLVMBuildSDiv(ptr, ptr, ptr, ptr)
 
 declare ptr @LLVMBuildSRem(ptr, ptr, ptr, ptr)
 
+declare ptr @LLVMBuildAnd(ptr, ptr, ptr, ptr)
+
+declare ptr @LLVMBuildOr(ptr, ptr, ptr, ptr)
+
 declare ptr @LLVMBuildGEP2(ptr, ptr, ptr, ptr, i64, ptr)
 
 declare ptr @LLVMAddGlobal(ptr, ptr, ptr)
@@ -10939,7 +11001,7 @@ then_block24:                                     ; preds = %merge_block22
 merge_block25:                                    ; preds = %merge_block22
   %type26 = getelementptr %Node, ptr %stmt, i32 0, i32 0
   %50 = load i64, ptr %type26, align 4
-  call void (ptr, ...) @printf(ptr @239, i64 %50)
+  call void (ptr, ...) @printf(ptr @241, i64 %50)
   call void @assert(i1 false)
   ret i64 0
 }
@@ -10999,7 +11061,7 @@ then_block:                                       ; preds = %entrypoint
 then_block4:                                      ; preds = %then_block
   %name5 = getelementptr %NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, ptr %ident, i32 0, i32 0
   %24 = load ptr, ptr %name5, align 8
-  call void (ptr, ...) @printf(ptr @231, ptr %24)
+  call void (ptr, ...) @printf(ptr @233, ptr %24)
   call void @assert(i1 false)
   br label %merge_block
 
@@ -11034,7 +11096,7 @@ then_block6:                                      ; preds = %merge_block
   %42 = load ptr, ptr %function, align 8
   %value8 = getelementptr %Variable, ptr %42, i32 0, i32 0
   %43 = load ptr, ptr %value8, align 8
-  %44 = call ptr @LLVMBuildLoad2(ptr %38, ptr %41, ptr %43, ptr @232)
+  %44 = call ptr @LLVMBuildLoad2(ptr %38, ptr %41, ptr %43, ptr @234)
   store ptr %44, ptr %value7, align 8
   %45 = load ptr, ptr %function, align 8
   %node9 = getelementptr %Variable, ptr %45, i32 0, i32 2
@@ -11172,7 +11234,7 @@ outer_block:                                      ; preds = %while_block
   %115 = load ptr, ptr %value26, align 8
   %116 = load ptr, ptr %arguments, align 8
   %117 = load i64, ptr %i, align 4
-  %118 = call ptr @LLVMBuildCall2(ptr %111, ptr %113, ptr %115, ptr %116, i64 %117, ptr @233)
+  %118 = call ptr @LLVMBuildCall2(ptr %111, ptr %113, ptr %115, ptr %116, i64 %117, ptr @235)
   %res = alloca ptr, align 8
   store ptr %118, ptr %res, align 8
   %119 = load ptr, ptr %c, align 8
@@ -12163,19 +12225,19 @@ merge_block189:                                   ; preds = %merge_block88
   %450 = load ptr, ptr %expression, align 8
   %type190 = getelementptr %Node, ptr %450, i32 0, i32 0
   %451 = load i64, ptr %type190, align 4
-  %452 = load i64, ptr @NODE_EQUALITY_EXPRESSION, align 4
+  %452 = load i64, ptr @NODE_LOGICAL_EXPRESSION, align 4
   %453 = icmp eq i64 %451, %452
-  br i1 %453, label %then_block191, label %merge_block222
+  br i1 %453, label %then_block191, label %merge_block207
 
 then_block191:                                    ; preds = %merge_block189
   %454 = load ptr, ptr %expression, align 8
   %data192 = getelementptr %Node, ptr %454, i32 0, i32 1
   %455 = load ptr, ptr %data192, align 8
-  %456 = load %NODE_EQUALITY_EXPRESSION_DATA, ptr %455, align 8
-  %exp = alloca %NODE_EQUALITY_EXPRESSION_DATA, align 8
-  store %NODE_EQUALITY_EXPRESSION_DATA %456, ptr %exp, align 8
+  %456 = load %NODE_LOGICAL_EXPRESSION_DATA, ptr %455, align 8
+  %exp = alloca %NODE_LOGICAL_EXPRESSION_DATA, align 8
+  store %NODE_LOGICAL_EXPRESSION_DATA %456, ptr %exp, align 8
   %457 = load ptr, ptr %c, align 8
-  %lhs = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp, i32 0, i32 0
+  %lhs = getelementptr %NODE_LOGICAL_EXPRESSION_DATA, ptr %exp, i32 0, i32 0
   %458 = load ptr, ptr %lhs, align 8
   %459 = call ptr @codegen_generate_expression_value(ptr %457, ptr %458, ptr null)
   %lhs_value = alloca ptr, align 8
@@ -12184,7 +12246,7 @@ then_block191:                                    ; preds = %merge_block189
   %461 = icmp ne ptr %460, null
   call void @assert(i1 %461)
   %462 = load ptr, ptr %c, align 8
-  %rhs = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp, i32 0, i32 1
+  %rhs = getelementptr %NODE_LOGICAL_EXPRESSION_DATA, ptr %exp, i32 0, i32 1
   %463 = load ptr, ptr %rhs, align 8
   %464 = call ptr @codegen_generate_expression_value(ptr %462, ptr %463, ptr null)
   %rhs_value = alloca ptr, align 8
@@ -12201,1128 +12263,1224 @@ then_block191:                                    ; preds = %merge_block189
   %471 = load ptr, ptr %node_type194, align 8
   %472 = call i1 @compare_types(ptr %467, ptr %469, ptr %471, i1 false)
   call void @assert(i1 %472)
-  %op = alloca i64, align 8
-  store i64 -1, ptr %op, align 4
-  %typ = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp, i32 0, i32 2
-  %473 = load i64, ptr %typ, align 4
-  %474 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_EQ, align 4
-  %475 = icmp eq i64 %473, %474
-  br i1 %475, label %then_block195, label %merge_block196
+  %result = alloca ptr, align 8
+  store ptr null, ptr %result, align 8
+  %an = getelementptr %NODE_LOGICAL_EXPRESSION_DATA, ptr %exp, i32 0, i32 2
+  %473 = load i1, ptr %an, align 1
+  br i1 %473, label %then_block195, label %merge_block199
 
 then_block195:                                    ; preds = %then_block191
-  %476 = load i64, ptr @LLVMIntEQ, align 4
-  store i64 %476, ptr %op, align 4
-  br label %merge_block196
-
-merge_block196:                                   ; preds = %then_block191, %then_block195
-  %typ197 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp, i32 0, i32 2
-  %477 = load i64, ptr %typ197, align 4
-  %478 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_NE, align 4
-  %479 = icmp eq i64 %477, %478
-  br i1 %479, label %then_block198, label %merge_block199
-
-then_block198:                                    ; preds = %merge_block196
-  %480 = load i64, ptr @LLVMIntNE, align 4
-  store i64 %480, ptr %op, align 4
+  %474 = load ptr, ptr %c, align 8
+  %builder196 = getelementptr %codegen, ptr %474, i32 0, i32 2
+  %475 = load ptr, ptr %builder196, align 8
+  %476 = load ptr, ptr %lhs_value, align 8
+  %value197 = getelementptr %Variable, ptr %476, i32 0, i32 0
+  %477 = load ptr, ptr %value197, align 8
+  %478 = load ptr, ptr %rhs_value, align 8
+  %value198 = getelementptr %Variable, ptr %478, i32 0, i32 0
+  %479 = load ptr, ptr %value198, align 8
+  %480 = call ptr @LLVMBuildAnd(ptr %475, ptr %477, ptr %479, ptr @209)
+  store ptr %480, ptr %result, align 8
   br label %merge_block199
 
-merge_block199:                                   ; preds = %merge_block196, %then_block198
-  %typ200 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp, i32 0, i32 2
-  %481 = load i64, ptr %typ200, align 4
-  %482 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_GE, align 4
-  %483 = icmp eq i64 %481, %482
-  br i1 %483, label %then_block201, label %merge_block202
+merge_block199:                                   ; preds = %then_block191, %then_block195
+  %an200 = getelementptr %NODE_LOGICAL_EXPRESSION_DATA, ptr %exp, i32 0, i32 2
+  %481 = load i1, ptr %an200, align 1
+  %482 = icmp eq i1 %481, false
+  br i1 %482, label %then_block201, label %merge_block205
 
 then_block201:                                    ; preds = %merge_block199
-  %484 = load i64, ptr @LLVMIntSGE, align 4
-  store i64 %484, ptr %op, align 4
-  br label %merge_block202
-
-merge_block202:                                   ; preds = %merge_block199, %then_block201
-  %typ203 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp, i32 0, i32 2
-  %485 = load i64, ptr %typ203, align 4
-  %486 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_LE, align 4
-  %487 = icmp eq i64 %485, %486
-  br i1 %487, label %then_block204, label %merge_block205
-
-then_block204:                                    ; preds = %merge_block202
-  %488 = load i64, ptr @LLVMIntSLE, align 4
-  store i64 %488, ptr %op, align 4
+  %483 = load ptr, ptr %c, align 8
+  %builder202 = getelementptr %codegen, ptr %483, i32 0, i32 2
+  %484 = load ptr, ptr %builder202, align 8
+  %485 = load ptr, ptr %lhs_value, align 8
+  %value203 = getelementptr %Variable, ptr %485, i32 0, i32 0
+  %486 = load ptr, ptr %value203, align 8
+  %487 = load ptr, ptr %rhs_value, align 8
+  %value204 = getelementptr %Variable, ptr %487, i32 0, i32 0
+  %488 = load ptr, ptr %value204, align 8
+  %489 = call ptr @LLVMBuildOr(ptr %484, ptr %486, ptr %488, ptr @210)
+  store ptr %489, ptr %result, align 8
   br label %merge_block205
 
-merge_block205:                                   ; preds = %merge_block202, %then_block204
-  %typ206 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp, i32 0, i32 2
-  %489 = load i64, ptr %typ206, align 4
-  %490 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_LT, align 4
-  %491 = icmp eq i64 %489, %490
-  br i1 %491, label %then_block207, label %merge_block208
-
-then_block207:                                    ; preds = %merge_block205
-  %492 = load i64, ptr @LLVMIntSLT, align 4
-  store i64 %492, ptr %op, align 4
-  br label %merge_block208
-
-merge_block208:                                   ; preds = %merge_block205, %then_block207
-  %typ209 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp, i32 0, i32 2
-  %493 = load i64, ptr %typ209, align 4
-  %494 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_GT, align 4
-  %495 = icmp eq i64 %493, %494
-  br i1 %495, label %then_block210, label %merge_block211
-
-then_block210:                                    ; preds = %merge_block208
-  %496 = load i64, ptr @LLVMIntSGT, align 4
-  store i64 %496, ptr %op, align 4
-  br label %merge_block211
-
-merge_block211:                                   ; preds = %merge_block208, %then_block210
-  %497 = load i64, ptr %op, align 4
-  %498 = icmp ne i64 %497, -1
-  call void @assert(i1 %498)
-  %499 = load ptr, ptr %c, align 8
-  %builder212 = getelementptr %codegen, ptr %499, i32 0, i32 2
-  %500 = load ptr, ptr %builder212, align 8
-  %501 = load i64, ptr %op, align 4
-  %502 = load ptr, ptr %lhs_value, align 8
-  %value213 = getelementptr %Variable, ptr %502, i32 0, i32 0
-  %503 = load ptr, ptr %value213, align 8
-  %504 = load ptr, ptr %rhs_value, align 8
-  %value214 = getelementptr %Variable, ptr %504, i32 0, i32 0
-  %505 = load ptr, ptr %value214, align 8
-  %506 = call ptr @LLVMBuildICmp(ptr %500, i64 %501, ptr %503, ptr %505, ptr @209)
-  %cmp = alloca ptr, align 8
-  store ptr %506, ptr %cmp, align 8
-  %node_type215 = alloca %Node, align 8
-  %type216 = getelementptr %Node, ptr %node_type215, i32 0, i32 0
-  %507 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
-  store i64 %507, ptr %type216, align 4
-  %508 = load ptr, ptr %c, align 8
-  %arena217 = getelementptr %codegen, ptr %508, i32 0, i32 3
-  %509 = load ptr, ptr %arena217, align 8
-  %510 = call ptr @arena_alloc(ptr %509, i64 16)
-  %d218 = alloca ptr, align 8
-  store ptr %510, ptr %d218, align 8
-  %511 = load ptr, ptr %d218, align 8
-  %name219 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %511, i32 0, i32 0
-  store ptr @210, ptr %name219, align 8
-  %512 = load ptr, ptr %d218, align 8
-  %underlying_type220 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %512, i32 0, i32 1
-  store ptr null, ptr %underlying_type220, align 8
-  %data221 = getelementptr %Node, ptr %node_type215, i32 0, i32 1
-  %513 = load ptr, ptr %d218, align 8
-  store ptr %513, ptr %data221, align 8
-  %514 = load ptr, ptr %c, align 8
-  %515 = load ptr, ptr %cmp, align 8
-  %516 = load ptr, ptr %name, align 8
-  %517 = load ptr, ptr %expression, align 8
-  %518 = load ptr, ptr %c, align 8
-  %519 = load %Node, ptr %node_type215, align 8
-  %520 = call ptr @create_node(ptr %518, %Node %519)
-  %521 = call ptr @codegen_generate_literal(ptr %514, ptr %515, ptr %516, ptr %517, ptr %520)
-  ret ptr %521
-
-merge_block222:                                   ; preds = %merge_block189
-  %522 = load ptr, ptr %expression, align 8
-  %type223 = getelementptr %Node, ptr %522, i32 0, i32 0
-  %523 = load i64, ptr %type223, align 4
-  %524 = load i64, ptr @NODE_ADDITIVE_EXPRESSION, align 4
-  %525 = icmp eq i64 %523, %524
-  br i1 %525, label %then_block224, label %merge_block265
+merge_block205:                                   ; preds = %merge_block199, %then_block201
+  %490 = load ptr, ptr %result, align 8
+  %491 = icmp ne ptr %490, null
+  call void @assert(i1 %491)
+  %492 = load ptr, ptr %c, align 8
+  %493 = load ptr, ptr %result, align 8
+  %494 = load ptr, ptr %name, align 8
+  %495 = load ptr, ptr %expression, align 8
+  %496 = load ptr, ptr %lhs_value, align 8
+  %node_type206 = getelementptr %Variable, ptr %496, i32 0, i32 3
+  %497 = load ptr, ptr %node_type206, align 8
+  %498 = call ptr @codegen_generate_literal(ptr %492, ptr %493, ptr %494, ptr %495, ptr %497)
+  ret ptr %498
+
+merge_block207:                                   ; preds = %merge_block189
+  %499 = load ptr, ptr %expression, align 8
+  %type208 = getelementptr %Node, ptr %499, i32 0, i32 0
+  %500 = load i64, ptr %type208, align 4
+  %501 = load i64, ptr @NODE_EQUALITY_EXPRESSION, align 4
+  %502 = icmp eq i64 %500, %501
+  br i1 %502, label %then_block209, label %merge_block245
+
+then_block209:                                    ; preds = %merge_block207
+  %503 = load ptr, ptr %expression, align 8
+  %data210 = getelementptr %Node, ptr %503, i32 0, i32 1
+  %504 = load ptr, ptr %data210, align 8
+  %505 = load %NODE_EQUALITY_EXPRESSION_DATA, ptr %504, align 8
+  %exp211 = alloca %NODE_EQUALITY_EXPRESSION_DATA, align 8
+  store %NODE_EQUALITY_EXPRESSION_DATA %505, ptr %exp211, align 8
+  %506 = load ptr, ptr %c, align 8
+  %lhs212 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp211, i32 0, i32 0
+  %507 = load ptr, ptr %lhs212, align 8
+  %508 = call ptr @codegen_generate_expression_value(ptr %506, ptr %507, ptr null)
+  %lhs_value213 = alloca ptr, align 8
+  store ptr %508, ptr %lhs_value213, align 8
+  %509 = load ptr, ptr %lhs_value213, align 8
+  %510 = icmp ne ptr %509, null
+  call void @assert(i1 %510)
+  %511 = load ptr, ptr %c, align 8
+  %rhs214 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp211, i32 0, i32 1
+  %512 = load ptr, ptr %rhs214, align 8
+  %513 = call ptr @codegen_generate_expression_value(ptr %511, ptr %512, ptr null)
+  %rhs_value215 = alloca ptr, align 8
+  store ptr %513, ptr %rhs_value215, align 8
+  %514 = load ptr, ptr %rhs_value215, align 8
+  %515 = icmp ne ptr %514, null
+  call void @assert(i1 %515)
+  %516 = load ptr, ptr %c, align 8
+  %517 = load ptr, ptr %lhs_value213, align 8
+  %node_type216 = getelementptr %Variable, ptr %517, i32 0, i32 3
+  %518 = load ptr, ptr %node_type216, align 8
+  %519 = load ptr, ptr %rhs_value215, align 8
+  %node_type217 = getelementptr %Variable, ptr %519, i32 0, i32 3
+  %520 = load ptr, ptr %node_type217, align 8
+  %521 = call i1 @compare_types(ptr %516, ptr %518, ptr %520, i1 false)
+  call void @assert(i1 %521)
+  %op = alloca i64, align 8
+  store i64 -1, ptr %op, align 4
+  %typ = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp211, i32 0, i32 2
+  %522 = load i64, ptr %typ, align 4
+  %523 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_EQ, align 4
+  %524 = icmp eq i64 %522, %523
+  br i1 %524, label %then_block218, label %merge_block219
+
+then_block218:                                    ; preds = %then_block209
+  %525 = load i64, ptr @LLVMIntEQ, align 4
+  store i64 %525, ptr %op, align 4
+  br label %merge_block219
+
+merge_block219:                                   ; preds = %then_block209, %then_block218
+  %typ220 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp211, i32 0, i32 2
+  %526 = load i64, ptr %typ220, align 4
+  %527 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_NE, align 4
+  %528 = icmp eq i64 %526, %527
+  br i1 %528, label %then_block221, label %merge_block222
+
+then_block221:                                    ; preds = %merge_block219
+  %529 = load i64, ptr @LLVMIntNE, align 4
+  store i64 %529, ptr %op, align 4
+  br label %merge_block222
+
+merge_block222:                                   ; preds = %merge_block219, %then_block221
+  %typ223 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp211, i32 0, i32 2
+  %530 = load i64, ptr %typ223, align 4
+  %531 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_GE, align 4
+  %532 = icmp eq i64 %530, %531
+  br i1 %532, label %then_block224, label %merge_block225
 
 then_block224:                                    ; preds = %merge_block222
-  %526 = load ptr, ptr %expression, align 8
-  %data225 = getelementptr %Node, ptr %526, i32 0, i32 1
-  %527 = load ptr, ptr %data225, align 8
-  %528 = load %NODE_ADDITIVE_EXPRESSION_DATA, ptr %527, align 8
-  %exp226 = alloca %NODE_ADDITIVE_EXPRESSION_DATA, align 8
-  store %NODE_ADDITIVE_EXPRESSION_DATA %528, ptr %exp226, align 8
-  %529 = load ptr, ptr %c, align 8
-  %lhs227 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %exp226, i32 0, i32 1
-  %530 = load ptr, ptr %lhs227, align 8
-  %531 = call ptr @codegen_generate_expression_value(ptr %529, ptr %530, ptr null)
-  %lhs_value228 = alloca ptr, align 8
-  store ptr %531, ptr %lhs_value228, align 8
-  %532 = load ptr, ptr %lhs_value228, align 8
-  %533 = icmp ne ptr %532, null
-  call void @assert(i1 %533)
-  %534 = load ptr, ptr %c, align 8
-  %rhs229 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %exp226, i32 0, i32 2
-  %535 = load ptr, ptr %rhs229, align 8
-  %536 = call ptr @codegen_generate_expression_value(ptr %534, ptr %535, ptr null)
-  %rhs_value230 = alloca ptr, align 8
-  store ptr %536, ptr %rhs_value230, align 8
-  %537 = load ptr, ptr %rhs_value230, align 8
-  %538 = icmp ne ptr %537, null
-  call void @assert(i1 %538)
-  %539 = load ptr, ptr %c, align 8
-  %540 = load ptr, ptr %lhs_value228, align 8
-  %node_type231 = getelementptr %Variable, ptr %540, i32 0, i32 3
-  %541 = load ptr, ptr %node_type231, align 8
-  %542 = load ptr, ptr %rhs_value230, align 8
-  %node_type232 = getelementptr %Variable, ptr %542, i32 0, i32 3
-  %543 = load ptr, ptr %node_type232, align 8
-  %544 = call i1 @compare_types(ptr %539, ptr %541, ptr %543, i1 false)
-  call void @assert(i1 %544)
-  %result = alloca ptr, align 8
-  store ptr null, ptr %result, align 8
-  %node_type233 = alloca %Node, align 8
-  %type234 = getelementptr %Node, ptr %node_type233, i32 0, i32 0
-  %545 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
-  store i64 %545, ptr %type234, align 4
-  %546 = load ptr, ptr %c, align 8
-  %arena235 = getelementptr %codegen, ptr %546, i32 0, i32 3
-  %547 = load ptr, ptr %arena235, align 8
-  %548 = call ptr @arena_alloc(ptr %547, i64 16)
-  %d236 = alloca ptr, align 8
-  store ptr %548, ptr %d236, align 8
-  %549 = load ptr, ptr %d236, align 8
-  %name237 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %549, i32 0, i32 0
-  store ptr @211, ptr %name237, align 8
-  %550 = load ptr, ptr %d236, align 8
-  %underlying_type238 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %550, i32 0, i32 1
-  store ptr null, ptr %underlying_type238, align 8
-  %data239 = getelementptr %Node, ptr %node_type233, i32 0, i32 1
-  %551 = load ptr, ptr %d236, align 8
-  store ptr %551, ptr %data239, align 8
-  %552 = load ptr, ptr %c, align 8
-  %553 = load %Node, ptr %node_type233, align 8
-  %554 = call ptr @create_node(ptr %552, %Node %553)
+  %533 = load i64, ptr @LLVMIntSGE, align 4
+  store i64 %533, ptr %op, align 4
+  br label %merge_block225
+
+merge_block225:                                   ; preds = %merge_block222, %then_block224
+  %typ226 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp211, i32 0, i32 2
+  %534 = load i64, ptr %typ226, align 4
+  %535 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_LE, align 4
+  %536 = icmp eq i64 %534, %535
+  br i1 %536, label %then_block227, label %merge_block228
+
+then_block227:                                    ; preds = %merge_block225
+  %537 = load i64, ptr @LLVMIntSLE, align 4
+  store i64 %537, ptr %op, align 4
+  br label %merge_block228
+
+merge_block228:                                   ; preds = %merge_block225, %then_block227
+  %typ229 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp211, i32 0, i32 2
+  %538 = load i64, ptr %typ229, align 4
+  %539 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_LT, align 4
+  %540 = icmp eq i64 %538, %539
+  br i1 %540, label %then_block230, label %merge_block231
+
+then_block230:                                    ; preds = %merge_block228
+  %541 = load i64, ptr @LLVMIntSLT, align 4
+  store i64 %541, ptr %op, align 4
+  br label %merge_block231
+
+merge_block231:                                   ; preds = %merge_block228, %then_block230
+  %typ232 = getelementptr %NODE_EQUALITY_EXPRESSION_DATA, ptr %exp211, i32 0, i32 2
+  %542 = load i64, ptr %typ232, align 4
+  %543 = load i64, ptr @EQUALITY_EXPRESSION_TYPE_GT, align 4
+  %544 = icmp eq i64 %542, %543
+  br i1 %544, label %then_block233, label %merge_block234
+
+then_block233:                                    ; preds = %merge_block231
+  %545 = load i64, ptr @LLVMIntSGT, align 4
+  store i64 %545, ptr %op, align 4
+  br label %merge_block234
+
+merge_block234:                                   ; preds = %merge_block231, %then_block233
+  %546 = load i64, ptr %op, align 4
+  %547 = icmp ne i64 %546, -1
+  call void @assert(i1 %547)
+  %548 = load ptr, ptr %c, align 8
+  %builder235 = getelementptr %codegen, ptr %548, i32 0, i32 2
+  %549 = load ptr, ptr %builder235, align 8
+  %550 = load i64, ptr %op, align 4
+  %551 = load ptr, ptr %lhs_value213, align 8
+  %value236 = getelementptr %Variable, ptr %551, i32 0, i32 0
+  %552 = load ptr, ptr %value236, align 8
+  %553 = load ptr, ptr %rhs_value215, align 8
+  %value237 = getelementptr %Variable, ptr %553, i32 0, i32 0
+  %554 = load ptr, ptr %value237, align 8
+  %555 = call ptr @LLVMBuildICmp(ptr %549, i64 %550, ptr %552, ptr %554, ptr @211)
+  %cmp = alloca ptr, align 8
+  store ptr %555, ptr %cmp, align 8
+  %node_type238 = alloca %Node, align 8
+  %type239 = getelementptr %Node, ptr %node_type238, i32 0, i32 0
+  %556 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
+  store i64 %556, ptr %type239, align 4
+  %557 = load ptr, ptr %c, align 8
+  %arena240 = getelementptr %codegen, ptr %557, i32 0, i32 3
+  %558 = load ptr, ptr %arena240, align 8
+  %559 = call ptr @arena_alloc(ptr %558, i64 16)
+  %d241 = alloca ptr, align 8
+  store ptr %559, ptr %d241, align 8
+  %560 = load ptr, ptr %d241, align 8
+  %name242 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %560, i32 0, i32 0
+  store ptr @212, ptr %name242, align 8
+  %561 = load ptr, ptr %d241, align 8
+  %underlying_type243 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %561, i32 0, i32 1
+  store ptr null, ptr %underlying_type243, align 8
+  %data244 = getelementptr %Node, ptr %node_type238, i32 0, i32 1
+  %562 = load ptr, ptr %d241, align 8
+  store ptr %562, ptr %data244, align 8
+  %563 = load ptr, ptr %c, align 8
+  %564 = load ptr, ptr %cmp, align 8
+  %565 = load ptr, ptr %name, align 8
+  %566 = load ptr, ptr %expression, align 8
+  %567 = load ptr, ptr %c, align 8
+  %568 = load %Node, ptr %node_type238, align 8
+  %569 = call ptr @create_node(ptr %567, %Node %568)
+  %570 = call ptr @codegen_generate_literal(ptr %563, ptr %564, ptr %565, ptr %566, ptr %569)
+  ret ptr %570
+
+merge_block245:                                   ; preds = %merge_block207
+  %571 = load ptr, ptr %expression, align 8
+  %type246 = getelementptr %Node, ptr %571, i32 0, i32 0
+  %572 = load i64, ptr %type246, align 4
+  %573 = load i64, ptr @NODE_ADDITIVE_EXPRESSION, align 4
+  %574 = icmp eq i64 %572, %573
+  br i1 %574, label %then_block247, label %merge_block289
+
+then_block247:                                    ; preds = %merge_block245
+  %575 = load ptr, ptr %expression, align 8
+  %data248 = getelementptr %Node, ptr %575, i32 0, i32 1
+  %576 = load ptr, ptr %data248, align 8
+  %577 = load %NODE_ADDITIVE_EXPRESSION_DATA, ptr %576, align 8
+  %exp249 = alloca %NODE_ADDITIVE_EXPRESSION_DATA, align 8
+  store %NODE_ADDITIVE_EXPRESSION_DATA %577, ptr %exp249, align 8
+  %578 = load ptr, ptr %c, align 8
+  %lhs250 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %exp249, i32 0, i32 1
+  %579 = load ptr, ptr %lhs250, align 8
+  %580 = call ptr @codegen_generate_expression_value(ptr %578, ptr %579, ptr null)
+  %lhs_value251 = alloca ptr, align 8
+  store ptr %580, ptr %lhs_value251, align 8
+  %581 = load ptr, ptr %lhs_value251, align 8
+  %582 = icmp ne ptr %581, null
+  call void @assert(i1 %582)
+  %583 = load ptr, ptr %c, align 8
+  %rhs252 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %exp249, i32 0, i32 2
+  %584 = load ptr, ptr %rhs252, align 8
+  %585 = call ptr @codegen_generate_expression_value(ptr %583, ptr %584, ptr null)
+  %rhs_value253 = alloca ptr, align 8
+  store ptr %585, ptr %rhs_value253, align 8
+  %586 = load ptr, ptr %rhs_value253, align 8
+  %587 = icmp ne ptr %586, null
+  call void @assert(i1 %587)
+  %588 = load ptr, ptr %c, align 8
+  %589 = load ptr, ptr %lhs_value251, align 8
+  %node_type254 = getelementptr %Variable, ptr %589, i32 0, i32 3
+  %590 = load ptr, ptr %node_type254, align 8
+  %591 = load ptr, ptr %rhs_value253, align 8
+  %node_type255 = getelementptr %Variable, ptr %591, i32 0, i32 3
+  %592 = load ptr, ptr %node_type255, align 8
+  %593 = call i1 @compare_types(ptr %588, ptr %590, ptr %592, i1 false)
+  call void @assert(i1 %593)
+  %result256 = alloca ptr, align 8
+  store ptr null, ptr %result256, align 8
+  %node_type257 = alloca %Node, align 8
+  %type258 = getelementptr %Node, ptr %node_type257, i32 0, i32 0
+  %594 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
+  store i64 %594, ptr %type258, align 4
+  %595 = load ptr, ptr %c, align 8
+  %arena259 = getelementptr %codegen, ptr %595, i32 0, i32 3
+  %596 = load ptr, ptr %arena259, align 8
+  %597 = call ptr @arena_alloc(ptr %596, i64 16)
+  %d260 = alloca ptr, align 8
+  store ptr %597, ptr %d260, align 8
+  %598 = load ptr, ptr %d260, align 8
+  %name261 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %598, i32 0, i32 0
+  store ptr @213, ptr %name261, align 8
+  %599 = load ptr, ptr %d260, align 8
+  %underlying_type262 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %599, i32 0, i32 1
+  store ptr null, ptr %underlying_type262, align 8
+  %data263 = getelementptr %Node, ptr %node_type257, i32 0, i32 1
+  %600 = load ptr, ptr %d260, align 8
+  store ptr %600, ptr %data263, align 8
+  %601 = load ptr, ptr %c, align 8
+  %602 = load %Node, ptr %node_type257, align 8
+  %603 = call ptr @create_node(ptr %601, %Node %602)
   %pnode_type = alloca ptr, align 8
-  store ptr %554, ptr %pnode_type, align 8
-  %addition = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %exp226, i32 0, i32 0
-  %555 = load i1, ptr %addition, align 1
-  br i1 %555, label %then_block240, label %merge_block258
-
-then_block240:                                    ; preds = %then_block224
-  %556 = load ptr, ptr %lhs_value228, align 8
-  %node_type241 = getelementptr %Variable, ptr %556, i32 0, i32 3
-  %557 = load ptr, ptr %node_type241, align 8
+  store ptr %603, ptr %pnode_type, align 8
+  %addition = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %exp249, i32 0, i32 0
+  %604 = load i1, ptr %addition, align 1
+  br i1 %604, label %then_block264, label %merge_block282
+
+then_block264:                                    ; preds = %then_block247
+  %605 = load ptr, ptr %lhs_value251, align 8
+  %node_type265 = getelementptr %Variable, ptr %605, i32 0, i32 3
+  %606 = load ptr, ptr %node_type265, align 8
   %nt = alloca ptr, align 8
-  store ptr %557, ptr %nt, align 8
-  %558 = load ptr, ptr %nt, align 8
-  %type242 = getelementptr %Node, ptr %558, i32 0, i32 0
-  %559 = load i64, ptr %type242, align 4
-  %560 = load i64, ptr @NODE_TYPE_POINTER_TYPE, align 4
-  %561 = icmp eq i64 %559, %560
-  br i1 %561, label %then_block243, label %merge_block251
-
-then_block243:                                    ; preds = %then_block240
-  %562 = load ptr, ptr %nt, align 8
-  %data244 = getelementptr %Node, ptr %562, i32 0, i32 1
-  %563 = load ptr, ptr %data244, align 8
+  store ptr %606, ptr %nt, align 8
+  %607 = load ptr, ptr %nt, align 8
+  %type266 = getelementptr %Node, ptr %607, i32 0, i32 0
+  %608 = load i64, ptr %type266, align 4
+  %609 = load i64, ptr @NODE_TYPE_POINTER_TYPE, align 4
+  %610 = icmp eq i64 %608, %609
+  br i1 %610, label %then_block267, label %merge_block275
+
+then_block267:                                    ; preds = %then_block264
+  %611 = load ptr, ptr %nt, align 8
+  %data268 = getelementptr %Node, ptr %611, i32 0, i32 1
+  %612 = load ptr, ptr %data268, align 8
   %ipt = alloca ptr, align 8
-  store ptr %563, ptr %ipt, align 8
-  %564 = load ptr, ptr %c, align 8
-  %565 = load ptr, ptr %ipt, align 8
-  %type245 = getelementptr %NODE_TYPE_POINTER_TYPE_DATA, ptr %565, i32 0, i32 0
-  %566 = load ptr, ptr %type245, align 8
-  %567 = call ptr @codegen_get_llvm_type(ptr %564, ptr %566)
+  store ptr %612, ptr %ipt, align 8
+  %613 = load ptr, ptr %c, align 8
+  %614 = load ptr, ptr %ipt, align 8
+  %type269 = getelementptr %NODE_TYPE_POINTER_TYPE_DATA, ptr %614, i32 0, i32 0
+  %615 = load ptr, ptr %type269, align 8
+  %616 = call ptr @codegen_get_llvm_type(ptr %613, ptr %615)
   %llvmipt = alloca ptr, align 8
-  store ptr %567, ptr %llvmipt, align 8
-  %568 = load ptr, ptr %llvmipt, align 8
-  %569 = icmp ne ptr %568, null
-  call void @assert(i1 %569)
-  %570 = load ptr, ptr %c, align 8
-  %arena246 = getelementptr %codegen, ptr %570, i32 0, i32 3
-  %571 = load ptr, ptr %arena246, align 8
-  %572 = call ptr @arena_alloc(ptr %571, i64 8)
+  store ptr %616, ptr %llvmipt, align 8
+  %617 = load ptr, ptr %llvmipt, align 8
+  %618 = icmp ne ptr %617, null
+  call void @assert(i1 %618)
+  %619 = load ptr, ptr %c, align 8
+  %arena270 = getelementptr %codegen, ptr %619, i32 0, i32 3
+  %620 = load ptr, ptr %arena270, align 8
+  %621 = call ptr @arena_alloc(ptr %620, i64 8)
   %arr = alloca ptr, align 8
-  store ptr %572, ptr %arr, align 8
-  %573 = load ptr, ptr %arr, align 8
-  %574 = getelementptr ptr, ptr %573, i64 0
-  %575 = load ptr, ptr %rhs_value230, align 8
-  %value247 = getelementptr %Variable, ptr %575, i32 0, i32 0
-  %576 = load ptr, ptr %value247, align 8
-  store ptr %576, ptr %574, align 8
-  %577 = load ptr, ptr %c, align 8
-  %builder248 = getelementptr %codegen, ptr %577, i32 0, i32 2
-  %578 = load ptr, ptr %builder248, align 8
-  %579 = load ptr, ptr %llvmipt, align 8
-  %580 = load ptr, ptr %579, align 8
-  %581 = load ptr, ptr %lhs_value228, align 8
-  %value249 = getelementptr %Variable, ptr %581, i32 0, i32 0
-  %582 = load ptr, ptr %value249, align 8
-  %583 = load ptr, ptr %arr, align 8
-  %584 = call ptr @LLVMBuildGEP2(ptr %578, ptr %580, ptr %582, ptr %583, i64 1, ptr @212)
-  store ptr %584, ptr %result, align 8
-  %585 = load ptr, ptr %lhs_value228, align 8
-  %node_type250 = getelementptr %Variable, ptr %585, i32 0, i32 3
-  %586 = load ptr, ptr %node_type250, align 8
-  store ptr %586, ptr %pnode_type, align 8
-  br label %merge_block251
-
-merge_block251:                                   ; preds = %then_block240, %then_block243
-  %587 = load ptr, ptr %nt, align 8
-  %type252 = getelementptr %Node, ptr %587, i32 0, i32 0
-  %588 = load i64, ptr %type252, align 4
-  %589 = load i64, ptr @NODE_TYPE_POINTER_TYPE, align 4
-  %590 = icmp ne i64 %588, %589
-  br i1 %590, label %then_block253, label %merge_block257
-
-then_block253:                                    ; preds = %merge_block251
-  %591 = load ptr, ptr %c, align 8
-  %builder254 = getelementptr %codegen, ptr %591, i32 0, i32 2
-  %592 = load ptr, ptr %builder254, align 8
-  %593 = load ptr, ptr %lhs_value228, align 8
-  %value255 = getelementptr %Variable, ptr %593, i32 0, i32 0
-  %594 = load ptr, ptr %value255, align 8
-  %595 = load ptr, ptr %rhs_value230, align 8
-  %value256 = getelementptr %Variable, ptr %595, i32 0, i32 0
-  %596 = load ptr, ptr %value256, align 8
-  %597 = call ptr @LLVMBuildAdd(ptr %592, ptr %594, ptr %596, ptr @213)
-  store ptr %597, ptr %result, align 8
-  br label %merge_block257
-
-merge_block257:                                   ; preds = %merge_block251, %then_block253
-  br label %merge_block258
-
-merge_block258:                                   ; preds = %then_block224, %merge_block257
-  %addition259 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %exp226, i32 0, i32 0
-  %598 = load i1, ptr %addition259, align 1
-  %599 = icmp eq i1 %598, false
-  br i1 %599, label %then_block260, label %merge_block264
-
-then_block260:                                    ; preds = %merge_block258
-  %600 = load ptr, ptr %c, align 8
-  %builder261 = getelementptr %codegen, ptr %600, i32 0, i32 2
-  %601 = load ptr, ptr %builder261, align 8
-  %602 = load ptr, ptr %lhs_value228, align 8
-  %value262 = getelementptr %Variable, ptr %602, i32 0, i32 0
-  %603 = load ptr, ptr %value262, align 8
-  %604 = load ptr, ptr %rhs_value230, align 8
-  %value263 = getelementptr %Variable, ptr %604, i32 0, i32 0
-  %605 = load ptr, ptr %value263, align 8
-  %606 = call ptr @LLVMBuildSub(ptr %601, ptr %603, ptr %605, ptr @214)
-  store ptr %606, ptr %result, align 8
-  br label %merge_block264
-
-merge_block264:                                   ; preds = %merge_block258, %then_block260
-  %607 = load ptr, ptr %c, align 8
-  %608 = load ptr, ptr %result, align 8
-  %609 = load ptr, ptr %name, align 8
-  %610 = load ptr, ptr %expression, align 8
-  %611 = load ptr, ptr %pnode_type, align 8
-  %612 = call ptr @codegen_generate_literal(ptr %607, ptr %608, ptr %609, ptr %610, ptr %611)
-  ret ptr %612
-
-merge_block265:                                   ; preds = %merge_block222
-  %613 = load ptr, ptr %expression, align 8
-  %type266 = getelementptr %Node, ptr %613, i32 0, i32 0
-  %614 = load i64, ptr %type266, align 4
-  %615 = load i64, ptr @NODE_MULTIPLICATIVE_EXPRESSION, align 4
-  %616 = icmp eq i64 %614, %615
-  br i1 %616, label %then_block267, label %merge_block296
-
-then_block267:                                    ; preds = %merge_block265
-  %617 = load ptr, ptr %expression, align 8
-  %data268 = getelementptr %Node, ptr %617, i32 0, i32 1
-  %618 = load ptr, ptr %data268, align 8
-  %619 = load %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %618, align 8
-  %exp269 = alloca %NODE_MULTIPLICATIVE_EXPRESSION_DATA, align 8
-  store %NODE_MULTIPLICATIVE_EXPRESSION_DATA %619, ptr %exp269, align 8
-  %620 = load ptr, ptr %c, align 8
-  %lhs270 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp269, i32 0, i32 0
-  %621 = load ptr, ptr %lhs270, align 8
-  %622 = call ptr @codegen_generate_expression_value(ptr %620, ptr %621, ptr null)
-  %lhs_value271 = alloca ptr, align 8
-  store ptr %622, ptr %lhs_value271, align 8
-  %623 = load ptr, ptr %lhs_value271, align 8
-  %624 = icmp ne ptr %623, null
-  call void @assert(i1 %624)
-  %625 = load ptr, ptr %c, align 8
-  %rhs272 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp269, i32 0, i32 1
-  %626 = load ptr, ptr %rhs272, align 8
-  %627 = call ptr @codegen_generate_expression_value(ptr %625, ptr %626, ptr null)
-  %rhs_value273 = alloca ptr, align 8
-  store ptr %627, ptr %rhs_value273, align 8
-  %628 = load ptr, ptr %rhs_value273, align 8
-  %629 = icmp ne ptr %628, null
-  call void @assert(i1 %629)
-  %630 = load ptr, ptr %c, align 8
-  %631 = load ptr, ptr %lhs_value271, align 8
-  %node_type274 = getelementptr %Variable, ptr %631, i32 0, i32 3
-  %632 = load ptr, ptr %node_type274, align 8
-  %633 = load ptr, ptr %rhs_value273, align 8
-  %node_type275 = getelementptr %Variable, ptr %633, i32 0, i32 3
-  %634 = load ptr, ptr %node_type275, align 8
-  %635 = call i1 @compare_types(ptr %630, ptr %632, ptr %634, i1 false)
-  call void @assert(i1 %635)
-  %result276 = alloca ptr, align 8
-  store ptr null, ptr %result276, align 8
-  %typ277 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp269, i32 0, i32 2
-  %636 = load i64, ptr %typ277, align 4
-  %637 = load i64, ptr @MULTIPLICATIVE_EXPRESSION_TYPE_MUL, align 4
-  %638 = icmp eq i64 %636, %637
-  br i1 %638, label %then_block278, label %merge_block282
-
-then_block278:                                    ; preds = %then_block267
-  %639 = load ptr, ptr %c, align 8
-  %builder279 = getelementptr %codegen, ptr %639, i32 0, i32 2
-  %640 = load ptr, ptr %builder279, align 8
-  %641 = load ptr, ptr %lhs_value271, align 8
-  %value280 = getelementptr %Variable, ptr %641, i32 0, i32 0
-  %642 = load ptr, ptr %value280, align 8
-  %643 = load ptr, ptr %rhs_value273, align 8
-  %value281 = getelementptr %Variable, ptr %643, i32 0, i32 0
-  %644 = load ptr, ptr %value281, align 8
-  %645 = call ptr @LLVMBuildMul(ptr %640, ptr %642, ptr %644, ptr @215)
-  store ptr %645, ptr %result276, align 8
+  store ptr %621, ptr %arr, align 8
+  %622 = load ptr, ptr %arr, align 8
+  %623 = getelementptr ptr, ptr %622, i64 0
+  %624 = load ptr, ptr %rhs_value253, align 8
+  %value271 = getelementptr %Variable, ptr %624, i32 0, i32 0
+  %625 = load ptr, ptr %value271, align 8
+  store ptr %625, ptr %623, align 8
+  %626 = load ptr, ptr %c, align 8
+  %builder272 = getelementptr %codegen, ptr %626, i32 0, i32 2
+  %627 = load ptr, ptr %builder272, align 8
+  %628 = load ptr, ptr %llvmipt, align 8
+  %629 = load ptr, ptr %628, align 8
+  %630 = load ptr, ptr %lhs_value251, align 8
+  %value273 = getelementptr %Variable, ptr %630, i32 0, i32 0
+  %631 = load ptr, ptr %value273, align 8
+  %632 = load ptr, ptr %arr, align 8
+  %633 = call ptr @LLVMBuildGEP2(ptr %627, ptr %629, ptr %631, ptr %632, i64 1, ptr @214)
+  store ptr %633, ptr %result256, align 8
+  %634 = load ptr, ptr %lhs_value251, align 8
+  %node_type274 = getelementptr %Variable, ptr %634, i32 0, i32 3
+  %635 = load ptr, ptr %node_type274, align 8
+  store ptr %635, ptr %pnode_type, align 8
+  br label %merge_block275
+
+merge_block275:                                   ; preds = %then_block264, %then_block267
+  %636 = load ptr, ptr %nt, align 8
+  %type276 = getelementptr %Node, ptr %636, i32 0, i32 0
+  %637 = load i64, ptr %type276, align 4
+  %638 = load i64, ptr @NODE_TYPE_POINTER_TYPE, align 4
+  %639 = icmp ne i64 %637, %638
+  br i1 %639, label %then_block277, label %merge_block281
+
+then_block277:                                    ; preds = %merge_block275
+  %640 = load ptr, ptr %c, align 8
+  %builder278 = getelementptr %codegen, ptr %640, i32 0, i32 2
+  %641 = load ptr, ptr %builder278, align 8
+  %642 = load ptr, ptr %lhs_value251, align 8
+  %value279 = getelementptr %Variable, ptr %642, i32 0, i32 0
+  %643 = load ptr, ptr %value279, align 8
+  %644 = load ptr, ptr %rhs_value253, align 8
+  %value280 = getelementptr %Variable, ptr %644, i32 0, i32 0
+  %645 = load ptr, ptr %value280, align 8
+  %646 = call ptr @LLVMBuildAdd(ptr %641, ptr %643, ptr %645, ptr @215)
+  store ptr %646, ptr %result256, align 8
+  br label %merge_block281
+
+merge_block281:                                   ; preds = %merge_block275, %then_block277
   br label %merge_block282
 
-merge_block282:                                   ; preds = %then_block267, %then_block278
-  %typ283 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp269, i32 0, i32 2
-  %646 = load i64, ptr %typ283, align 4
-  %647 = load i64, ptr @MULTIPLICATIVE_EXPRESSION_TYPE_DIV, align 4
-  %648 = icmp eq i64 %646, %647
+merge_block282:                                   ; preds = %then_block247, %merge_block281
+  %addition283 = getelementptr %NODE_ADDITIVE_EXPRESSION_DATA, ptr %exp249, i32 0, i32 0
+  %647 = load i1, ptr %addition283, align 1
+  %648 = icmp eq i1 %647, false
   br i1 %648, label %then_block284, label %merge_block288
 
 then_block284:                                    ; preds = %merge_block282
   %649 = load ptr, ptr %c, align 8
   %builder285 = getelementptr %codegen, ptr %649, i32 0, i32 2
   %650 = load ptr, ptr %builder285, align 8
-  %651 = load ptr, ptr %lhs_value271, align 8
+  %651 = load ptr, ptr %lhs_value251, align 8
   %value286 = getelementptr %Variable, ptr %651, i32 0, i32 0
   %652 = load ptr, ptr %value286, align 8
-  %653 = load ptr, ptr %rhs_value273, align 8
+  %653 = load ptr, ptr %rhs_value253, align 8
   %value287 = getelementptr %Variable, ptr %653, i32 0, i32 0
   %654 = load ptr, ptr %value287, align 8
-  %655 = call ptr @LLVMBuildSDiv(ptr %650, ptr %652, ptr %654, ptr @216)
-  store ptr %655, ptr %result276, align 8
+  %655 = call ptr @LLVMBuildSub(ptr %650, ptr %652, ptr %654, ptr @216)
+  store ptr %655, ptr %result256, align 8
   br label %merge_block288
 
 merge_block288:                                   ; preds = %merge_block282, %then_block284
-  %typ289 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp269, i32 0, i32 2
-  %656 = load i64, ptr %typ289, align 4
-  %657 = load i64, ptr @MULTIPLICATIVE_EXPRESSION_TYPE_MOD, align 4
-  %658 = icmp eq i64 %656, %657
-  br i1 %658, label %then_block290, label %merge_block294
-
-then_block290:                                    ; preds = %merge_block288
-  %659 = load ptr, ptr %c, align 8
-  %builder291 = getelementptr %codegen, ptr %659, i32 0, i32 2
-  %660 = load ptr, ptr %builder291, align 8
-  %661 = load ptr, ptr %lhs_value271, align 8
-  %value292 = getelementptr %Variable, ptr %661, i32 0, i32 0
-  %662 = load ptr, ptr %value292, align 8
-  %663 = load ptr, ptr %rhs_value273, align 8
-  %value293 = getelementptr %Variable, ptr %663, i32 0, i32 0
-  %664 = load ptr, ptr %value293, align 8
-  %665 = call ptr @LLVMBuildSRem(ptr %660, ptr %662, ptr %664, ptr @217)
-  store ptr %665, ptr %result276, align 8
-  br label %merge_block294
-
-merge_block294:                                   ; preds = %merge_block288, %then_block290
-  %666 = load ptr, ptr %result276, align 8
-  %667 = icmp ne ptr %666, null
-  call void @assert(i1 %667)
-  %668 = load ptr, ptr %c, align 8
-  %669 = load ptr, ptr %result276, align 8
-  %670 = load ptr, ptr %name, align 8
-  %671 = load ptr, ptr %expression, align 8
-  %672 = load ptr, ptr %lhs_value271, align 8
-  %node_type295 = getelementptr %Variable, ptr %672, i32 0, i32 3
-  %673 = load ptr, ptr %node_type295, align 8
-  %674 = call ptr @codegen_generate_literal(ptr %668, ptr %669, ptr %670, ptr %671, ptr %673)
-  ret ptr %674
-
-merge_block296:                                   ; preds = %merge_block265
-  %675 = load ptr, ptr %expression, align 8
-  %type297 = getelementptr %Node, ptr %675, i32 0, i32 0
-  %676 = load i64, ptr %type297, align 4
-  %677 = load i64, ptr @NODE_UNARY_EXPRESSION, align 4
-  %678 = icmp eq i64 %676, %677
-  br i1 %678, label %then_block298, label %merge_block342
-
-then_block298:                                    ; preds = %merge_block296
-  %679 = load ptr, ptr %expression, align 8
-  %data299 = getelementptr %Node, ptr %679, i32 0, i32 1
-  %680 = load ptr, ptr %data299, align 8
-  %681 = load %NODE_UNARY_EXPRESSION_DATA, ptr %680, align 8
-  %exp300 = alloca %NODE_UNARY_EXPRESSION_DATA, align 8
-  store %NODE_UNARY_EXPRESSION_DATA %681, ptr %exp300, align 8
-  %682 = load ptr, ptr %c, align 8
-  %expression301 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %exp300, i32 0, i32 1
-  %683 = load ptr, ptr %expression301, align 8
-  %684 = call ptr @codegen_generate_expression_value(ptr %682, ptr %683, ptr null)
+  %656 = load ptr, ptr %c, align 8
+  %657 = load ptr, ptr %result256, align 8
+  %658 = load ptr, ptr %name, align 8
+  %659 = load ptr, ptr %expression, align 8
+  %660 = load ptr, ptr %pnode_type, align 8
+  %661 = call ptr @codegen_generate_literal(ptr %656, ptr %657, ptr %658, ptr %659, ptr %660)
+  ret ptr %661
+
+merge_block289:                                   ; preds = %merge_block245
+  %662 = load ptr, ptr %expression, align 8
+  %type290 = getelementptr %Node, ptr %662, i32 0, i32 0
+  %663 = load i64, ptr %type290, align 4
+  %664 = load i64, ptr @NODE_MULTIPLICATIVE_EXPRESSION, align 4
+  %665 = icmp eq i64 %663, %664
+  br i1 %665, label %then_block291, label %merge_block320
+
+then_block291:                                    ; preds = %merge_block289
+  %666 = load ptr, ptr %expression, align 8
+  %data292 = getelementptr %Node, ptr %666, i32 0, i32 1
+  %667 = load ptr, ptr %data292, align 8
+  %668 = load %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %667, align 8
+  %exp293 = alloca %NODE_MULTIPLICATIVE_EXPRESSION_DATA, align 8
+  store %NODE_MULTIPLICATIVE_EXPRESSION_DATA %668, ptr %exp293, align 8
+  %669 = load ptr, ptr %c, align 8
+  %lhs294 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp293, i32 0, i32 0
+  %670 = load ptr, ptr %lhs294, align 8
+  %671 = call ptr @codegen_generate_expression_value(ptr %669, ptr %670, ptr null)
+  %lhs_value295 = alloca ptr, align 8
+  store ptr %671, ptr %lhs_value295, align 8
+  %672 = load ptr, ptr %lhs_value295, align 8
+  %673 = icmp ne ptr %672, null
+  call void @assert(i1 %673)
+  %674 = load ptr, ptr %c, align 8
+  %rhs296 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp293, i32 0, i32 1
+  %675 = load ptr, ptr %rhs296, align 8
+  %676 = call ptr @codegen_generate_expression_value(ptr %674, ptr %675, ptr null)
+  %rhs_value297 = alloca ptr, align 8
+  store ptr %676, ptr %rhs_value297, align 8
+  %677 = load ptr, ptr %rhs_value297, align 8
+  %678 = icmp ne ptr %677, null
+  call void @assert(i1 %678)
+  %679 = load ptr, ptr %c, align 8
+  %680 = load ptr, ptr %lhs_value295, align 8
+  %node_type298 = getelementptr %Variable, ptr %680, i32 0, i32 3
+  %681 = load ptr, ptr %node_type298, align 8
+  %682 = load ptr, ptr %rhs_value297, align 8
+  %node_type299 = getelementptr %Variable, ptr %682, i32 0, i32 3
+  %683 = load ptr, ptr %node_type299, align 8
+  %684 = call i1 @compare_types(ptr %679, ptr %681, ptr %683, i1 false)
+  call void @assert(i1 %684)
+  %result300 = alloca ptr, align 8
+  store ptr null, ptr %result300, align 8
+  %typ301 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp293, i32 0, i32 2
+  %685 = load i64, ptr %typ301, align 4
+  %686 = load i64, ptr @MULTIPLICATIVE_EXPRESSION_TYPE_MUL, align 4
+  %687 = icmp eq i64 %685, %686
+  br i1 %687, label %then_block302, label %merge_block306
+
+then_block302:                                    ; preds = %then_block291
+  %688 = load ptr, ptr %c, align 8
+  %builder303 = getelementptr %codegen, ptr %688, i32 0, i32 2
+  %689 = load ptr, ptr %builder303, align 8
+  %690 = load ptr, ptr %lhs_value295, align 8
+  %value304 = getelementptr %Variable, ptr %690, i32 0, i32 0
+  %691 = load ptr, ptr %value304, align 8
+  %692 = load ptr, ptr %rhs_value297, align 8
+  %value305 = getelementptr %Variable, ptr %692, i32 0, i32 0
+  %693 = load ptr, ptr %value305, align 8
+  %694 = call ptr @LLVMBuildMul(ptr %689, ptr %691, ptr %693, ptr @217)
+  store ptr %694, ptr %result300, align 8
+  br label %merge_block306
+
+merge_block306:                                   ; preds = %then_block291, %then_block302
+  %typ307 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp293, i32 0, i32 2
+  %695 = load i64, ptr %typ307, align 4
+  %696 = load i64, ptr @MULTIPLICATIVE_EXPRESSION_TYPE_DIV, align 4
+  %697 = icmp eq i64 %695, %696
+  br i1 %697, label %then_block308, label %merge_block312
+
+then_block308:                                    ; preds = %merge_block306
+  %698 = load ptr, ptr %c, align 8
+  %builder309 = getelementptr %codegen, ptr %698, i32 0, i32 2
+  %699 = load ptr, ptr %builder309, align 8
+  %700 = load ptr, ptr %lhs_value295, align 8
+  %value310 = getelementptr %Variable, ptr %700, i32 0, i32 0
+  %701 = load ptr, ptr %value310, align 8
+  %702 = load ptr, ptr %rhs_value297, align 8
+  %value311 = getelementptr %Variable, ptr %702, i32 0, i32 0
+  %703 = load ptr, ptr %value311, align 8
+  %704 = call ptr @LLVMBuildSDiv(ptr %699, ptr %701, ptr %703, ptr @218)
+  store ptr %704, ptr %result300, align 8
+  br label %merge_block312
+
+merge_block312:                                   ; preds = %merge_block306, %then_block308
+  %typ313 = getelementptr %NODE_MULTIPLICATIVE_EXPRESSION_DATA, ptr %exp293, i32 0, i32 2
+  %705 = load i64, ptr %typ313, align 4
+  %706 = load i64, ptr @MULTIPLICATIVE_EXPRESSION_TYPE_MOD, align 4
+  %707 = icmp eq i64 %705, %706
+  br i1 %707, label %then_block314, label %merge_block318
+
+then_block314:                                    ; preds = %merge_block312
+  %708 = load ptr, ptr %c, align 8
+  %builder315 = getelementptr %codegen, ptr %708, i32 0, i32 2
+  %709 = load ptr, ptr %builder315, align 8
+  %710 = load ptr, ptr %lhs_value295, align 8
+  %value316 = getelementptr %Variable, ptr %710, i32 0, i32 0
+  %711 = load ptr, ptr %value316, align 8
+  %712 = load ptr, ptr %rhs_value297, align 8
+  %value317 = getelementptr %Variable, ptr %712, i32 0, i32 0
+  %713 = load ptr, ptr %value317, align 8
+  %714 = call ptr @LLVMBuildSRem(ptr %709, ptr %711, ptr %713, ptr @219)
+  store ptr %714, ptr %result300, align 8
+  br label %merge_block318
+
+merge_block318:                                   ; preds = %merge_block312, %then_block314
+  %715 = load ptr, ptr %result300, align 8
+  %716 = icmp ne ptr %715, null
+  call void @assert(i1 %716)
+  %717 = load ptr, ptr %c, align 8
+  %718 = load ptr, ptr %result300, align 8
+  %719 = load ptr, ptr %name, align 8
+  %720 = load ptr, ptr %expression, align 8
+  %721 = load ptr, ptr %lhs_value295, align 8
+  %node_type319 = getelementptr %Variable, ptr %721, i32 0, i32 3
+  %722 = load ptr, ptr %node_type319, align 8
+  %723 = call ptr @codegen_generate_literal(ptr %717, ptr %718, ptr %719, ptr %720, ptr %722)
+  ret ptr %723
+
+merge_block320:                                   ; preds = %merge_block289
+  %724 = load ptr, ptr %expression, align 8
+  %type321 = getelementptr %Node, ptr %724, i32 0, i32 0
+  %725 = load i64, ptr %type321, align 4
+  %726 = load i64, ptr @NODE_UNARY_EXPRESSION, align 4
+  %727 = icmp eq i64 %725, %726
+  br i1 %727, label %then_block322, label %merge_block366
+
+then_block322:                                    ; preds = %merge_block320
+  %728 = load ptr, ptr %expression, align 8
+  %data323 = getelementptr %Node, ptr %728, i32 0, i32 1
+  %729 = load ptr, ptr %data323, align 8
+  %730 = load %NODE_UNARY_EXPRESSION_DATA, ptr %729, align 8
+  %exp324 = alloca %NODE_UNARY_EXPRESSION_DATA, align 8
+  store %NODE_UNARY_EXPRESSION_DATA %730, ptr %exp324, align 8
+  %731 = load ptr, ptr %c, align 8
+  %expression325 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %exp324, i32 0, i32 1
+  %732 = load ptr, ptr %expression325, align 8
+  %733 = call ptr @codegen_generate_expression_value(ptr %731, ptr %732, ptr null)
   %k = alloca ptr, align 8
-  store ptr %684, ptr %k, align 8
-  %685 = load ptr, ptr %k, align 8
-  %686 = icmp ne ptr %685, null
-  call void @assert(i1 %686)
+  store ptr %733, ptr %k, align 8
+  %734 = load ptr, ptr %k, align 8
+  %735 = icmp ne ptr %734, null
+  call void @assert(i1 %735)
   %r = alloca ptr, align 8
   store ptr null, ptr %r, align 8
-  %687 = load ptr, ptr %k, align 8
-  %node_type302 = getelementptr %Variable, ptr %687, i32 0, i32 3
-  %688 = load ptr, ptr %node_type302, align 8
-  %typ303 = alloca ptr, align 8
-  store ptr %688, ptr %typ303, align 8
-  %typ304 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %exp300, i32 0, i32 0
-  %689 = load i64, ptr %typ304, align 4
-  %690 = load i64, ptr @UNARY_EXPRESSION_TYPE_NOT, align 4
-  %691 = icmp eq i64 %689, %690
-  br i1 %691, label %then_block305, label %merge_block319
-
-then_block305:                                    ; preds = %then_block298
-  %692 = load ptr, ptr %typ303, align 8
-  %type306 = getelementptr %Node, ptr %692, i32 0, i32 0
-  %693 = load i64, ptr %type306, align 4
-  %694 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
-  %695 = icmp eq i64 %693, %694
-  call void @assert(i1 %695)
-  %696 = load ptr, ptr %typ303, align 8
-  %data307 = getelementptr %Node, ptr %696, i32 0, i32 1
-  %697 = load ptr, ptr %data307, align 8
-  %698 = load %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %697, align 8
-  %simple_type308 = alloca %NODE_TYPE_SIMPLE_TYPE_DATA, align 8
-  store %NODE_TYPE_SIMPLE_TYPE_DATA %698, ptr %simple_type308, align 8
-  %name309 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %simple_type308, i32 0, i32 0
-  %699 = load ptr, ptr %name309, align 8
-  %700 = call i1 @strcmp(ptr %699, ptr @218)
-  call void @assert(i1 %700)
-  %701 = load ptr, ptr %c, align 8
-  %builder310 = getelementptr %codegen, ptr %701, i32 0, i32 2
-  %702 = load ptr, ptr %builder310, align 8
-  %703 = load i64, ptr @LLVMIntEQ, align 4
-  %704 = load ptr, ptr %k, align 8
-  %value311 = getelementptr %Variable, ptr %704, i32 0, i32 0
-  %705 = load ptr, ptr %value311, align 8
-  %706 = call ptr @LLVMInt1Type()
-  %707 = call ptr @LLVMConstInt(ptr %706, i64 0, i64 0)
-  %708 = call ptr @LLVMBuildICmp(ptr %702, i64 %703, ptr %705, ptr %707, ptr @219)
-  store ptr %708, ptr %r, align 8
-  %node_type312 = alloca %Node, align 8
-  %type313 = getelementptr %Node, ptr %node_type312, i32 0, i32 0
-  %709 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
-  store i64 %709, ptr %type313, align 4
-  %710 = load ptr, ptr %c, align 8
-  %arena314 = getelementptr %codegen, ptr %710, i32 0, i32 3
-  %711 = load ptr, ptr %arena314, align 8
-  %712 = call ptr @arena_alloc(ptr %711, i64 16)
-  %d315 = alloca ptr, align 8
-  store ptr %712, ptr %d315, align 8
-  %713 = load ptr, ptr %d315, align 8
-  %name316 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %713, i32 0, i32 0
-  store ptr @220, ptr %name316, align 8
-  %714 = load ptr, ptr %d315, align 8
-  %underlying_type317 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %714, i32 0, i32 1
-  store ptr null, ptr %underlying_type317, align 8
-  %data318 = getelementptr %Node, ptr %node_type312, i32 0, i32 1
-  %715 = load ptr, ptr %d315, align 8
-  store ptr %715, ptr %data318, align 8
-  %716 = load ptr, ptr %c, align 8
-  %717 = load %Node, ptr %node_type312, align 8
-  %718 = call ptr @create_node(ptr %716, %Node %717)
-  store ptr %718, ptr %typ303, align 8
-  br label %merge_block319
-
-merge_block319:                                   ; preds = %then_block298, %then_block305
-  %typ320 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %exp300, i32 0, i32 0
-  %719 = load i64, ptr %typ320, align 4
-  %720 = load i64, ptr @UNARY_EXPRESSION_TYPE_MINUS, align 4
-  %721 = icmp eq i64 %719, %720
-  br i1 %721, label %then_block321, label %merge_block331
-
-then_block321:                                    ; preds = %merge_block319
-  %722 = load ptr, ptr %c, align 8
-  %builder322 = getelementptr %codegen, ptr %722, i32 0, i32 2
-  %723 = load ptr, ptr %builder322, align 8
-  %724 = load ptr, ptr %k, align 8
-  %value323 = getelementptr %Variable, ptr %724, i32 0, i32 0
-  %725 = load ptr, ptr %value323, align 8
-  %726 = call ptr @LLVMBuildNeg(ptr %723, ptr %725, ptr @221)
-  store ptr %726, ptr %r, align 8
-  %node_type324 = alloca %Node, align 8
-  %type325 = getelementptr %Node, ptr %node_type324, i32 0, i32 0
-  %727 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
-  store i64 %727, ptr %type325, align 4
-  %728 = load ptr, ptr %c, align 8
-  %arena326 = getelementptr %codegen, ptr %728, i32 0, i32 3
-  %729 = load ptr, ptr %arena326, align 8
-  %730 = call ptr @arena_alloc(ptr %729, i64 16)
-  %d327 = alloca ptr, align 8
-  store ptr %730, ptr %d327, align 8
-  %731 = load ptr, ptr %d327, align 8
-  %name328 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %731, i32 0, i32 0
-  store ptr @222, ptr %name328, align 8
-  %732 = load ptr, ptr %d327, align 8
-  %underlying_type329 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %732, i32 0, i32 1
-  store ptr null, ptr %underlying_type329, align 8
-  %data330 = getelementptr %Node, ptr %node_type324, i32 0, i32 1
-  %733 = load ptr, ptr %d327, align 8
-  store ptr %733, ptr %data330, align 8
-  %734 = load ptr, ptr %c, align 8
-  %735 = load %Node, ptr %node_type324, align 8
-  %736 = call ptr @create_node(ptr %734, %Node %735)
-  store ptr %736, ptr %typ303, align 8
-  br label %merge_block331
-
-merge_block331:                                   ; preds = %merge_block319, %then_block321
-  %typ332 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %exp300, i32 0, i32 0
-  %737 = load i64, ptr %typ332, align 4
-  %738 = load i64, ptr @UNARY_EXPRESSION_TYPE_STAR, align 4
-  %739 = icmp eq i64 %737, %738
-  br i1 %739, label %then_block333, label %merge_block341
-
-then_block333:                                    ; preds = %merge_block331
-  %740 = load ptr, ptr %typ303, align 8
-  %type334 = getelementptr %Node, ptr %740, i32 0, i32 0
-  %741 = load i64, ptr %type334, align 4
-  %742 = load i64, ptr @NODE_TYPE_POINTER_TYPE, align 4
-  %743 = icmp eq i64 %741, %742
-  call void @assert(i1 %743)
-  %744 = load ptr, ptr %k, align 8
-  %node_type335 = getelementptr %Variable, ptr %744, i32 0, i32 3
-  %745 = load ptr, ptr %node_type335, align 8
-  %n336 = alloca ptr, align 8
-  store ptr %745, ptr %n336, align 8
-  %746 = load ptr, ptr %n336, align 8
-  %data337 = getelementptr %Node, ptr %746, i32 0, i32 1
-  %747 = load ptr, ptr %data337, align 8
-  %type338 = getelementptr %NODE_TYPE_POINTER_TYPE_DATA, ptr %747, i32 0, i32 0
-  %748 = load ptr, ptr %type338, align 8
-  store ptr %748, ptr %typ303, align 8
-  %749 = load ptr, ptr %c, align 8
-  %750 = load ptr, ptr %typ303, align 8
-  %751 = call ptr @codegen_get_llvm_type(ptr %749, ptr %750)
-  %ptr_type = alloca ptr, align 8
-  store ptr %751, ptr %ptr_type, align 8
-  %752 = load ptr, ptr %ptr_type, align 8
-  %753 = icmp ne ptr %752, null
-  call void @assert(i1 %753)
-  %754 = load ptr, ptr %c, align 8
-  %builder339 = getelementptr %codegen, ptr %754, i32 0, i32 2
-  %755 = load ptr, ptr %builder339, align 8
-  %756 = load ptr, ptr %ptr_type, align 8
-  %757 = load ptr, ptr %756, align 8
-  %758 = load ptr, ptr %k, align 8
-  %value340 = getelementptr %Variable, ptr %758, i32 0, i32 0
-  %759 = load ptr, ptr %value340, align 8
-  %760 = call ptr @LLVMBuildLoad2(ptr %755, ptr %757, ptr %759, ptr @223)
-  store ptr %760, ptr %r, align 8
-  br label %merge_block341
-
-merge_block341:                                   ; preds = %merge_block331, %then_block333
-  %761 = load ptr, ptr %c, align 8
-  %762 = load ptr, ptr %r, align 8
-  %763 = load ptr, ptr %name, align 8
-  %764 = load ptr, ptr %expression, align 8
-  %765 = load ptr, ptr %typ303, align 8
-  %766 = call ptr @codegen_generate_literal(ptr %761, ptr %762, ptr %763, ptr %764, ptr %765)
-  ret ptr %766
-
-merge_block342:                                   ; preds = %merge_block296
-  %767 = load ptr, ptr %expression, align 8
-  %type343 = getelementptr %Node, ptr %767, i32 0, i32 0
-  %768 = load i64, ptr %type343, align 4
-  %769 = load i64, ptr @NODE_TYPE_FUNCTION_TYPE, align 4
+  %736 = load ptr, ptr %k, align 8
+  %node_type326 = getelementptr %Variable, ptr %736, i32 0, i32 3
+  %737 = load ptr, ptr %node_type326, align 8
+  %typ327 = alloca ptr, align 8
+  store ptr %737, ptr %typ327, align 8
+  %typ328 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %exp324, i32 0, i32 0
+  %738 = load i64, ptr %typ328, align 4
+  %739 = load i64, ptr @UNARY_EXPRESSION_TYPE_NOT, align 4
+  %740 = icmp eq i64 %738, %739
+  br i1 %740, label %then_block329, label %merge_block343
+
+then_block329:                                    ; preds = %then_block322
+  %741 = load ptr, ptr %typ327, align 8
+  %type330 = getelementptr %Node, ptr %741, i32 0, i32 0
+  %742 = load i64, ptr %type330, align 4
+  %743 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
+  %744 = icmp eq i64 %742, %743
+  call void @assert(i1 %744)
+  %745 = load ptr, ptr %typ327, align 8
+  %data331 = getelementptr %Node, ptr %745, i32 0, i32 1
+  %746 = load ptr, ptr %data331, align 8
+  %747 = load %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %746, align 8
+  %simple_type332 = alloca %NODE_TYPE_SIMPLE_TYPE_DATA, align 8
+  store %NODE_TYPE_SIMPLE_TYPE_DATA %747, ptr %simple_type332, align 8
+  %name333 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %simple_type332, i32 0, i32 0
+  %748 = load ptr, ptr %name333, align 8
+  %749 = call i1 @strcmp(ptr %748, ptr @220)
+  call void @assert(i1 %749)
+  %750 = load ptr, ptr %c, align 8
+  %builder334 = getelementptr %codegen, ptr %750, i32 0, i32 2
+  %751 = load ptr, ptr %builder334, align 8
+  %752 = load i64, ptr @LLVMIntEQ, align 4
+  %753 = load ptr, ptr %k, align 8
+  %value335 = getelementptr %Variable, ptr %753, i32 0, i32 0
+  %754 = load ptr, ptr %value335, align 8
+  %755 = call ptr @LLVMInt1Type()
+  %756 = call ptr @LLVMConstInt(ptr %755, i64 0, i64 0)
+  %757 = call ptr @LLVMBuildICmp(ptr %751, i64 %752, ptr %754, ptr %756, ptr @221)
+  store ptr %757, ptr %r, align 8
+  %node_type336 = alloca %Node, align 8
+  %type337 = getelementptr %Node, ptr %node_type336, i32 0, i32 0
+  %758 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
+  store i64 %758, ptr %type337, align 4
+  %759 = load ptr, ptr %c, align 8
+  %arena338 = getelementptr %codegen, ptr %759, i32 0, i32 3
+  %760 = load ptr, ptr %arena338, align 8
+  %761 = call ptr @arena_alloc(ptr %760, i64 16)
+  %d339 = alloca ptr, align 8
+  store ptr %761, ptr %d339, align 8
+  %762 = load ptr, ptr %d339, align 8
+  %name340 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %762, i32 0, i32 0
+  store ptr @222, ptr %name340, align 8
+  %763 = load ptr, ptr %d339, align 8
+  %underlying_type341 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %763, i32 0, i32 1
+  store ptr null, ptr %underlying_type341, align 8
+  %data342 = getelementptr %Node, ptr %node_type336, i32 0, i32 1
+  %764 = load ptr, ptr %d339, align 8
+  store ptr %764, ptr %data342, align 8
+  %765 = load ptr, ptr %c, align 8
+  %766 = load %Node, ptr %node_type336, align 8
+  %767 = call ptr @create_node(ptr %765, %Node %766)
+  store ptr %767, ptr %typ327, align 8
+  br label %merge_block343
+
+merge_block343:                                   ; preds = %then_block322, %then_block329
+  %typ344 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %exp324, i32 0, i32 0
+  %768 = load i64, ptr %typ344, align 4
+  %769 = load i64, ptr @UNARY_EXPRESSION_TYPE_MINUS, align 4
   %770 = icmp eq i64 %768, %769
-  br i1 %770, label %then_block344, label %merge_block358
+  br i1 %770, label %then_block345, label %merge_block355
 
-then_block344:                                    ; preds = %merge_block342
+then_block345:                                    ; preds = %merge_block343
   %771 = load ptr, ptr %c, align 8
-  %environment345 = getelementptr %codegen, ptr %771, i32 0, i32 4
-  %772 = load ptr, ptr %environment345, align 8
-  %773 = load %Environment, ptr %772, align 8
+  %builder346 = getelementptr %codegen, ptr %771, i32 0, i32 2
+  %772 = load ptr, ptr %builder346, align 8
+  %773 = load ptr, ptr %k, align 8
+  %value347 = getelementptr %Variable, ptr %773, i32 0, i32 0
+  %774 = load ptr, ptr %value347, align 8
+  %775 = call ptr @LLVMBuildNeg(ptr %772, ptr %774, ptr @223)
+  store ptr %775, ptr %r, align 8
+  %node_type348 = alloca %Node, align 8
+  %type349 = getelementptr %Node, ptr %node_type348, i32 0, i32 0
+  %776 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
+  store i64 %776, ptr %type349, align 4
+  %777 = load ptr, ptr %c, align 8
+  %arena350 = getelementptr %codegen, ptr %777, i32 0, i32 3
+  %778 = load ptr, ptr %arena350, align 8
+  %779 = call ptr @arena_alloc(ptr %778, i64 16)
+  %d351 = alloca ptr, align 8
+  store ptr %779, ptr %d351, align 8
+  %780 = load ptr, ptr %d351, align 8
+  %name352 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %780, i32 0, i32 0
+  store ptr @224, ptr %name352, align 8
+  %781 = load ptr, ptr %d351, align 8
+  %underlying_type353 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %781, i32 0, i32 1
+  store ptr null, ptr %underlying_type353, align 8
+  %data354 = getelementptr %Node, ptr %node_type348, i32 0, i32 1
+  %782 = load ptr, ptr %d351, align 8
+  store ptr %782, ptr %data354, align 8
+  %783 = load ptr, ptr %c, align 8
+  %784 = load %Node, ptr %node_type348, align 8
+  %785 = call ptr @create_node(ptr %783, %Node %784)
+  store ptr %785, ptr %typ327, align 8
+  br label %merge_block355
+
+merge_block355:                                   ; preds = %merge_block343, %then_block345
+  %typ356 = getelementptr %NODE_UNARY_EXPRESSION_DATA, ptr %exp324, i32 0, i32 0
+  %786 = load i64, ptr %typ356, align 4
+  %787 = load i64, ptr @UNARY_EXPRESSION_TYPE_STAR, align 4
+  %788 = icmp eq i64 %786, %787
+  br i1 %788, label %then_block357, label %merge_block365
+
+then_block357:                                    ; preds = %merge_block355
+  %789 = load ptr, ptr %typ327, align 8
+  %type358 = getelementptr %Node, ptr %789, i32 0, i32 0
+  %790 = load i64, ptr %type358, align 4
+  %791 = load i64, ptr @NODE_TYPE_POINTER_TYPE, align 4
+  %792 = icmp eq i64 %790, %791
+  call void @assert(i1 %792)
+  %793 = load ptr, ptr %k, align 8
+  %node_type359 = getelementptr %Variable, ptr %793, i32 0, i32 3
+  %794 = load ptr, ptr %node_type359, align 8
+  %n360 = alloca ptr, align 8
+  store ptr %794, ptr %n360, align 8
+  %795 = load ptr, ptr %n360, align 8
+  %data361 = getelementptr %Node, ptr %795, i32 0, i32 1
+  %796 = load ptr, ptr %data361, align 8
+  %type362 = getelementptr %NODE_TYPE_POINTER_TYPE_DATA, ptr %796, i32 0, i32 0
+  %797 = load ptr, ptr %type362, align 8
+  store ptr %797, ptr %typ327, align 8
+  %798 = load ptr, ptr %c, align 8
+  %799 = load ptr, ptr %typ327, align 8
+  %800 = call ptr @codegen_get_llvm_type(ptr %798, ptr %799)
+  %ptr_type = alloca ptr, align 8
+  store ptr %800, ptr %ptr_type, align 8
+  %801 = load ptr, ptr %ptr_type, align 8
+  %802 = icmp ne ptr %801, null
+  call void @assert(i1 %802)
+  %803 = load ptr, ptr %c, align 8
+  %builder363 = getelementptr %codegen, ptr %803, i32 0, i32 2
+  %804 = load ptr, ptr %builder363, align 8
+  %805 = load ptr, ptr %ptr_type, align 8
+  %806 = load ptr, ptr %805, align 8
+  %807 = load ptr, ptr %k, align 8
+  %value364 = getelementptr %Variable, ptr %807, i32 0, i32 0
+  %808 = load ptr, ptr %value364, align 8
+  %809 = call ptr @LLVMBuildLoad2(ptr %804, ptr %806, ptr %808, ptr @225)
+  store ptr %809, ptr %r, align 8
+  br label %merge_block365
+
+merge_block365:                                   ; preds = %merge_block355, %then_block357
+  %810 = load ptr, ptr %c, align 8
+  %811 = load ptr, ptr %r, align 8
+  %812 = load ptr, ptr %name, align 8
+  %813 = load ptr, ptr %expression, align 8
+  %814 = load ptr, ptr %typ327, align 8
+  %815 = call ptr @codegen_generate_literal(ptr %810, ptr %811, ptr %812, ptr %813, ptr %814)
+  ret ptr %815
+
+merge_block366:                                   ; preds = %merge_block320
+  %816 = load ptr, ptr %expression, align 8
+  %type367 = getelementptr %Node, ptr %816, i32 0, i32 0
+  %817 = load i64, ptr %type367, align 4
+  %818 = load i64, ptr @NODE_TYPE_FUNCTION_TYPE, align 4
+  %819 = icmp eq i64 %817, %818
+  br i1 %819, label %then_block368, label %merge_block382
+
+then_block368:                                    ; preds = %merge_block366
+  %820 = load ptr, ptr %c, align 8
+  %environment369 = getelementptr %codegen, ptr %820, i32 0, i32 4
+  %821 = load ptr, ptr %environment369, align 8
+  %822 = load %Environment, ptr %821, align 8
   %e = alloca %Environment, align 8
-  store %Environment %773, ptr %e, align 8
+  store %Environment %822, ptr %e, align 8
   %scope_stack_len = getelementptr %Environment, ptr %e, i32 0, i32 1
-  %774 = load i64, ptr %scope_stack_len, align 4
-  %775 = icmp eq i64 %774, 1
-  call void @assert(i1 %775)
-  %776 = load ptr, ptr %c, align 8
-  %environment346 = getelementptr %codegen, ptr %776, i32 0, i32 4
-  %777 = load ptr, ptr %environment346, align 8
-  %778 = load ptr, ptr %name, align 8
-  %779 = call ptr @environment_get_variable(ptr %777, ptr %778)
+  %823 = load i64, ptr %scope_stack_len, align 4
+  %824 = icmp eq i64 %823, 1
+  call void @assert(i1 %824)
+  %825 = load ptr, ptr %c, align 8
+  %environment370 = getelementptr %codegen, ptr %825, i32 0, i32 4
+  %826 = load ptr, ptr %environment370, align 8
+  %827 = load ptr, ptr %name, align 8
+  %828 = call ptr @environment_get_variable(ptr %826, ptr %827)
   %existing = alloca ptr, align 8
-  store ptr %779, ptr %existing, align 8
-  %780 = load ptr, ptr %existing, align 8
-  %781 = icmp ne ptr %780, null
-  br i1 %781, label %then_block347, label %merge_block348
-
-then_block347:                                    ; preds = %then_block344
-  %782 = load ptr, ptr %existing, align 8
-  ret ptr %782
-
-merge_block348:                                   ; preds = %then_block344
-  %783 = load ptr, ptr %c, align 8
-  %784 = load ptr, ptr %expression, align 8
-  %785 = call ptr @codegen_get_llvm_type(ptr %783, ptr %784)
-  %function_type349 = alloca ptr, align 8
-  store ptr %785, ptr %function_type349, align 8
-  %786 = load ptr, ptr %function_type349, align 8
-  %787 = icmp ne ptr %786, null
-  call void @assert(i1 %787)
-  %788 = load ptr, ptr %c, align 8
-  %llvm_module350 = getelementptr %codegen, ptr %788, i32 0, i32 0
-  %789 = load ptr, ptr %llvm_module350, align 8
-  %790 = load ptr, ptr %name, align 8
-  %791 = load ptr, ptr %function_type349, align 8
-  %792 = load ptr, ptr %791, align 8
-  %793 = call ptr @LLVMAddFunction(ptr %789, ptr %790, ptr %792)
-  %function351 = alloca ptr, align 8
-  store ptr %793, ptr %function351, align 8
-  %v352 = alloca %Variable, align 8
-  %value353 = getelementptr %Variable, ptr %v352, i32 0, i32 0
-  %794 = load ptr, ptr %function351, align 8
-  store ptr %794, ptr %value353, align 8
-  %type354 = getelementptr %Variable, ptr %v352, i32 0, i32 1
-  store ptr null, ptr %type354, align 8
-  %stack_level355 = getelementptr %Variable, ptr %v352, i32 0, i32 4
-  store ptr null, ptr %stack_level355, align 8
-  %node356 = getelementptr %Variable, ptr %v352, i32 0, i32 2
-  %795 = load ptr, ptr %expression, align 8
-  store ptr %795, ptr %node356, align 8
-  %node_type357 = getelementptr %Variable, ptr %v352, i32 0, i32 3
-  %796 = load ptr, ptr %expression, align 8
-  store ptr %796, ptr %node_type357, align 8
-  %797 = load ptr, ptr %c, align 8
-  %798 = load %Variable, ptr %v352, align 8
-  %799 = call ptr @codegen_create_variable(ptr %797, %Variable %798)
-  ret ptr %799
-
-merge_block358:                                   ; preds = %merge_block342
-  %800 = load ptr, ptr %expression, align 8
-  %type359 = getelementptr %Node, ptr %800, i32 0, i32 0
-  %801 = load i64, ptr %type359, align 4
-  %802 = load i64, ptr @NODE_FUNCTION_CALL_STATEMENT, align 4
-  %803 = icmp eq i64 %801, %802
-  br i1 %803, label %then_block360, label %merge_block361
-
-then_block360:                                    ; preds = %merge_block358
-  %804 = load ptr, ptr %c, align 8
-  %805 = load ptr, ptr %expression, align 8
-  %806 = call ptr @codegen_generate_function_call_statement(ptr %804, ptr %805)
-  ret ptr %806
-
-merge_block361:                                   ; preds = %merge_block358
-  %807 = load ptr, ptr %expression, align 8
-  %type362 = getelementptr %Node, ptr %807, i32 0, i32 0
-  %808 = load i64, ptr %type362, align 4
-  %809 = load i64, ptr @NODE_CAST_STATEMENT, align 4
-  %810 = icmp eq i64 %808, %809
-  br i1 %810, label %then_block363, label %merge_block375
-
-then_block363:                                    ; preds = %merge_block361
-  %811 = load ptr, ptr %expression, align 8
-  %data364 = getelementptr %Node, ptr %811, i32 0, i32 1
-  %812 = load ptr, ptr %data364, align 8
-  %813 = load %NODE_CAST_STATEMENT_DATA, ptr %812, align 8
-  %exp365 = alloca %NODE_CAST_STATEMENT_DATA, align 8
-  store %NODE_CAST_STATEMENT_DATA %813, ptr %exp365, align 8
-  %814 = load ptr, ptr %c, align 8
-  %expression366 = getelementptr %NODE_CAST_STATEMENT_DATA, ptr %exp365, i32 0, i32 1
-  %815 = load ptr, ptr %expression366, align 8
-  %816 = call ptr @codegen_generate_expression_value(ptr %814, ptr %815, ptr @224)
-  %val = alloca ptr, align 8
-  store ptr %816, ptr %val, align 8
-  %817 = load ptr, ptr %val, align 8
-  %818 = icmp ne ptr %817, null
-  call void @assert(i1 %818)
-  %v367 = alloca %Variable, align 8
-  %value368 = getelementptr %Variable, ptr %v367, i32 0, i32 0
-  %819 = load ptr, ptr %val, align 8
-  %value369 = getelementptr %Variable, ptr %819, i32 0, i32 0
-  %820 = load ptr, ptr %value369, align 8
-  store ptr %820, ptr %value368, align 8
-  %type370 = getelementptr %Variable, ptr %v367, i32 0, i32 1
-  store ptr null, ptr %type370, align 8
-  %stack_level371 = getelementptr %Variable, ptr %v367, i32 0, i32 4
-  store ptr null, ptr %stack_level371, align 8
-  %node372 = getelementptr %Variable, ptr %v367, i32 0, i32 2
-  %821 = load ptr, ptr %expression, align 8
-  store ptr %821, ptr %node372, align 8
-  %node_type373 = getelementptr %Variable, ptr %v367, i32 0, i32 3
-  %typ374 = getelementptr %NODE_CAST_STATEMENT_DATA, ptr %exp365, i32 0, i32 0
-  %822 = load ptr, ptr %typ374, align 8
-  store ptr %822, ptr %node_type373, align 8
-  %823 = load ptr, ptr %c, align 8
-  %824 = load %Variable, ptr %v367, align 8
-  %825 = call ptr @codegen_create_variable(ptr %823, %Variable %824)
-  ret ptr %825
-
-merge_block375:                                   ; preds = %merge_block361
-  %826 = load ptr, ptr %expression, align 8
-  %type376 = getelementptr %Node, ptr %826, i32 0, i32 0
-  %827 = load i64, ptr %type376, align 4
-  %828 = load i64, ptr @NODE_SIZEOF_STATEMENT, align 4
-  %829 = icmp eq i64 %827, %828
-  br i1 %829, label %then_block377, label %merge_block395
-
-then_block377:                                    ; preds = %merge_block375
-  %830 = load ptr, ptr %expression, align 8
-  %data378 = getelementptr %Node, ptr %830, i32 0, i32 1
-  %831 = load ptr, ptr %data378, align 8
-  %832 = load %NODE_SIZEOF_STATEMENT_DATA, ptr %831, align 8
-  %exp379 = alloca %NODE_SIZEOF_STATEMENT_DATA, align 8
-  store %NODE_SIZEOF_STATEMENT_DATA %832, ptr %exp379, align 8
-  %833 = load ptr, ptr %c, align 8
-  %typ380 = getelementptr %NODE_SIZEOF_STATEMENT_DATA, ptr %exp379, i32 0, i32 0
-  %834 = load ptr, ptr %typ380, align 8
-  %835 = call ptr @codegen_get_llvm_type(ptr %833, ptr %834)
-  %typ381 = alloca ptr, align 8
-  store ptr %835, ptr %typ381, align 8
-  %836 = load ptr, ptr %typ381, align 8
-  %837 = icmp ne ptr %836, null
-  call void @assert(i1 %837)
-  %838 = load ptr, ptr %c, align 8
-  %llvm_target_data = getelementptr %codegen, ptr %838, i32 0, i32 9
-  %839 = load ptr, ptr %llvm_target_data, align 8
-  %840 = load ptr, ptr %typ381, align 8
+  store ptr %828, ptr %existing, align 8
+  %829 = load ptr, ptr %existing, align 8
+  %830 = icmp ne ptr %829, null
+  br i1 %830, label %then_block371, label %merge_block372
+
+then_block371:                                    ; preds = %then_block368
+  %831 = load ptr, ptr %existing, align 8
+  ret ptr %831
+
+merge_block372:                                   ; preds = %then_block368
+  %832 = load ptr, ptr %c, align 8
+  %833 = load ptr, ptr %expression, align 8
+  %834 = call ptr @codegen_get_llvm_type(ptr %832, ptr %833)
+  %function_type373 = alloca ptr, align 8
+  store ptr %834, ptr %function_type373, align 8
+  %835 = load ptr, ptr %function_type373, align 8
+  %836 = icmp ne ptr %835, null
+  call void @assert(i1 %836)
+  %837 = load ptr, ptr %c, align 8
+  %llvm_module374 = getelementptr %codegen, ptr %837, i32 0, i32 0
+  %838 = load ptr, ptr %llvm_module374, align 8
+  %839 = load ptr, ptr %name, align 8
+  %840 = load ptr, ptr %function_type373, align 8
   %841 = load ptr, ptr %840, align 8
-  %842 = call i64 @LLVMStoreSizeOfType(ptr %839, ptr %841)
+  %842 = call ptr @LLVMAddFunction(ptr %838, ptr %839, ptr %841)
+  %function375 = alloca ptr, align 8
+  store ptr %842, ptr %function375, align 8
+  %v376 = alloca %Variable, align 8
+  %value377 = getelementptr %Variable, ptr %v376, i32 0, i32 0
+  %843 = load ptr, ptr %function375, align 8
+  store ptr %843, ptr %value377, align 8
+  %type378 = getelementptr %Variable, ptr %v376, i32 0, i32 1
+  store ptr null, ptr %type378, align 8
+  %stack_level379 = getelementptr %Variable, ptr %v376, i32 0, i32 4
+  store ptr null, ptr %stack_level379, align 8
+  %node380 = getelementptr %Variable, ptr %v376, i32 0, i32 2
+  %844 = load ptr, ptr %expression, align 8
+  store ptr %844, ptr %node380, align 8
+  %node_type381 = getelementptr %Variable, ptr %v376, i32 0, i32 3
+  %845 = load ptr, ptr %expression, align 8
+  store ptr %845, ptr %node_type381, align 8
+  %846 = load ptr, ptr %c, align 8
+  %847 = load %Variable, ptr %v376, align 8
+  %848 = call ptr @codegen_create_variable(ptr %846, %Variable %847)
+  ret ptr %848
+
+merge_block382:                                   ; preds = %merge_block366
+  %849 = load ptr, ptr %expression, align 8
+  %type383 = getelementptr %Node, ptr %849, i32 0, i32 0
+  %850 = load i64, ptr %type383, align 4
+  %851 = load i64, ptr @NODE_FUNCTION_CALL_STATEMENT, align 4
+  %852 = icmp eq i64 %850, %851
+  br i1 %852, label %then_block384, label %merge_block385
+
+then_block384:                                    ; preds = %merge_block382
+  %853 = load ptr, ptr %c, align 8
+  %854 = load ptr, ptr %expression, align 8
+  %855 = call ptr @codegen_generate_function_call_statement(ptr %853, ptr %854)
+  ret ptr %855
+
+merge_block385:                                   ; preds = %merge_block382
+  %856 = load ptr, ptr %expression, align 8
+  %type386 = getelementptr %Node, ptr %856, i32 0, i32 0
+  %857 = load i64, ptr %type386, align 4
+  %858 = load i64, ptr @NODE_CAST_STATEMENT, align 4
+  %859 = icmp eq i64 %857, %858
+  br i1 %859, label %then_block387, label %merge_block399
+
+then_block387:                                    ; preds = %merge_block385
+  %860 = load ptr, ptr %expression, align 8
+  %data388 = getelementptr %Node, ptr %860, i32 0, i32 1
+  %861 = load ptr, ptr %data388, align 8
+  %862 = load %NODE_CAST_STATEMENT_DATA, ptr %861, align 8
+  %exp389 = alloca %NODE_CAST_STATEMENT_DATA, align 8
+  store %NODE_CAST_STATEMENT_DATA %862, ptr %exp389, align 8
+  %863 = load ptr, ptr %c, align 8
+  %expression390 = getelementptr %NODE_CAST_STATEMENT_DATA, ptr %exp389, i32 0, i32 1
+  %864 = load ptr, ptr %expression390, align 8
+  %865 = call ptr @codegen_generate_expression_value(ptr %863, ptr %864, ptr @226)
+  %val = alloca ptr, align 8
+  store ptr %865, ptr %val, align 8
+  %866 = load ptr, ptr %val, align 8
+  %867 = icmp ne ptr %866, null
+  call void @assert(i1 %867)
+  %v391 = alloca %Variable, align 8
+  %value392 = getelementptr %Variable, ptr %v391, i32 0, i32 0
+  %868 = load ptr, ptr %val, align 8
+  %value393 = getelementptr %Variable, ptr %868, i32 0, i32 0
+  %869 = load ptr, ptr %value393, align 8
+  store ptr %869, ptr %value392, align 8
+  %type394 = getelementptr %Variable, ptr %v391, i32 0, i32 1
+  store ptr null, ptr %type394, align 8
+  %stack_level395 = getelementptr %Variable, ptr %v391, i32 0, i32 4
+  store ptr null, ptr %stack_level395, align 8
+  %node396 = getelementptr %Variable, ptr %v391, i32 0, i32 2
+  %870 = load ptr, ptr %expression, align 8
+  store ptr %870, ptr %node396, align 8
+  %node_type397 = getelementptr %Variable, ptr %v391, i32 0, i32 3
+  %typ398 = getelementptr %NODE_CAST_STATEMENT_DATA, ptr %exp389, i32 0, i32 0
+  %871 = load ptr, ptr %typ398, align 8
+  store ptr %871, ptr %node_type397, align 8
+  %872 = load ptr, ptr %c, align 8
+  %873 = load %Variable, ptr %v391, align 8
+  %874 = call ptr @codegen_create_variable(ptr %872, %Variable %873)
+  ret ptr %874
+
+merge_block399:                                   ; preds = %merge_block385
+  %875 = load ptr, ptr %expression, align 8
+  %type400 = getelementptr %Node, ptr %875, i32 0, i32 0
+  %876 = load i64, ptr %type400, align 4
+  %877 = load i64, ptr @NODE_SIZEOF_STATEMENT, align 4
+  %878 = icmp eq i64 %876, %877
+  br i1 %878, label %then_block401, label %merge_block419
+
+then_block401:                                    ; preds = %merge_block399
+  %879 = load ptr, ptr %expression, align 8
+  %data402 = getelementptr %Node, ptr %879, i32 0, i32 1
+  %880 = load ptr, ptr %data402, align 8
+  %881 = load %NODE_SIZEOF_STATEMENT_DATA, ptr %880, align 8
+  %exp403 = alloca %NODE_SIZEOF_STATEMENT_DATA, align 8
+  store %NODE_SIZEOF_STATEMENT_DATA %881, ptr %exp403, align 8
+  %882 = load ptr, ptr %c, align 8
+  %typ404 = getelementptr %NODE_SIZEOF_STATEMENT_DATA, ptr %exp403, i32 0, i32 0
+  %883 = load ptr, ptr %typ404, align 8
+  %884 = call ptr @codegen_get_llvm_type(ptr %882, ptr %883)
+  %typ405 = alloca ptr, align 8
+  store ptr %884, ptr %typ405, align 8
+  %885 = load ptr, ptr %typ405, align 8
+  %886 = icmp ne ptr %885, null
+  call void @assert(i1 %886)
+  %887 = load ptr, ptr %c, align 8
+  %llvm_target_data = getelementptr %codegen, ptr %887, i32 0, i32 9
+  %888 = load ptr, ptr %llvm_target_data, align 8
+  %889 = load ptr, ptr %typ405, align 8
+  %890 = load ptr, ptr %889, align 8
+  %891 = call i64 @LLVMStoreSizeOfType(ptr %888, ptr %890)
   %size_in_bytes = alloca i64, align 8
-  store i64 %842, ptr %size_in_bytes, align 4
-  %843 = call ptr @LLVMInt64Type()
-  %844 = load i64, ptr %size_in_bytes, align 4
-  %845 = call ptr @LLVMConstInt(ptr %843, i64 %844, i64 0)
+  store i64 %891, ptr %size_in_bytes, align 4
+  %892 = call ptr @LLVMInt64Type()
+  %893 = load i64, ptr %size_in_bytes, align 4
+  %894 = call ptr @LLVMConstInt(ptr %892, i64 %893, i64 0)
   %size_val = alloca ptr, align 8
-  store ptr %845, ptr %size_val, align 8
-  %node_type382 = alloca %Node, align 8
-  %type383 = getelementptr %Node, ptr %node_type382, i32 0, i32 0
-  %846 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
-  store i64 %846, ptr %type383, align 4
-  %847 = load ptr, ptr %c, align 8
-  %arena384 = getelementptr %codegen, ptr %847, i32 0, i32 3
-  %848 = load ptr, ptr %arena384, align 8
-  %849 = call ptr @arena_alloc(ptr %848, i64 16)
-  %d385 = alloca ptr, align 8
-  store ptr %849, ptr %d385, align 8
-  %850 = load ptr, ptr %d385, align 8
-  %name386 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %850, i32 0, i32 0
-  store ptr @225, ptr %name386, align 8
-  %851 = load ptr, ptr %d385, align 8
-  %underlying_type387 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %851, i32 0, i32 1
-  store ptr null, ptr %underlying_type387, align 8
-  %data388 = getelementptr %Node, ptr %node_type382, i32 0, i32 1
-  %852 = load ptr, ptr %d385, align 8
-  store ptr %852, ptr %data388, align 8
-  %v389 = alloca %Variable, align 8
-  %value390 = getelementptr %Variable, ptr %v389, i32 0, i32 0
-  %853 = load ptr, ptr %size_val, align 8
-  store ptr %853, ptr %value390, align 8
-  %type391 = getelementptr %Variable, ptr %v389, i32 0, i32 1
-  store ptr null, ptr %type391, align 8
-  %stack_level392 = getelementptr %Variable, ptr %v389, i32 0, i32 4
-  store ptr null, ptr %stack_level392, align 8
-  %node393 = getelementptr %Variable, ptr %v389, i32 0, i32 2
-  %854 = load ptr, ptr %expression, align 8
-  store ptr %854, ptr %node393, align 8
-  %node_type394 = getelementptr %Variable, ptr %v389, i32 0, i32 3
-  %855 = load ptr, ptr %c, align 8
-  %856 = load %Node, ptr %node_type382, align 8
-  %857 = call ptr @create_node(ptr %855, %Node %856)
-  store ptr %857, ptr %node_type394, align 8
-  %858 = load ptr, ptr %c, align 8
-  %859 = load %Variable, ptr %v389, align 8
-  %860 = call ptr @codegen_create_variable(ptr %858, %Variable %859)
-  ret ptr %860
-
-merge_block395:                                   ; preds = %merge_block375
-  %861 = load ptr, ptr %expression, align 8
-  %type396 = getelementptr %Node, ptr %861, i32 0, i32 0
-  %862 = load i64, ptr %type396, align 4
-  %863 = load i64, ptr @NODE_TYPE_STRUCT_TYPE, align 4
-  %864 = icmp eq i64 %862, %863
-  br i1 %864, label %then_block397, label %merge_block428
-
-then_block397:                                    ; preds = %merge_block395
-  %865 = load ptr, ptr %expression, align 8
-  %data398 = getelementptr %Node, ptr %865, i32 0, i32 1
-  %866 = load ptr, ptr %data398, align 8
-  %867 = load %NODE_TYPE_STRUCT_TYPE_DATA, ptr %866, align 8
+  store ptr %894, ptr %size_val, align 8
+  %node_type406 = alloca %Node, align 8
+  %type407 = getelementptr %Node, ptr %node_type406, i32 0, i32 0
+  %895 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
+  store i64 %895, ptr %type407, align 4
+  %896 = load ptr, ptr %c, align 8
+  %arena408 = getelementptr %codegen, ptr %896, i32 0, i32 3
+  %897 = load ptr, ptr %arena408, align 8
+  %898 = call ptr @arena_alloc(ptr %897, i64 16)
+  %d409 = alloca ptr, align 8
+  store ptr %898, ptr %d409, align 8
+  %899 = load ptr, ptr %d409, align 8
+  %name410 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %899, i32 0, i32 0
+  store ptr @227, ptr %name410, align 8
+  %900 = load ptr, ptr %d409, align 8
+  %underlying_type411 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %900, i32 0, i32 1
+  store ptr null, ptr %underlying_type411, align 8
+  %data412 = getelementptr %Node, ptr %node_type406, i32 0, i32 1
+  %901 = load ptr, ptr %d409, align 8
+  store ptr %901, ptr %data412, align 8
+  %v413 = alloca %Variable, align 8
+  %value414 = getelementptr %Variable, ptr %v413, i32 0, i32 0
+  %902 = load ptr, ptr %size_val, align 8
+  store ptr %902, ptr %value414, align 8
+  %type415 = getelementptr %Variable, ptr %v413, i32 0, i32 1
+  store ptr null, ptr %type415, align 8
+  %stack_level416 = getelementptr %Variable, ptr %v413, i32 0, i32 4
+  store ptr null, ptr %stack_level416, align 8
+  %node417 = getelementptr %Variable, ptr %v413, i32 0, i32 2
+  %903 = load ptr, ptr %expression, align 8
+  store ptr %903, ptr %node417, align 8
+  %node_type418 = getelementptr %Variable, ptr %v413, i32 0, i32 3
+  %904 = load ptr, ptr %c, align 8
+  %905 = load %Node, ptr %node_type406, align 8
+  %906 = call ptr @create_node(ptr %904, %Node %905)
+  store ptr %906, ptr %node_type418, align 8
+  %907 = load ptr, ptr %c, align 8
+  %908 = load %Variable, ptr %v413, align 8
+  %909 = call ptr @codegen_create_variable(ptr %907, %Variable %908)
+  ret ptr %909
+
+merge_block419:                                   ; preds = %merge_block399
+  %910 = load ptr, ptr %expression, align 8
+  %type420 = getelementptr %Node, ptr %910, i32 0, i32 0
+  %911 = load i64, ptr %type420, align 4
+  %912 = load i64, ptr @NODE_TYPE_STRUCT_TYPE, align 4
+  %913 = icmp eq i64 %911, %912
+  br i1 %913, label %then_block421, label %merge_block452
+
+then_block421:                                    ; preds = %merge_block419
+  %914 = load ptr, ptr %expression, align 8
+  %data422 = getelementptr %Node, ptr %914, i32 0, i32 1
+  %915 = load ptr, ptr %data422, align 8
+  %916 = load %NODE_TYPE_STRUCT_TYPE_DATA, ptr %915, align 8
   %struc_data = alloca %NODE_TYPE_STRUCT_TYPE_DATA, align 8
-  store %NODE_TYPE_STRUCT_TYPE_DATA %867, ptr %struc_data, align 8
-  %868 = load ptr, ptr %c, align 8
-  %arena399 = getelementptr %codegen, ptr %868, i32 0, i32 3
-  %869 = load ptr, ptr %arena399, align 8
-  %870 = call ptr @arena_alloc(ptr %869, i64 16)
+  store %NODE_TYPE_STRUCT_TYPE_DATA %916, ptr %struc_data, align 8
+  %917 = load ptr, ptr %c, align 8
+  %arena423 = getelementptr %codegen, ptr %917, i32 0, i32 3
+  %918 = load ptr, ptr %arena423, align 8
+  %919 = call ptr @arena_alloc(ptr %918, i64 16)
   %dd = alloca ptr, align 8
-  store ptr %870, ptr %dd, align 8
-  %871 = load ptr, ptr %dd, align 8
-  %name400 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %871, i32 0, i32 0
-  %872 = load ptr, ptr %name, align 8
-  store ptr %872, ptr %name400, align 8
-  %873 = load ptr, ptr %dd, align 8
-  %underlying_type401 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %873, i32 0, i32 1
-  %874 = load ptr, ptr %expression, align 8
-  store ptr %874, ptr %underlying_type401, align 8
-  %n402 = alloca %Node, align 8
-  %type403 = getelementptr %Node, ptr %n402, i32 0, i32 0
-  %875 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
-  store i64 %875, ptr %type403, align 4
-  %data404 = getelementptr %Node, ptr %n402, i32 0, i32 1
-  %876 = load ptr, ptr %dd, align 8
-  store ptr %876, ptr %data404, align 8
-  %877 = load ptr, ptr %c, align 8
-  %878 = load %Node, ptr %n402, align 8
-  %879 = call ptr @create_node(ptr %877, %Node %878)
+  store ptr %919, ptr %dd, align 8
+  %920 = load ptr, ptr %dd, align 8
+  %name424 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %920, i32 0, i32 0
+  %921 = load ptr, ptr %name, align 8
+  store ptr %921, ptr %name424, align 8
+  %922 = load ptr, ptr %dd, align 8
+  %underlying_type425 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %922, i32 0, i32 1
+  %923 = load ptr, ptr %expression, align 8
+  store ptr %923, ptr %underlying_type425, align 8
+  %n426 = alloca %Node, align 8
+  %type427 = getelementptr %Node, ptr %n426, i32 0, i32 0
+  %924 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
+  store i64 %924, ptr %type427, align 4
+  %data428 = getelementptr %Node, ptr %n426, i32 0, i32 1
+  %925 = load ptr, ptr %dd, align 8
+  store ptr %925, ptr %data428, align 8
+  %926 = load ptr, ptr %c, align 8
+  %927 = load %Node, ptr %n426, align 8
+  %928 = call ptr @create_node(ptr %926, %Node %927)
   %simple_type_node = alloca ptr, align 8
-  store ptr %879, ptr %simple_type_node, align 8
-  %880 = load ptr, ptr %c, align 8
-  %llvm_context = getelementptr %codegen, ptr %880, i32 0, i32 1
-  %881 = load ptr, ptr %llvm_context, align 8
-  %882 = load ptr, ptr %name, align 8
-  %883 = call ptr @LLVMStructCreateNamed(ptr %881, ptr %882)
+  store ptr %928, ptr %simple_type_node, align 8
+  %929 = load ptr, ptr %c, align 8
+  %llvm_context = getelementptr %codegen, ptr %929, i32 0, i32 1
+  %930 = load ptr, ptr %llvm_context, align 8
+  %931 = load ptr, ptr %name, align 8
+  %932 = call ptr @LLVMStructCreateNamed(ptr %930, ptr %931)
   %struc_type = alloca ptr, align 8
-  store ptr %883, ptr %struc_type, align 8
-  %884 = load ptr, ptr %name, align 8
-  %885 = icmp ne ptr %884, null
-  br i1 %885, label %then_block405, label %merge_block413
-
-then_block405:                                    ; preds = %then_block397
-  %v406 = alloca %Variable, align 8
-  %value407 = getelementptr %Variable, ptr %v406, i32 0, i32 0
-  store ptr null, ptr %value407, align 8
-  %type408 = getelementptr %Variable, ptr %v406, i32 0, i32 1
-  %886 = load ptr, ptr %struc_type, align 8
-  store ptr %886, ptr %type408, align 8
-  %stack_level409 = getelementptr %Variable, ptr %v406, i32 0, i32 4
-  store ptr null, ptr %stack_level409, align 8
-  %node410 = getelementptr %Variable, ptr %v406, i32 0, i32 2
-  %887 = load ptr, ptr %expression, align 8
-  store ptr %887, ptr %node410, align 8
-  %node_type411 = getelementptr %Variable, ptr %v406, i32 0, i32 3
-  %888 = load ptr, ptr %simple_type_node, align 8
-  store ptr %888, ptr %node_type411, align 8
-  %889 = load ptr, ptr %c, align 8
-  %environment412 = getelementptr %codegen, ptr %889, i32 0, i32 4
-  %890 = load ptr, ptr %environment412, align 8
-  %891 = load ptr, ptr %name, align 8
-  %892 = load ptr, ptr %c, align 8
-  %893 = load %Variable, ptr %v406, align 8
-  %894 = call ptr @codegen_create_variable(ptr %892, %Variable %893)
-  call void @environment_add_variable(ptr %890, ptr %891, ptr %894)
-  br label %merge_block413
-
-merge_block413:                                   ; preds = %then_block397, %then_block405
-  %895 = load ptr, ptr %c, align 8
-  %arena414 = getelementptr %codegen, ptr %895, i32 0, i32 3
-  %896 = load ptr, ptr %arena414, align 8
-  %897 = call ptr @arena_alloc(ptr %896, i64 160)
+  store ptr %932, ptr %struc_type, align 8
+  %933 = load ptr, ptr %name, align 8
+  %934 = icmp ne ptr %933, null
+  br i1 %934, label %then_block429, label %merge_block437
+
+then_block429:                                    ; preds = %then_block421
+  %v430 = alloca %Variable, align 8
+  %value431 = getelementptr %Variable, ptr %v430, i32 0, i32 0
+  store ptr null, ptr %value431, align 8
+  %type432 = getelementptr %Variable, ptr %v430, i32 0, i32 1
+  %935 = load ptr, ptr %struc_type, align 8
+  store ptr %935, ptr %type432, align 8
+  %stack_level433 = getelementptr %Variable, ptr %v430, i32 0, i32 4
+  store ptr null, ptr %stack_level433, align 8
+  %node434 = getelementptr %Variable, ptr %v430, i32 0, i32 2
+  %936 = load ptr, ptr %expression, align 8
+  store ptr %936, ptr %node434, align 8
+  %node_type435 = getelementptr %Variable, ptr %v430, i32 0, i32 3
+  %937 = load ptr, ptr %simple_type_node, align 8
+  store ptr %937, ptr %node_type435, align 8
+  %938 = load ptr, ptr %c, align 8
+  %environment436 = getelementptr %codegen, ptr %938, i32 0, i32 4
+  %939 = load ptr, ptr %environment436, align 8
+  %940 = load ptr, ptr %name, align 8
+  %941 = load ptr, ptr %c, align 8
+  %942 = load %Variable, ptr %v430, align 8
+  %943 = call ptr @codegen_create_variable(ptr %941, %Variable %942)
+  call void @environment_add_variable(ptr %939, ptr %940, ptr %943)
+  br label %merge_block437
+
+merge_block437:                                   ; preds = %then_block421, %then_block429
+  %944 = load ptr, ptr %c, align 8
+  %arena438 = getelementptr %codegen, ptr %944, i32 0, i32 3
+  %945 = load ptr, ptr %arena438, align 8
+  %946 = call ptr @arena_alloc(ptr %945, i64 160)
   %llvm_types = alloca ptr, align 8
-  store ptr %897, ptr %llvm_types, align 8
-  %i415 = alloca i64, align 8
-  store i64 0, ptr %i415, align 4
-  br label %while_block416
+  store ptr %946, ptr %llvm_types, align 8
+  %i439 = alloca i64, align 8
+  store i64 0, ptr %i439, align 4
+  br label %while_block440
 
-while_block416:                                   ; preds = %inner_block417, %merge_block413
-  %898 = load i64, ptr %i415, align 4
+while_block440:                                   ; preds = %inner_block441, %merge_block437
+  %947 = load i64, ptr %i439, align 4
   %fields_len = getelementptr %NODE_TYPE_STRUCT_TYPE_DATA, ptr %struc_data, i32 0, i32 1
-  %899 = load i64, ptr %fields_len, align 4
-  %900 = icmp slt i64 %898, %899
-  br i1 %900, label %inner_block417, label %outer_block418
+  %948 = load i64, ptr %fields_len, align 4
+  %949 = icmp slt i64 %947, %948
+  br i1 %949, label %inner_block441, label %outer_block442
 
-inner_block417:                                   ; preds = %while_block416
+inner_block441:                                   ; preds = %while_block440
   %fields = getelementptr %NODE_TYPE_STRUCT_TYPE_DATA, ptr %struc_data, i32 0, i32 0
-  %901 = load ptr, ptr %fields, align 8
-  %902 = load i64, ptr %i415, align 4
-  %903 = getelementptr ptr, ptr %901, i64 %902
-  %904 = load ptr, ptr %903, align 8
+  %950 = load ptr, ptr %fields, align 8
+  %951 = load i64, ptr %i439, align 4
+  %952 = getelementptr ptr, ptr %950, i64 %951
+  %953 = load ptr, ptr %952, align 8
   %field = alloca ptr, align 8
-  store ptr %904, ptr %field, align 8
-  %905 = load ptr, ptr %field, align 8
-  %type419 = getelementptr %Node, ptr %905, i32 0, i32 0
-  %906 = load i64, ptr %type419, align 4
-  %907 = load i64, ptr @NODE_PRIMARY_EXPRESSION_IDENTIFIER, align 4
-  %908 = icmp eq i64 %906, %907
-  call void @assert(i1 %908)
-  %909 = load ptr, ptr %field, align 8
-  %data420 = getelementptr %Node, ptr %909, i32 0, i32 1
-  %910 = load ptr, ptr %data420, align 8
-  %type421 = getelementptr %NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, ptr %910, i32 0, i32 1
-  %911 = load ptr, ptr %type421, align 8
+  store ptr %953, ptr %field, align 8
+  %954 = load ptr, ptr %field, align 8
+  %type443 = getelementptr %Node, ptr %954, i32 0, i32 0
+  %955 = load i64, ptr %type443, align 4
+  %956 = load i64, ptr @NODE_PRIMARY_EXPRESSION_IDENTIFIER, align 4
+  %957 = icmp eq i64 %955, %956
+  call void @assert(i1 %957)
+  %958 = load ptr, ptr %field, align 8
+  %data444 = getelementptr %Node, ptr %958, i32 0, i32 1
+  %959 = load ptr, ptr %data444, align 8
+  %type445 = getelementptr %NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, ptr %959, i32 0, i32 1
+  %960 = load ptr, ptr %type445, align 8
   %t = alloca ptr, align 8
-  store ptr %911, ptr %t, align 8
-  %912 = load ptr, ptr %c, align 8
-  %913 = load ptr, ptr %t, align 8
-  %914 = call ptr @codegen_get_llvm_type(ptr %912, ptr %913)
+  store ptr %960, ptr %t, align 8
+  %961 = load ptr, ptr %c, align 8
+  %962 = load ptr, ptr %t, align 8
+  %963 = call ptr @codegen_get_llvm_type(ptr %961, ptr %962)
   %lt = alloca ptr, align 8
-  store ptr %914, ptr %lt, align 8
-  %915 = load ptr, ptr %lt, align 8
-  %916 = icmp ne ptr %915, null
-  call void @assert(i1 %916)
-  %917 = load ptr, ptr %llvm_types, align 8
-  %918 = load i64, ptr %i415, align 4
-  %919 = getelementptr ptr, ptr %917, i64 %918
-  %920 = load ptr, ptr %lt, align 8
-  %921 = load ptr, ptr %920, align 8
-  store ptr %921, ptr %919, align 8
-  %922 = load i64, ptr %i415, align 4
-  %923 = add i64 %922, 1
-  store i64 %923, ptr %i415, align 4
-  br label %while_block416
-
-outer_block418:                                   ; preds = %while_block416
-  %924 = load ptr, ptr %struc_type, align 8
-  %925 = load ptr, ptr %llvm_types, align 8
-  %926 = load i64, ptr %i415, align 4
-  call void @LLVMStructSetBody(ptr %924, ptr %925, i64 %926, i64 0)
-  %v422 = alloca %Variable, align 8
-  %value423 = getelementptr %Variable, ptr %v422, i32 0, i32 0
-  store ptr null, ptr %value423, align 8
-  %type424 = getelementptr %Variable, ptr %v422, i32 0, i32 1
-  %927 = load ptr, ptr %struc_type, align 8
-  store ptr %927, ptr %type424, align 8
-  %stack_level425 = getelementptr %Variable, ptr %v422, i32 0, i32 4
-  store ptr null, ptr %stack_level425, align 8
-  %node426 = getelementptr %Variable, ptr %v422, i32 0, i32 2
-  %928 = load ptr, ptr %expression, align 8
-  store ptr %928, ptr %node426, align 8
-  %node_type427 = getelementptr %Variable, ptr %v422, i32 0, i32 3
-  %929 = load ptr, ptr %simple_type_node, align 8
-  store ptr %929, ptr %node_type427, align 8
-  %930 = load ptr, ptr %c, align 8
-  %931 = load %Variable, ptr %v422, align 8
-  %932 = call ptr @codegen_create_variable(ptr %930, %Variable %931)
-  ret ptr %932
-
-merge_block428:                                   ; preds = %merge_block395
-  %933 = load ptr, ptr %expression, align 8
-  %type429 = getelementptr %Node, ptr %933, i32 0, i32 0
-  %934 = load i64, ptr %type429, align 4
-  %935 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
-  %936 = icmp eq i64 %934, %935
-  br i1 %936, label %then_block430, label %merge_block441
-
-then_block430:                                    ; preds = %merge_block428
-  %937 = load ptr, ptr %expression, align 8
-  %data431 = getelementptr %Node, ptr %937, i32 0, i32 1
-  %938 = load ptr, ptr %data431, align 8
-  %939 = load %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %938, align 8
+  store ptr %963, ptr %lt, align 8
+  %964 = load ptr, ptr %lt, align 8
+  %965 = icmp ne ptr %964, null
+  call void @assert(i1 %965)
+  %966 = load ptr, ptr %llvm_types, align 8
+  %967 = load i64, ptr %i439, align 4
+  %968 = getelementptr ptr, ptr %966, i64 %967
+  %969 = load ptr, ptr %lt, align 8
+  %970 = load ptr, ptr %969, align 8
+  store ptr %970, ptr %968, align 8
+  %971 = load i64, ptr %i439, align 4
+  %972 = add i64 %971, 1
+  store i64 %972, ptr %i439, align 4
+  br label %while_block440
+
+outer_block442:                                   ; preds = %while_block440
+  %973 = load ptr, ptr %struc_type, align 8
+  %974 = load ptr, ptr %llvm_types, align 8
+  %975 = load i64, ptr %i439, align 4
+  call void @LLVMStructSetBody(ptr %973, ptr %974, i64 %975, i64 0)
+  %v446 = alloca %Variable, align 8
+  %value447 = getelementptr %Variable, ptr %v446, i32 0, i32 0
+  store ptr null, ptr %value447, align 8
+  %type448 = getelementptr %Variable, ptr %v446, i32 0, i32 1
+  %976 = load ptr, ptr %struc_type, align 8
+  store ptr %976, ptr %type448, align 8
+  %stack_level449 = getelementptr %Variable, ptr %v446, i32 0, i32 4
+  store ptr null, ptr %stack_level449, align 8
+  %node450 = getelementptr %Variable, ptr %v446, i32 0, i32 2
+  %977 = load ptr, ptr %expression, align 8
+  store ptr %977, ptr %node450, align 8
+  %node_type451 = getelementptr %Variable, ptr %v446, i32 0, i32 3
+  %978 = load ptr, ptr %simple_type_node, align 8
+  store ptr %978, ptr %node_type451, align 8
+  %979 = load ptr, ptr %c, align 8
+  %980 = load %Variable, ptr %v446, align 8
+  %981 = call ptr @codegen_create_variable(ptr %979, %Variable %980)
+  ret ptr %981
+
+merge_block452:                                   ; preds = %merge_block419
+  %982 = load ptr, ptr %expression, align 8
+  %type453 = getelementptr %Node, ptr %982, i32 0, i32 0
+  %983 = load i64, ptr %type453, align 4
+  %984 = load i64, ptr @NODE_TYPE_SIMPLE_TYPE, align 4
+  %985 = icmp eq i64 %983, %984
+  br i1 %985, label %then_block454, label %merge_block465
+
+then_block454:                                    ; preds = %merge_block452
+  %986 = load ptr, ptr %expression, align 8
+  %data455 = getelementptr %Node, ptr %986, i32 0, i32 1
+  %987 = load ptr, ptr %data455, align 8
+  %988 = load %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %987, align 8
   %simple_type_data = alloca %NODE_TYPE_SIMPLE_TYPE_DATA, align 8
-  store %NODE_TYPE_SIMPLE_TYPE_DATA %939, ptr %simple_type_data, align 8
-  %940 = load ptr, ptr %c, align 8
-  %underlying_type432 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %simple_type_data, i32 0, i32 1
-  %941 = load ptr, ptr %underlying_type432, align 8
-  %942 = call ptr @codegen_get_llvm_type(ptr %940, ptr %941)
-  %typ433 = alloca ptr, align 8
-  store ptr %942, ptr %typ433, align 8
-  %943 = load ptr, ptr %typ433, align 8
-  %944 = icmp ne ptr %943, null
-  call void @assert(i1 %944)
-  %v434 = alloca %Variable, align 8
-  %value435 = getelementptr %Variable, ptr %v434, i32 0, i32 0
-  store ptr null, ptr %value435, align 8
-  %type436 = getelementptr %Variable, ptr %v434, i32 0, i32 1
-  %945 = load ptr, ptr %typ433, align 8
-  %946 = load ptr, ptr %945, align 8
-  store ptr %946, ptr %type436, align 8
-  %stack_level437 = getelementptr %Variable, ptr %v434, i32 0, i32 4
-  store ptr null, ptr %stack_level437, align 8
-  %node438 = getelementptr %Variable, ptr %v434, i32 0, i32 2
-  %947 = load ptr, ptr %expression, align 8
-  store ptr %947, ptr %node438, align 8
-  %node_type439 = getelementptr %Variable, ptr %v434, i32 0, i32 3
-  %underlying_type440 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %simple_type_data, i32 0, i32 1
-  %948 = load ptr, ptr %underlying_type440, align 8
-  store ptr %948, ptr %node_type439, align 8
-  %949 = load ptr, ptr %c, align 8
-  %950 = load %Variable, ptr %v434, align 8
-  %951 = call ptr @codegen_create_variable(ptr %949, %Variable %950)
-  ret ptr %951
-
-merge_block441:                                   ; preds = %merge_block428
-  %952 = load ptr, ptr %expression, align 8
-  %type442 = getelementptr %Node, ptr %952, i32 0, i32 0
-  %953 = load i64, ptr %type442, align 4
-  %954 = load i64, ptr @NODE_STRUCT_INSTANCIATION, align 4
-  %955 = icmp eq i64 %953, %954
-  br i1 %955, label %then_block443, label %merge_block449
-
-then_block443:                                    ; preds = %merge_block441
-  %956 = load ptr, ptr %expression, align 8
-  %data444 = getelementptr %Node, ptr %956, i32 0, i32 1
-  %957 = load ptr, ptr %data444, align 8
-  %958 = load %NODE_STRUCT_INSTANCIATION_DATA, ptr %957, align 8
-  %struc_data445 = alloca %NODE_STRUCT_INSTANCIATION_DATA, align 8
-  store %NODE_STRUCT_INSTANCIATION_DATA %958, ptr %struc_data445, align 8
-  %959 = load ptr, ptr %c, align 8
-  %environment446 = getelementptr %codegen, ptr %959, i32 0, i32 4
-  %960 = load ptr, ptr %environment446, align 8
-  %typ447 = getelementptr %NODE_STRUCT_INSTANCIATION_DATA, ptr %struc_data445, i32 0, i32 0
-  %961 = load ptr, ptr %typ447, align 8
-  %962 = call ptr @environment_get_variable(ptr %960, ptr %961)
-  %v448 = alloca ptr, align 8
-  store ptr %962, ptr %v448, align 8
-  %963 = load ptr, ptr %v448, align 8
-  %964 = icmp ne ptr %963, null
-  call void @assert(i1 %964)
-  %965 = load ptr, ptr %v448, align 8
-  ret ptr %965
-
-merge_block449:                                   ; preds = %merge_block441
-  %966 = load ptr, ptr %expression, align 8
-  %type450 = getelementptr %Node, ptr %966, i32 0, i32 0
-  %967 = load i64, ptr %type450, align 4
-  %968 = load i64, ptr @NODE_FIELD_ACCESS, align 4
-  %969 = icmp eq i64 %967, %968
-  br i1 %969, label %then_block451, label %merge_block467
-
-then_block451:                                    ; preds = %merge_block449
-  %970 = load ptr, ptr %expression, align 8
-  %data452 = getelementptr %Node, ptr %970, i32 0, i32 1
-  %971 = load ptr, ptr %data452, align 8
-  %972 = load %NODE_FIELD_ACCESS_DATA, ptr %971, align 8
+  store %NODE_TYPE_SIMPLE_TYPE_DATA %988, ptr %simple_type_data, align 8
+  %989 = load ptr, ptr %c, align 8
+  %underlying_type456 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %simple_type_data, i32 0, i32 1
+  %990 = load ptr, ptr %underlying_type456, align 8
+  %991 = call ptr @codegen_get_llvm_type(ptr %989, ptr %990)
+  %typ457 = alloca ptr, align 8
+  store ptr %991, ptr %typ457, align 8
+  %992 = load ptr, ptr %typ457, align 8
+  %993 = icmp ne ptr %992, null
+  call void @assert(i1 %993)
+  %v458 = alloca %Variable, align 8
+  %value459 = getelementptr %Variable, ptr %v458, i32 0, i32 0
+  store ptr null, ptr %value459, align 8
+  %type460 = getelementptr %Variable, ptr %v458, i32 0, i32 1
+  %994 = load ptr, ptr %typ457, align 8
+  %995 = load ptr, ptr %994, align 8
+  store ptr %995, ptr %type460, align 8
+  %stack_level461 = getelementptr %Variable, ptr %v458, i32 0, i32 4
+  store ptr null, ptr %stack_level461, align 8
+  %node462 = getelementptr %Variable, ptr %v458, i32 0, i32 2
+  %996 = load ptr, ptr %expression, align 8
+  store ptr %996, ptr %node462, align 8
+  %node_type463 = getelementptr %Variable, ptr %v458, i32 0, i32 3
+  %underlying_type464 = getelementptr %NODE_TYPE_SIMPLE_TYPE_DATA, ptr %simple_type_data, i32 0, i32 1
+  %997 = load ptr, ptr %underlying_type464, align 8
+  store ptr %997, ptr %node_type463, align 8
+  %998 = load ptr, ptr %c, align 8
+  %999 = load %Variable, ptr %v458, align 8
+  %1000 = call ptr @codegen_create_variable(ptr %998, %Variable %999)
+  ret ptr %1000
+
+merge_block465:                                   ; preds = %merge_block452
+  %1001 = load ptr, ptr %expression, align 8
+  %type466 = getelementptr %Node, ptr %1001, i32 0, i32 0
+  %1002 = load i64, ptr %type466, align 4
+  %1003 = load i64, ptr @NODE_STRUCT_INSTANCIATION, align 4
+  %1004 = icmp eq i64 %1002, %1003
+  br i1 %1004, label %then_block467, label %merge_block473
+
+then_block467:                                    ; preds = %merge_block465
+  %1005 = load ptr, ptr %expression, align 8
+  %data468 = getelementptr %Node, ptr %1005, i32 0, i32 1
+  %1006 = load ptr, ptr %data468, align 8
+  %1007 = load %NODE_STRUCT_INSTANCIATION_DATA, ptr %1006, align 8
+  %struc_data469 = alloca %NODE_STRUCT_INSTANCIATION_DATA, align 8
+  store %NODE_STRUCT_INSTANCIATION_DATA %1007, ptr %struc_data469, align 8
+  %1008 = load ptr, ptr %c, align 8
+  %environment470 = getelementptr %codegen, ptr %1008, i32 0, i32 4
+  %1009 = load ptr, ptr %environment470, align 8
+  %typ471 = getelementptr %NODE_STRUCT_INSTANCIATION_DATA, ptr %struc_data469, i32 0, i32 0
+  %1010 = load ptr, ptr %typ471, align 8
+  %1011 = call ptr @environment_get_variable(ptr %1009, ptr %1010)
+  %v472 = alloca ptr, align 8
+  store ptr %1011, ptr %v472, align 8
+  %1012 = load ptr, ptr %v472, align 8
+  %1013 = icmp ne ptr %1012, null
+  call void @assert(i1 %1013)
+  %1014 = load ptr, ptr %v472, align 8
+  ret ptr %1014
+
+merge_block473:                                   ; preds = %merge_block465
+  %1015 = load ptr, ptr %expression, align 8
+  %type474 = getelementptr %Node, ptr %1015, i32 0, i32 0
+  %1016 = load i64, ptr %type474, align 4
+  %1017 = load i64, ptr @NODE_FIELD_ACCESS, align 4
+  %1018 = icmp eq i64 %1016, %1017
+  br i1 %1018, label %then_block475, label %merge_block491
+
+then_block475:                                    ; preds = %merge_block473
+  %1019 = load ptr, ptr %expression, align 8
+  %data476 = getelementptr %Node, ptr %1019, i32 0, i32 1
+  %1020 = load ptr, ptr %data476, align 8
+  %1021 = load %NODE_FIELD_ACCESS_DATA, ptr %1020, align 8
   %field_access = alloca %NODE_FIELD_ACCESS_DATA, align 8
-  store %NODE_FIELD_ACCESS_DATA %972, ptr %field_access, align 8
-  %973 = load ptr, ptr %c, align 8
-  %expression453 = getelementptr %NODE_FIELD_ACCESS_DATA, ptr %field_access, i32 0, i32 0
-  %974 = load ptr, ptr %expression453, align 8
-  %name454 = getelementptr %NODE_FIELD_ACCESS_DATA, ptr %field_access, i32 0, i32 1
-  %975 = load ptr, ptr %name454, align 8
-  %976 = call ptr @codegen_get_struct_field(ptr %973, ptr %974, ptr %975)
-  %x455 = alloca ptr, align 8
-  store ptr %976, ptr %x455, align 8
-  %977 = load ptr, ptr %x455, align 8
-  %978 = icmp ne ptr %977, null
-  call void @assert(i1 %978)
-  %979 = load ptr, ptr %c, align 8
-  %980 = load ptr, ptr %x455, align 8
-  %type456 = getelementptr %StructField, ptr %980, i32 0, i32 1
-  %981 = load ptr, ptr %type456, align 8
-  %982 = call ptr @codegen_get_llvm_type(ptr %979, ptr %981)
-  %t457 = alloca ptr, align 8
-  store ptr %982, ptr %t457, align 8
-  %983 = load ptr, ptr %t457, align 8
-  %984 = icmp ne ptr %983, null
-  call void @assert(i1 %984)
-  %985 = load ptr, ptr %c, align 8
-  %builder458 = getelementptr %codegen, ptr %985, i32 0, i32 2
-  %986 = load ptr, ptr %builder458, align 8
-  %987 = load ptr, ptr %t457, align 8
-  %988 = load ptr, ptr %987, align 8
-  %989 = load ptr, ptr %x455, align 8
-  %value459 = getelementptr %StructField, ptr %989, i32 0, i32 0
-  %990 = load ptr, ptr %value459, align 8
-  %991 = call ptr @LLVMBuildLoad2(ptr %986, ptr %988, ptr %990, ptr @226)
+  store %NODE_FIELD_ACCESS_DATA %1021, ptr %field_access, align 8
+  %1022 = load ptr, ptr %c, align 8
+  %expression477 = getelementptr %NODE_FIELD_ACCESS_DATA, ptr %field_access, i32 0, i32 0
+  %1023 = load ptr, ptr %expression477, align 8
+  %name478 = getelementptr %NODE_FIELD_ACCESS_DATA, ptr %field_access, i32 0, i32 1
+  %1024 = load ptr, ptr %name478, align 8
+  %1025 = call ptr @codegen_get_struct_field(ptr %1022, ptr %1023, ptr %1024)
+  %x479 = alloca ptr, align 8
+  store ptr %1025, ptr %x479, align 8
+  %1026 = load ptr, ptr %x479, align 8
+  %1027 = icmp ne ptr %1026, null
+  call void @assert(i1 %1027)
+  %1028 = load ptr, ptr %c, align 8
+  %1029 = load ptr, ptr %x479, align 8
+  %type480 = getelementptr %StructField, ptr %1029, i32 0, i32 1
+  %1030 = load ptr, ptr %type480, align 8
+  %1031 = call ptr @codegen_get_llvm_type(ptr %1028, ptr %1030)
+  %t481 = alloca ptr, align 8
+  store ptr %1031, ptr %t481, align 8
+  %1032 = load ptr, ptr %t481, align 8
+  %1033 = icmp ne ptr %1032, null
+  call void @assert(i1 %1033)
+  %1034 = load ptr, ptr %c, align 8
+  %builder482 = getelementptr %codegen, ptr %1034, i32 0, i32 2
+  %1035 = load ptr, ptr %builder482, align 8
+  %1036 = load ptr, ptr %t481, align 8
+  %1037 = load ptr, ptr %1036, align 8
+  %1038 = load ptr, ptr %x479, align 8
+  %value483 = getelementptr %StructField, ptr %1038, i32 0, i32 0
+  %1039 = load ptr, ptr %value483, align 8
+  %1040 = call ptr @LLVMBuildLoad2(ptr %1035, ptr %1037, ptr %1039, ptr @228)
   %loaded = alloca ptr, align 8
-  store ptr %991, ptr %loaded, align 8
-  %v460 = alloca %Variable, align 8
-  %value461 = getelementptr %Variable, ptr %v460, i32 0, i32 0
-  %992 = load ptr, ptr %loaded, align 8
-  store ptr %992, ptr %value461, align 8
-  %type462 = getelementptr %Variable, ptr %v460, i32 0, i32 1
-  store ptr null, ptr %type462, align 8
-  %stack_level463 = getelementptr %Variable, ptr %v460, i32 0, i32 4
-  store ptr null, ptr %stack_level463, align 8
-  %node464 = getelementptr %Variable, ptr %v460, i32 0, i32 2
-  %993 = load ptr, ptr %expression, align 8
-  store ptr %993, ptr %node464, align 8
-  %node_type465 = getelementptr %Variable, ptr %v460, i32 0, i32 3
-  %994 = load ptr, ptr %x455, align 8
-  %type466 = getelementptr %StructField, ptr %994, i32 0, i32 1
-  %995 = load ptr, ptr %type466, align 8
-  store ptr %995, ptr %node_type465, align 8
-  %996 = load ptr, ptr %c, align 8
-  %997 = load %Variable, ptr %v460, align 8
-  %998 = call ptr @codegen_create_variable(ptr %996, %Variable %997)
-  ret ptr %998
-
-merge_block467:                                   ; preds = %merge_block449
-  %999 = load ptr, ptr %expression, align 8
-  %type468 = getelementptr %Node, ptr %999, i32 0, i32 0
-  %1000 = load i64, ptr %type468, align 4
-  call void (ptr, ...) @printf(ptr @227, i64 %1000)
+  store ptr %1040, ptr %loaded, align 8
+  %v484 = alloca %Variable, align 8
+  %value485 = getelementptr %Variable, ptr %v484, i32 0, i32 0
+  %1041 = load ptr, ptr %loaded, align 8
+  store ptr %1041, ptr %value485, align 8
+  %type486 = getelementptr %Variable, ptr %v484, i32 0, i32 1
+  store ptr null, ptr %type486, align 8
+  %stack_level487 = getelementptr %Variable, ptr %v484, i32 0, i32 4
+  store ptr null, ptr %stack_level487, align 8
+  %node488 = getelementptr %Variable, ptr %v484, i32 0, i32 2
+  %1042 = load ptr, ptr %expression, align 8
+  store ptr %1042, ptr %node488, align 8
+  %node_type489 = getelementptr %Variable, ptr %v484, i32 0, i32 3
+  %1043 = load ptr, ptr %x479, align 8
+  %type490 = getelementptr %StructField, ptr %1043, i32 0, i32 1
+  %1044 = load ptr, ptr %type490, align 8
+  store ptr %1044, ptr %node_type489, align 8
+  %1045 = load ptr, ptr %c, align 8
+  %1046 = load %Variable, ptr %v484, align 8
+  %1047 = call ptr @codegen_create_variable(ptr %1045, %Variable %1046)
+  ret ptr %1047
+
+merge_block491:                                   ; preds = %merge_block473
+  %1048 = load ptr, ptr %expression, align 8
+  %type492 = getelementptr %Node, ptr %1048, i32 0, i32 0
+  %1049 = load i64, ptr %type492, align 4
+  call void (ptr, ...) @printf(ptr @229, i64 %1049)
   call void @assert(i1 false)
   ret ptr null
 }
@@ -13825,7 +13983,7 @@ then_block16:                                     ; preds = %merge_block14
   %79 = load ptr, ptr %ltyp, align 8
   %80 = load ptr, ptr %79, align 8
   %81 = load ptr, ptr %ptr, align 8
-  %82 = call ptr @LLVMBuildLoad2(ptr %78, ptr %80, ptr %81, ptr @228)
+  %82 = call ptr @LLVMBuildLoad2(ptr %78, ptr %80, ptr %81, ptr @230)
   store ptr %82, ptr %ptr, align 8
   br label %merge_block18
 
@@ -14040,7 +14198,7 @@ then_block55:                                     ; preds = %merge_block53
 merge_block69:                                    ; preds = %merge_block53
   %type70 = getelementptr %Node, ptr %lhs1, i32 0, i32 0
   %184 = load i64, ptr %type70, align 4
-  call void (ptr, ...) @printf(ptr @229, i64 %184)
+  call void (ptr, ...) @printf(ptr @231, i64 %184)
   call void @assert(i1 false)
   ret i64 0
 }
@@ -14150,7 +14308,7 @@ then_block5:                                      ; preds = %then_block2
   %23 = load ptr, ptr %d4, align 8
   %name6 = getelementptr %NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, ptr %23, i32 0, i32 0
   %24 = load ptr, ptr %name6, align 8
-  call void (ptr, ...) @printf(ptr @230, ptr %24)
+  call void (ptr, ...) @printf(ptr @232, ptr %24)
   call void @assert(i1 false)
   br label %merge_block7
 
@@ -14258,7 +14416,7 @@ entrypoint:
   %11 = load ptr, ptr %c, align 8
   %current_function = getelementptr %codegen, ptr %11, i32 0, i32 7
   %12 = load ptr, ptr %current_function, align 8
-  %13 = call ptr @LLVMAppendBasicBlock(ptr %12, ptr @234)
+  %13 = call ptr @LLVMAppendBasicBlock(ptr %12, ptr @236)
   %then_block = alloca ptr, align 8
   store ptr %13, ptr %then_block, align 8
   %14 = load ptr, ptr %c, align 8
@@ -14304,7 +14462,7 @@ outer_block:                                      ; preds = %while_block
   %33 = load ptr, ptr %c, align 8
   %current_function2 = getelementptr %codegen, ptr %33, i32 0, i32 7
   %34 = load ptr, ptr %current_function2, align 8
-  %35 = call ptr @LLVMAppendBasicBlock(ptr %34, ptr @235)
+  %35 = call ptr @LLVMAppendBasicBlock(ptr %34, ptr @237)
   %merge_block = alloca ptr, align 8
   store ptr %35, ptr %merge_block, align 8
   %36 = load ptr, ptr %c, align 8
@@ -14380,7 +14538,7 @@ entrypoint:
   %2 = load ptr, ptr %c, align 8
   %current_function = getelementptr %codegen, ptr %2, i32 0, i32 7
   %3 = load ptr, ptr %current_function, align 8
-  %4 = call ptr @LLVMAppendBasicBlock(ptr %3, ptr @236)
+  %4 = call ptr @LLVMAppendBasicBlock(ptr %3, ptr @238)
   %whil_block = alloca ptr, align 8
   store ptr %4, ptr %whil_block, align 8
   %5 = load ptr, ptr %c, align 8
@@ -14406,13 +14564,13 @@ entrypoint:
   %18 = load ptr, ptr %c, align 8
   %current_function2 = getelementptr %codegen, ptr %18, i32 0, i32 7
   %19 = load ptr, ptr %current_function2, align 8
-  %20 = call ptr @LLVMAppendBasicBlock(ptr %19, ptr @237)
+  %20 = call ptr @LLVMAppendBasicBlock(ptr %19, ptr @239)
   %inner_block = alloca ptr, align 8
   store ptr %20, ptr %inner_block, align 8
   %21 = load ptr, ptr %c, align 8
   %current_function3 = getelementptr %codegen, ptr %21, i32 0, i32 7
   %22 = load ptr, ptr %current_function3, align 8
-  %23 = call ptr @LLVMAppendBasicBlock(ptr %22, ptr @238)
+  %23 = call ptr @LLVMAppendBasicBlock(ptr %22, ptr @240)
   %outer_block = alloca ptr, align 8
   store ptr %23, ptr %outer_block, align 8
   %24 = load ptr, ptr %c, align 8
@@ -14584,7 +14742,7 @@ then_block:                                       ; preds = %entrypoint
   %llvm_module1 = getelementptr %codegen, ptr %5, i32 0, i32 0
   %6 = load ptr, ptr %llvm_module1, align 8
   %7 = load ptr, ptr %message, align 8
-  %8 = call i64 @LLVMPrintModuleToFile(ptr %6, ptr @240, ptr %7)
+  %8 = call i64 @LLVMPrintModuleToFile(ptr %6, ptr @242, ptr %7)
   ret i64 0
 
 merge_block:                                      ; preds = %entrypoint
@@ -14610,7 +14768,7 @@ merge_block:                                      ; preds = %entrypoint
 then_block2:                                      ; preds = %merge_block
   %19 = load ptr, ptr %message, align 8
   %20 = load ptr, ptr %19, align 8
-  call void (ptr, ...) @printf(ptr @241, ptr %20)
+  call void (ptr, ...) @printf(ptr @243, ptr %20)
   %21 = load ptr, ptr %message, align 8
   %22 = load ptr, ptr %21, align 8
   call void @LLVMDisposeMessage(ptr %22)
@@ -14623,7 +14781,7 @@ merge_block3:                                     ; preds = %merge_block, %then_
   %26 = load i64, ptr @LLVMCodeGenLevelDefault, align 4
   %27 = load i64, ptr @LLVMRelocDefault, align 4
   %28 = load i64, ptr @LLVMCodeModelDefault, align 4
-  %29 = call ptr @LLVMCreateTargetMachine(ptr %24, ptr %25, ptr @242, ptr @243, i64 %26, i64 %27, i64 %28)
+  %29 = call ptr @LLVMCreateTargetMachine(ptr %24, ptr %25, ptr @244, ptr @245, i64 %26, i64 %27, i64 %28)
   %target_machine = alloca ptr, align 8
   store ptr %29, ptr %target_machine, align 8
   %30 = load ptr, ptr %triple, align 8
@@ -14642,7 +14800,7 @@ merge_block3:                                     ; preds = %merge_block, %then_
 then_block5:                                      ; preds = %merge_block3
   %38 = load ptr, ptr %message, align 8
   %39 = load ptr, ptr %38, align 8
-  call void (ptr, ...) @printf(ptr @244, ptr %39)
+  call void (ptr, ...) @printf(ptr @246, ptr %39)
   %40 = load ptr, ptr %message, align 8
   %41 = load ptr, ptr %40, align 8
   call void @LLVMDisposeMessage(ptr %41)
@@ -14650,7 +14808,7 @@ then_block5:                                      ; preds = %merge_block3
 
 merge_block6:                                     ; preds = %merge_block3, %then_block5
   %filename = alloca ptr, align 8
-  store ptr @245, ptr %filename, align 8
+  store ptr @247, ptr %filename, align 8
   %42 = load ptr, ptr %target_machine, align 8
   %43 = load ptr, ptr %c, align 8
   %llvm_module7 = getelementptr %codegen, ptr %43, i32 0, i32 0
@@ -14661,7 +14819,7 @@ merge_block6:                                     ; preds = %merge_block3, %then
   %48 = load ptr, ptr %target_machine, align 8
   call void @LLVMDisposeTargetMachine(ptr %48)
   %49 = load ptr, ptr %filename, align 8
-  call void (ptr, ...) @printf(ptr @246, ptr %49)
+  call void (ptr, ...) @printf(ptr @248, ptr %49)
   ret i64 0
 }
 
@@ -14688,7 +14846,7 @@ entrypoint:
   %alloc = alloca ptr, align 8
   store ptr %1, ptr %alloc, align 8
   %2 = load ptr, ptr %filename, align 8
-  %3 = call ptr @fopen(ptr %2, ptr @247)
+  %3 = call ptr @fopen(ptr %2, ptr @249)
   %file = alloca ptr, align 8
   store ptr %3, ptr %file, align 8
   %4 = load ptr, ptr %file, align 8
@@ -14739,7 +14897,7 @@ entrypoint:
   br i1 %3, label %then_block, label %merge_block
 
 then_block:                                       ; preds = %entrypoint
-  call void (ptr, ...) @printf(ptr @248)
+  call void (ptr, ...) @printf(ptr @250)
   ret i64 1
 
 merge_block:                                      ; preds = %entrypoint
@@ -14769,12 +14927,12 @@ inner_block:                                      ; preds = %while_block
   %arg = alloca ptr, align 8
   store ptr %13, ptr %arg, align 8
   %14 = load ptr, ptr %arg, align 8
-  %15 = call i1 @strcmp(ptr %14, ptr @249)
+  %15 = call i1 @strcmp(ptr %14, ptr @251)
   br i1 %15, label %then_block1, label %merge_block2
 
 outer_block:                                      ; preds = %while_block
   %16 = load ptr, ptr %filename, align 8
-  call void (ptr, ...) @printf(ptr @250, ptr %16)
+  call void (ptr, ...) @printf(ptr @252, ptr %16)
   %17 = call ptr @arena_init(i64 1073741824)
   %alloc = alloca ptr, align 8
   store ptr %17, ptr %alloc, align 8
diff --git a/grammar.ebnf b/grammar.ebnf
index 48667b2..d246838 100644
--- a/grammar.ebnf
+++ b/grammar.ebnf
@@ -18,13 +18,15 @@ ReturnStatement ::= RETURN (Expression)?
 
 FunctionArguments ::= Expression ("," Expression)*
 
-Expression ::= EqualityExpression | AdditiveExpression
+Expression ::= LogicalExpression
 
 CastStatement ::= "cast" LPAREN TYPE "," Expression RPAREN
-    
+
 SizeOfStatement ::= "sizeof" LPAREN TYPE RPAREN
 
-EqualityExpression ::= AdditiveExpression ("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression
+LogicalExpression ::= EqualityExpression (("and" | "or") EqualityExpression)*
+
+EqualityExpression ::= AdditiveExpression (("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression)*
 
 AdditiveExpression ::= MultiplicativeExpression (("+" | "-") MultiplicativeExpression)*
 
diff --git a/src/codegen.pry b/src/codegen.pry
index cb054ec..4c257b8 100644
--- a/src/codegen.pry
+++ b/src/codegen.pry
@@ -722,6 +722,27 @@ let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *
 		return codegen_create_variable(c, v);
 	};
 	
+	if ((*expression).type == NODE_LOGICAL_EXPRESSION) {
+		let exp = (*(cast(*NODE_LOGICAL_EXPRESSION_DATA, (*expression).data)));
+		let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null));
+		assert(lhs_value != cast(*Variable, null));
+		let rhs_value = codegen_generate_expression_value(c, exp.rhs, cast(*i8, null));
+		assert(rhs_value != cast(*Variable, null));
+		
+		assert(compare_types(c, (*lhs_value).node_type, (*rhs_value).node_type, false));
+
+		let result = cast(LLVMValueRef, null);
+		if exp.an {
+			result = LLVMBuildAnd((*c).builder, (*lhs_value).value, (*rhs_value).value, "");
+		};
+		if !exp.an {
+			result = LLVMBuildOr((*c).builder, (*lhs_value).value, (*rhs_value).value, "");
+		};
+		assert(result != cast(LLVMValueRef, null));
+
+		return codegen_generate_literal(c, result, name, expression, (*lhs_value).node_type);
+	};
+	
 	if ((*expression).type == NODE_EQUALITY_EXPRESSION) {
 		let exp = (*(cast(*NODE_EQUALITY_EXPRESSION_DATA, (*expression).data)));
 		let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null));
diff --git a/src/llvm.pry b/src/llvm.pry
index 2feb815..6608372 100644
--- a/src/llvm.pry
+++ b/src/llvm.pry
@@ -329,6 +329,8 @@ extern LLVMBuildAdd = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMV
 extern LLVMBuildMul = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
 extern LLVMBuildSDiv = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
 extern LLVMBuildSRem = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
+extern LLVMBuildAnd = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
+extern LLVMBuildOr = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef;
 
 extern LLVMBuildGEP2 = (LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, *LLVMValueRef, i64, *i8) => LLVMValueRef;
 extern LLVMAddGlobal = (LLVMModuleRef, LLVMTypeRef, *i8) => LLVMValueRef;
diff --git a/src/parser.pry b/src/parser.pry
index 0b448d0..1e7ff56 100644
--- a/src/parser.pry
+++ b/src/parser.pry
@@ -31,6 +31,7 @@ let NODE_IMPORT_DECLARATION = 4;
 let NODE_FUNCTION_CALL_STATEMENT = 5;
 let NODE_IF_STATEMENT = 6;
 let NODE_WHILE_STATEMENT = 7;
+let NODE_LOGICAL_EXPRESSION = 31;
 let NODE_EQUALITY_EXPRESSION = 8;
 let NODE_ADDITIVE_EXPRESSION = 9;
 let NODE_MULTIPLICATIVE_EXPRESSION = 10;
@@ -109,6 +110,12 @@ let NODE_WHILE_STATEMENT_DATA = struct {
     statements_len: i64,
 };
 
+let NODE_LOGICAL_EXPRESSION_DATA = struct {
+    lhs: *Node,
+    rhs: *Node,
+    an: bool,
+};
+
 let NODE_EQUALITY_EXPRESSION_DATA = struct {
     lhs: *Node,
     rhs: *Node,
@@ -897,107 +904,107 @@ let parser_parse_primary_expression = (p: *parser) => *Node {
 	return cast(*Node, null);
 };
 
-/* EqualityExpression ::= AdditiveExpression ("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression */
+/* EqualityExpression ::= AdditiveExpression (("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression)* */
 let parser_parse_equality_expression = (p: *parser) => *Node {
 	let lhs = parser_parse_additive_expression(p);
 	if lhs == cast(*Node, null) {
 	    return cast(*Node, null);
 	};	
 
-	let typ = -1;
-	let ex = parser_accept_parse(p, (ip: *parser) => *Node {
-		if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) {
-			return cast(*Node, null);
-		};
-		if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) {
-			return cast(*Node, null);
-		};
-		let n = Node{};
-		return create_node(ip, n);
-	});
-	if ex != cast(*Node, null) {
-		typ = EQUALITY_EXPRESSION_TYPE_EQ;
-	};
-
-	if (typ == -1) {
-		ex = parser_accept_parse(p, (ip: *parser) => *Node {
-			if (parser_accept_token(ip, TOKEN_BANG) == cast(*token, null)) {
+	while true {
+		let typ = -1;
+		let ex = parser_accept_parse(p, (ip: *parser) => *Node {
+			if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) {
 				return cast(*Node, null);
 			};
-			if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
+			if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) {
 				return cast(*Node, null);
 			};
 			let n = Node{};
 			return create_node(ip, n);
 		});
-		if (ex != cast(*Node, null)) {
-			typ = EQUALITY_EXPRESSION_TYPE_NE;
+		if ex != cast(*Node, null) {
+			typ = EQUALITY_EXPRESSION_TYPE_EQ;
 		};
-	};
 
-	if (typ == -1) {
-		ex = parser_accept_parse(p, (ip: *parser) => *Node {
-			if (parser_accept_token(ip, TOKEN_LESS) == cast(*token, null)) {
-				return cast(*Node, null);
-			};
-			if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
-				return cast(*Node, null);
+		if (typ == -1) {
+			ex = parser_accept_parse(p, (ip: *parser) => *Node {
+				if (parser_accept_token(ip, TOKEN_BANG) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				let n = Node{};
+				return create_node(ip, n);
+			});
+			if (ex != cast(*Node, null)) {
+				typ = EQUALITY_EXPRESSION_TYPE_NE;
 			};
-			let n = Node{};
-			return create_node(ip, n);
-		});
-		if (ex != cast(*Node, null)) {
-			typ = EQUALITY_EXPRESSION_TYPE_LE;
 		};
-	};
 
-	if (typ == -1) {
-		ex = parser_accept_parse(p, (ip: *parser) => *Node {
-			if (parser_accept_token(ip, TOKEN_GREATER) == cast(*token, null)) {
-				return cast(*Node, null);
+		if (typ == -1) {
+			ex = parser_accept_parse(p, (ip: *parser) => *Node {
+				if (parser_accept_token(ip, TOKEN_LESS) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				let n = Node{};
+				return create_node(ip, n);
+			});
+			if (ex != cast(*Node, null)) {
+				typ = EQUALITY_EXPRESSION_TYPE_LE;
 			};
-			if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
-				return cast(*Node, null);
+		};
+
+		if (typ == -1) {
+			ex = parser_accept_parse(p, (ip: *parser) => *Node {
+				if (parser_accept_token(ip, TOKEN_GREATER) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) {
+					return cast(*Node, null);
+				};
+				let n = Node{};
+				return create_node(ip, n);
+			});
+			if (ex != cast(*Node, null)) {
+				typ = EQUALITY_EXPRESSION_TYPE_GE;
 			};
-			let n = Node{};
-			return create_node(ip, n);
-		});
-		if (ex != cast(*Node, null)) {
-			typ = EQUALITY_EXPRESSION_TYPE_GE;
 		};
-	};
 
-	if (typ == -1) {
-		if (parser_accept_token(p, TOKEN_LESS) != cast(*token, null)) {
+		if (typ == -1 and parser_accept_token(p, TOKEN_LESS) != cast(*token, null)) {
 			typ = EQUALITY_EXPRESSION_TYPE_LT;
 		};
-	};
 
-	if (typ == -1) {
-		if (parser_accept_token(p, TOKEN_GREATER) != cast(*token, null)) {
+		if (typ == -1 and parser_accept_token(p, TOKEN_GREATER) != cast(*token, null)) {
 			typ = EQUALITY_EXPRESSION_TYPE_GT;
 		};
-	};
 
-	if typ == -1 {
-		return cast(*Node, null);
-	};
-	
-	let rhs = parser_parse_additive_expression(p);
-	if rhs == cast(*Node, null) {
-	    return cast(*Node, null);
-	};	
-	
-	let d = cast(*NODE_EQUALITY_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_EQUALITY_EXPRESSION_DATA)));
-	(*d).lhs = lhs;
-	(*d).rhs = rhs;
-	(*d).typ = typ;
+		if typ == -1 {
+			break;
+		};
+		
+		let rhs = parser_parse_additive_expression(p);
+		if rhs == cast(*Node, null) {
+		    return cast(*Node, null);
+		};	
+		
+		let d = cast(*NODE_EQUALITY_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_EQUALITY_EXPRESSION_DATA)));
+		(*d).lhs = lhs;
+		(*d).rhs = rhs;
+		(*d).typ = typ;
 
-	let n = Node{};
-	n.type = NODE_EQUALITY_EXPRESSION ;
-	n.data = cast(*void, d);
+		let n = Node{};
+		n.type = NODE_EQUALITY_EXPRESSION ;
+		n.data = cast(*void, d);
 
-	return create_node(p, n); 
+		lhs = create_node(p, n);
+	};
+
+	return lhs; 
 };
 
 /* PostfixExpression ::= PrimaryExpression (CastStatement | SizeOfStatement | FunctionCallStatement | FieldAccess )* */
@@ -1027,15 +1034,11 @@ let parser_parse_unary_expression = (p: *parser) => *Node {
 	if parser_accept_token(p, TOKEN_BANG) != cast(*token, null) {
 	    typ = UNARY_EXPRESSION_TYPE_NOT;
 	};
-	if typ == -1 {
-		if parser_accept_token(p, TOKEN_MINUS) != cast(*token, null) {
-		    typ = UNARY_EXPRESSION_TYPE_MINUS;
-		};
+	if typ == -1 and parser_accept_token(p, TOKEN_MINUS) != cast(*token, null) {
+	    typ = UNARY_EXPRESSION_TYPE_MINUS;
 	};
-	if typ == -1 {
-		if parser_accept_token(p, TOKEN_MUL) != cast(*token, null) {
-		    typ = UNARY_EXPRESSION_TYPE_STAR;
-		};
+	if typ == -1 and parser_accept_token(p, TOKEN_MUL) != cast(*token, null) {
+	    typ = UNARY_EXPRESSION_TYPE_STAR;
 	};
 	if typ == -1 {
 		return parser_parse_postfix_expression(p);
@@ -1104,10 +1107,8 @@ let parser_parse_additive_expression = (p: *parser) => *Node {
 		let plus = parser_accept_token(p, TOKEN_PLUS);
 		let minus = parser_accept_token(p, TOKEN_MINUS);
 
-		if plus == cast(*token, null) {
-			if minus == cast(*token, null) {
-				break;
-			};
+		if plus == cast(*token, null) and minus == cast(*token, null) {
+			break;
 		};
 
 		let rhs = parser_parse_multiplicative_expression(p);
@@ -1127,18 +1128,41 @@ let parser_parse_additive_expression = (p: *parser) => *Node {
 	return lhs;
 };
 
-/* Expression ::= EqualityExpression | AdditiveExpression */
-let parser_parse_expression = (p: *parser) => *Node {
-	let ex = parser_accept_parse(p, parser_parse_equality_expression);
-	if ex != cast(*Node, null) {
-		return ex;
+/* LogicalExpression ::= EqualityExpression (("and" | "or") EqualityExpression)* */
+let parser_parse_logical_expression = (p: *parser) => *Node {
+	let lhs = parser_parse_equality_expression(p);
+	if lhs == cast(*Node, null) {
+		return cast(*Node, null);
 	};
-	let ax = parser_accept_parse(p, parser_parse_additive_expression);
-	if ax != cast(*Node, null) {
-		return ax;
+
+	while true {
+		let an = parser_accept_token(p, TOKEN_AND);
+		let o = parser_accept_token(p, TOKEN_OR);
+
+		if an == cast(*token, null) and o == cast(*token, null) {
+			break;
+		};
+
+		let rhs = parser_parse_equality_expression(p);
+		if rhs == cast(*Node, null) {
+			return cast(*Node, null);
+		};
+
+		let new_lhs_data = cast(*NODE_LOGICAL_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_LOGICAL_EXPRESSION_DATA)));
+		((*new_lhs_data).an) = an != cast(*token, null);
+		((*new_lhs_data).lhs) = lhs;
+		((*new_lhs_data).rhs) = rhs;
+		let new_lhs = Node{};
+		new_lhs.type = NODE_LOGICAL_EXPRESSION;
+		new_lhs.data = cast(*void, new_lhs_data);
+		lhs = create_node(p, new_lhs);
 	};
+	return lhs;
+};
 
-	return cast(*Node, null);
+/* Expression ::= LogicalExpression */
+let parser_parse_expression = (p: *parser) => *Node {
+	return parser_parse_logical_expression(p);
 };
 
 /* AssignmentStatement ::= ("let")? ("*")? Expression EQUALS Expression */
diff --git a/src/tokenizer.pry b/src/tokenizer.pry
index ddc2cef..c809420 100644
--- a/src/tokenizer.pry
+++ b/src/tokenizer.pry
@@ -18,6 +18,8 @@ let TOKEN_CONTINUE   = 8;
 let TOKEN_ARROW      = 9;
 let TOKEN_STRUCT     = 10;
 let TOKEN_TYPE       = 34;
+let TOKEN_AND        = 35;
+let TOKEN_OR         = 36;
 
 /* Identifiers */
 let TOKEN_IDENTIFIER = 11;
@@ -101,6 +103,12 @@ let print_tokens = (ts: *token, ts_len: i64) => i64 {
 		if (to.type == TOKEN_TYPE) {
 			printf("Type\n");
 		};
+		if (to.type == TOKEN_AND) {
+			printf("And\n");
+		};
+		if (to.type == TOKEN_OR) {
+			printf("Or\n");
+		};
 		if (to.type == TOKEN_IDENTIFIER) {
 			printf("Identifier: %s\n", cast(*i8, to.data));
 		};
@@ -398,6 +406,14 @@ let tokenizer_next = (t: *tokenizer) => *token {
 	    (*to).type = TOKEN_TYPE;
 	    return to;
 	};
+	if tokenizer_accept_string(t, "and") {
+	    (*to).type = TOKEN_AND;
+	    return to;
+	};
+	if tokenizer_accept_string(t, "or") {
+	    (*to).type = TOKEN_OR;
+	    return to;
+	};
 
 	if tokenizer_accept_string(t, "=>") {
 	    (*to).type = TOKEN_ARROW;