Skip to content

Instantly share code, notes, and snippets.

@kkestell
Created April 29, 2025 12:24
Show Gist options
  • Save kkestell/577f9c2c4bbe1bb1c5c4b3db272b0bb6 to your computer and use it in GitHub Desktop.
Save kkestell/577f9c2c4bbe1bb1c5c4b3db272b0bb6 to your computer and use it in GitHub Desktop.
/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