Created
April 29, 2025 12:24
-
-
Save kkestell/577f9c2c4bbe1bb1c5c4b3db272b0bb6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/home/kyle/src/pl/fern/.venv/bin/python -m src.fern.main examples/test.fern | |
═ Source Code ═════════════════════════════════════════════════════════════════ | |
def check_positive_product(x: int, y: int): bool { | |
var product: int = x * y; | |
var is_positive: bool = product > 0; | |
return is_positive; | |
} | |
def process_values(a: int, b: int): int { | |
var sum: int = a + b; | |
var are_equal: bool = a == b; | |
var result: int; | |
if (are_equal) { | |
result = 0; | |
} else if (sum > 10) { | |
if (check_positive_product(a, b)) { | |
result = sum * 2; | |
} else { | |
result = sum; | |
} | |
} else { | |
var diff: int = a - b; | |
result = -diff; | |
} | |
return result; | |
} | |
def main(): int { | |
var val1: int = 5; | |
var val2: int = 7; | |
var outcome: int = process_values(val1, val2); | |
var another_outcome: int = process_values(3, 3); | |
return outcome - another_outcome; | |
} | |
═ AST ═════════════════════════════════════════════════════════════════════════ | |
{ | |
"functions": [ | |
{ | |
"name": "check_positive_product", | |
"parameters": [ | |
{ | |
"name": "x", | |
"type": { | |
"name": "int" | |
} | |
}, | |
{ | |
"name": "y", | |
"type": { | |
"name": "int" | |
} | |
} | |
], | |
"return_type": { | |
"name": "bool" | |
}, | |
"body": { | |
"statements": [ | |
{ | |
"name": "product", | |
"type": { | |
"name": "int" | |
}, | |
"initial_value": { | |
"operator": "MULTIPLY", | |
"left": { | |
"name": "x" | |
}, | |
"right": { | |
"name": "y" | |
} | |
} | |
}, | |
{ | |
"name": "is_positive", | |
"type": { | |
"name": "bool" | |
}, | |
"initial_value": { | |
"operator": "GREATER", | |
"left": { | |
"name": "product" | |
}, | |
"right": { | |
"value": 0 | |
} | |
} | |
}, | |
{ | |
"expression": { | |
"name": "is_positive" | |
} | |
} | |
] | |
} | |
}, | |
{ | |
"name": "process_values", | |
"parameters": [ | |
{ | |
"name": "a", | |
"type": { | |
"name": "int" | |
} | |
}, | |
{ | |
"name": "b", | |
"type": { | |
"name": "int" | |
} | |
} | |
], | |
"return_type": { | |
"name": "int" | |
}, | |
"body": { | |
"statements": [ | |
{ | |
"name": "sum", | |
"type": { | |
"name": "int" | |
}, | |
"initial_value": { | |
"operator": "ADD", | |
"left": { | |
"name": "a" | |
}, | |
"right": { | |
"name": "b" | |
} | |
} | |
}, | |
{ | |
"name": "are_equal", | |
"type": { | |
"name": "bool" | |
}, | |
"initial_value": { | |
"operator": "EQUAL", | |
"left": { | |
"name": "a" | |
}, | |
"right": { | |
"name": "b" | |
} | |
} | |
}, | |
{ | |
"name": "result", | |
"type": { | |
"name": "int" | |
}, | |
"initial_value": null | |
}, | |
{ | |
"condition": { | |
"name": "are_equal" | |
}, | |
"then_block": { | |
"statements": [ | |
{ | |
"name": "result", | |
"expression": { | |
"value": 0 | |
} | |
} | |
] | |
}, | |
"else_block": { | |
"condition": { | |
"operator": "GREATER", | |
"left": { | |
"name": "sum" | |
}, | |
"right": { | |
"value": 10 | |
} | |
}, | |
"then_block": { | |
"statements": [ | |
{ | |
"condition": { | |
"name": "check_positive_product", | |
"arguments": [ | |
{ | |
"name": "a" | |
}, | |
{ | |
"name": "b" | |
} | |
] | |
}, | |
"then_block": { | |
"statements": [ | |
{ | |
"name": "result", | |
"expression": { | |
"operator": "MULTIPLY", | |
"left": { | |
"name": "sum" | |
}, | |
"right": { | |
"value": 2 | |
} | |
} | |
} | |
] | |
}, | |
"else_block": { | |
"statements": [ | |
{ | |
"name": "result", | |
"expression": { | |
"name": "sum" | |
} | |
} | |
] | |
} | |
} | |
] | |
}, | |
"else_block": { | |
"statements": [ | |
{ | |
"name": "diff", | |
"type": { | |
"name": "int" | |
}, | |
"initial_value": { | |
"operator": "SUBTRACT", | |
"left": { | |
"name": "a" | |
}, | |
"right": { | |
"name": "b" | |
} | |
} | |
}, | |
{ | |
"name": "result", | |
"expression": { | |
"operator": "NEGATE", | |
"operand": { | |
"name": "diff" | |
} | |
} | |
} | |
] | |
} | |
} | |
}, | |
{ | |
"expression": { | |
"name": "result" | |
} | |
} | |
] | |
} | |
}, | |
{ | |
"name": "main", | |
"parameters": [], | |
"return_type": { | |
"name": "int" | |
}, | |
"body": { | |
"statements": [ | |
{ | |
"name": "val1", | |
"type": { | |
"name": "int" | |
}, | |
"initial_value": { | |
"value": 5 | |
} | |
}, | |
{ | |
"name": "val2", | |
"type": { | |
"name": "int" | |
}, | |
"initial_value": { | |
"value": 7 | |
} | |
}, | |
{ | |
"name": "outcome", | |
"type": { | |
"name": "int" | |
}, | |
"initial_value": { | |
"name": "process_values", | |
"arguments": [ | |
{ | |
"name": "val1" | |
}, | |
{ | |
"name": "val2" | |
} | |
] | |
} | |
}, | |
{ | |
"name": "another_outcome", | |
"type": { | |
"name": "int" | |
}, | |
"initial_value": { | |
"name": "process_values", | |
"arguments": [ | |
{ | |
"value": 3 | |
}, | |
{ | |
"value": 3 | |
} | |
] | |
} | |
}, | |
{ | |
"expression": { | |
"operator": "SUBTRACT", | |
"left": { | |
"name": "outcome" | |
}, | |
"right": { | |
"name": "another_outcome" | |
} | |
} | |
} | |
] | |
} | |
} | |
] | |
} | |
═ Symbol Table ════════════════════════════════════════════════════════════════ | |
check_positive_product(x: int, y: int) -> bool | |
process_values(a: int, b: int) -> int | |
main() -> int | |
→ | |
x: int | |
y: int | |
→ | |
product: int | |
is_positive: bool | |
← | |
← | |
→ | |
a: int | |
b: int | |
→ | |
sum: int | |
are_equal: bool | |
result: int | |
→ | |
← | |
← | |
← | |
→ | |
→ | |
val1: int | |
val2: int | |
outcome: int | |
another_outcome: int | |
← | |
← | |
═ Three-Address Code ══════════════════════════════════════════════════════════ | |
procedure check_positive_product(x: int, y: int) -> bool: | |
bb1: | |
t1 = x * y | |
product = t1 | |
t2 = product > 0 | |
is_positive = t2 | |
return is_positive | |
t3 = 0 | |
return t3 | |
procedure process_values(a: int, b: int) -> int: | |
bb2: | |
t4 = a + b | |
sum = t4 | |
t5 = a == b | |
are_equal = t5 | |
result = 0 | |
if are_equal goto bb3 else goto bb4 | |
bb3: | |
result = 0 | |
goto bb5 | |
bb4: | |
t6 = sum > 10 | |
if t6 goto bb6 else goto bb7 | |
bb5: | |
return result | |
t11 = 0 | |
return t11 | |
bb6: | |
t7 = check_positive_product(a, b) | |
if t7 goto bb9 else goto bb10 | |
bb7: | |
t9 = a - b | |
diff = t9 | |
t10 = -diff | |
result = t10 | |
goto bb8 | |
bb8: | |
goto bb5 | |
bb9: | |
t8 = sum * 2 | |
result = t8 | |
goto bb11 | |
bb10: | |
result = sum | |
goto bb11 | |
bb11: | |
goto bb8 | |
procedure main() -> int: | |
bb12: | |
val1 = 5 | |
val2 = 7 | |
t12 = process_values(val1, val2) | |
outcome = t12 | |
t13 = process_values(3, 3) | |
another_outcome = t13 | |
t14 = outcome - another_outcome | |
return t14 | |
t15 = 0 | |
return t15 | |
═ Three-Address Code (After Dead Code Elimination) ════════════════════════════ | |
procedure check_positive_product(x: int, y: int) -> bool: | |
bb1: | |
t1 = x * y | |
product = t1 | |
t2 = product > 0 | |
is_positive = t2 | |
return is_positive | |
procedure process_values(a: int, b: int) -> int: | |
bb2: | |
t4 = a + b | |
sum = t4 | |
t5 = a == b | |
are_equal = t5 | |
result = 0 | |
if are_equal goto bb3 else goto bb4 | |
bb3: | |
result = 0 | |
goto bb5 | |
bb4: | |
t6 = sum > 10 | |
if t6 goto bb6 else goto bb7 | |
bb5: | |
return result | |
bb6: | |
t7 = check_positive_product(a, b) | |
if t7 goto bb9 else goto bb10 | |
bb7: | |
t9 = a - b | |
diff = t9 | |
t10 = -diff | |
result = t10 | |
goto bb8 | |
bb8: | |
goto bb5 | |
bb9: | |
t8 = sum * 2 | |
result = t8 | |
goto bb11 | |
bb10: | |
result = sum | |
goto bb11 | |
bb11: | |
goto bb8 | |
procedure main() -> int: | |
bb12: | |
val1 = 5 | |
val2 = 7 | |
t12 = process_values(val1, val2) | |
outcome = t12 | |
t13 = process_values(3, 3) | |
another_outcome = t13 | |
t14 = outcome - another_outcome | |
return t14 | |
═ Control Flow Graphs ═════════════════════════════════════════════════════════ | |
check_positive_product: | |
entry: bb1, exit: bb1 | |
block bb1: | |
flags: entry, exit | |
predecessors: [] | |
successors: [] | |
instructions: | |
t1 = x * y | |
product = t1 | |
t2 = product > 0 | |
is_positive = t2 | |
return is_positive | |
process_values: | |
entry: bb2, exit: bb5 | |
block bb2: | |
flags: entry | |
predecessors: [] | |
successors: ['bb3', 'bb4'] | |
instructions: | |
t4 = a + b | |
sum = t4 | |
t5 = a == b | |
are_equal = t5 | |
result = 0 | |
if are_equal goto bb3 else goto bb4 | |
block bb3: | |
predecessors: ['bb2'] | |
successors: ['bb5'] | |
instructions: | |
result = 0 | |
goto bb5 | |
block bb4: | |
predecessors: ['bb2'] | |
successors: ['bb6', 'bb7'] | |
instructions: | |
t6 = sum > 10 | |
if t6 goto bb6 else goto bb7 | |
block bb5: | |
flags: exit | |
predecessors: ['bb3', 'bb8'] | |
successors: [] | |
instructions: | |
return result | |
block bb6: | |
predecessors: ['bb4'] | |
successors: ['bb10', 'bb9'] | |
instructions: | |
t7 = check_positive_product(a, b) | |
if t7 goto bb9 else goto bb10 | |
block bb7: | |
predecessors: ['bb4'] | |
successors: ['bb8'] | |
instructions: | |
t9 = a - b | |
diff = t9 | |
t10 = -diff | |
result = t10 | |
goto bb8 | |
block bb8: | |
predecessors: ['bb11', 'bb7'] | |
successors: ['bb5'] | |
instructions: | |
goto bb5 | |
block bb9: | |
predecessors: ['bb6'] | |
successors: ['bb11'] | |
instructions: | |
t8 = sum * 2 | |
result = t8 | |
goto bb11 | |
block bb10: | |
predecessors: ['bb6'] | |
successors: ['bb11'] | |
instructions: | |
result = sum | |
goto bb11 | |
block bb11: | |
predecessors: ['bb10', 'bb9'] | |
successors: ['bb8'] | |
instructions: | |
goto bb8 | |
main: | |
entry: bb12, exit: bb12 | |
block bb12: | |
flags: entry, exit | |
predecessors: [] | |
successors: [] | |
instructions: | |
val1 = 5 | |
val2 = 7 | |
t12 = process_values(val1, val2) | |
outcome = t12 | |
t13 = process_values(3, 3) | |
another_outcome = t13 | |
t14 = outcome - another_outcome | |
return t14 | |
═ Static Single Assignment ════════════════════════════════════════════════════ | |
proc check_positive_product(x: int, y: int) -> bool: | |
block bb1: | |
t1 = x.0 * y.0 | |
product.0 = t1 | |
t2 = product.0 > 0 | |
is_positive.0 = t2 | |
return is_positive.0 | |
proc process_values(a: int, b: int) -> int: | |
block bb2: | |
t4 = a.0 + b.0 | |
sum.0 = t4 | |
t5 = a.0 == b.0 | |
are_equal.0 = t5 | |
result.0 = 0 | |
if are_equal.0 goto bb3 else goto bb4 | |
block bb3: | |
result.4 = 0 | |
goto bb5 | |
block bb4: | |
t6 = sum.0 > 10 | |
if t6 goto bb6 else goto bb7 | |
block bb5: | |
diff.0 = φ(bb8: diff.1, bb3: None) | |
result.1 = φ(bb8: result.3, bb3: result.4) | |
return result.1 | |
block bb6: | |
t7 = check_positive_product(a.0, b.0) | |
if t7 goto bb9 else goto bb10 | |
block bb7: | |
t9 = a.0 - b.0 | |
diff.2 = t9 | |
t10 = neg diff.2 | |
result.7 = t10 | |
goto bb8 | |
block bb8: | |
diff.1 = φ(bb11: None, bb7: diff.2) | |
result.3 = φ(bb11: result.5, bb7: result.7) | |
goto bb5 | |
block bb9: | |
t8 = sum.0 * 2 | |
result.6 = t8 | |
goto bb11 | |
block bb10: | |
result.2 = sum.0 | |
goto bb11 | |
block bb11: | |
result.5 = φ(bb10: result.2, bb9: result.6) | |
goto bb8 | |
proc main() -> int: | |
block bb12: | |
val1.0 = 5 | |
val2.0 = 7 | |
t12 = process_values(val1.0, val2.0) | |
outcome.0 = t12 | |
t13 = process_values(3, 3) | |
another_outcome.0 = t13 | |
t14 = outcome.0 - another_outcome.0 | |
return t14 | |
═ LLVM IR ═════════════════════════════════════════════════════════════════════ | |
; ModuleID = "module" | |
target triple = "unknown-unknown-unknown" | |
target datalayout = "" | |
define i1 @"check_positive_product"(i32 %"x", i32 %"y") | |
{ | |
bb1: | |
%"t1" = mul i32 %"x", %"y" | |
%"t2" = icmp sgt i32 %"t1", 0 | |
ret i1 %"t2" | |
} | |
define i32 @"process_values"(i32 %"a", i32 %"b") | |
{ | |
bb2: | |
%"t4" = add i32 %"a", %"b" | |
%"t5" = icmp eq i32 %"a", %"b" | |
br i1 %"t5", label %"bb3", label %"bb4" | |
bb3: | |
br label %"bb5" | |
bb4: | |
%"t6" = icmp sgt i32 %"t4", 10 | |
br i1 %"t6", label %"bb6", label %"bb7" | |
bb5: | |
%"diff.0" = phi i32 [%"diff.1", %"bb8"], [0, %"bb3"] | |
%"result.1" = phi i32 [%"result.3", %"bb8"], [0, %"bb3"] | |
ret i32 %"result.1" | |
bb6: | |
%"t7" = call i1 @"check_positive_product"(i32 %"a", i32 %"b") | |
br i1 %"t7", label %"bb9", label %"bb10" | |
bb7: | |
%"t9" = sub i32 %"a", %"b" | |
%"t10" = sub i32 0, %"t9" | |
br label %"bb8" | |
bb8: | |
%"diff.1" = phi i32 [0, %"bb11"], [%"t9", %"bb7"] | |
%"result.3" = phi i32 [%"result.5", %"bb11"], [%"t10", %"bb7"] | |
br label %"bb5" | |
bb9: | |
%"t8" = mul i32 %"t4", 2 | |
br label %"bb11" | |
bb10: | |
br label %"bb11" | |
bb11: | |
%"result.5" = phi i32 [%"t4", %"bb10"], [%"t8", %"bb9"] | |
br label %"bb8" | |
} | |
define i32 @"main"() | |
{ | |
bb12: | |
%"t12" = call i32 @"process_values"(i32 5, i32 7) | |
%"t13" = call i32 @"process_values"(i32 3, i32 3) | |
%"t14" = sub i32 %"t12", %"t13" | |
ret i32 %"t14" | |
} | |
═ Result ══════════════════════════════════════════════════════════════════════ | |
24 | |
═ Executable Generated ════════════════════════════════════════════════════════ | |
examples/test | |
Process finished with exit code 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment