Hi, I'm Vachan!
- A minimal implementation of a tiny subset of the C language in C and C++23
int putchar(int c);
// return type, only int is supported as of now
int putint(int x) {
if (x < 0) {
putchar(45); // ASCII '-'
x = -x;
}
if (x >= 10)
putint(x / 10);
putchar(48 + (x % 10)); // ASCII '0' = 48
return 0;
}
int factorial(int n) {
int ret;
if (n <= 1) {
ret = 1;
} else {
ret = n * factorial(n - 1);
}
return ret;
}
int main(void) {
// "Hello, World!" using only integers
putchar(72); putchar(101); putchar(108);
putchar(108); putchar(111); putchar(44);
putchar(32); putchar(87); putchar(111);
putchar(114); putchar(108); putchar(100);
putchar(33); putchar(10);
for (int i = 1; i <= 5; i = i + 1) {
int fact = factorial(i);
putint(i); /*space*/ putchar(32);
putint(fact); /*newline*/ putchar(10);
}
return 0;
}Abstract Syntax Tree
Program(
Function(
name='putchar'
Parameters(
name='c.0'
)
)
Function(
name='putint'
Parameters(
name='x.1'
)
body=(
Block(
IfElse(
Binary(<,
Var(name='x.1')
Constant(0)
)
Block(
Expression(
FunctionCall(
name='putchar'
args(
Constant(45)
)
)
)
Expression(
Assignment(
Var(name='x.1')
Unary(-
Var(name='x.1')
)
)
)
)
)
IfElse(
Binary(>=,
Var(name='x.1')
Constant(10)
)
Expression(
FunctionCall(
name='putint'
args(
Binary(/,
Var(name='x.1')
Constant(10)
)
)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Binary(+,
Constant(48)
Binary(%,
Var(name='x.1')
Constant(10)
)
)
)
)
)
Return(
Constant(0)
)
)
)
)
Function(
name='factorial'
Parameters(
name='n.2'
)
body=(
Block(
Declaration(
name='ret.3')
IfElse(
Binary(<=,
Var(name='n.2')
Constant(1)
)
Block(
Expression(
Assignment(
Var(name='ret.3')
Constant(1)
)
)
)
Block(
Expression(
Assignment(
Var(name='ret.3')
Binary(*,
Var(name='n.2')
FunctionCall(
name='factorial'
args(
Binary(-,
Var(name='n.2')
Constant(1)
)
)
)
)
)
)
)
)
Return(
Var(name='ret.3')
)
)
)
)
Function(
name='main'
Parameters()
body=(
Block(
Expression(
FunctionCall(
name='putchar'
args(
Constant(72)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(101)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(108)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(108)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(111)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(44)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(32)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(87)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(111)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(114)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(108)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(100)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(33)
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(10)
)
)
)
For(name='for.0'
Init:
Declaration(
name='i.4'
Constant(1)
)
Condition:
Binary(<=,
Var(name='i.4')
Constant(5)
)
Post:
Assignment(
Var(name='i.4')
Binary(+,
Var(name='i.4')
Constant(1)
)
)
ForLoopBody:
Block(
Declaration(
name='fact.5'
FunctionCall(
name='factorial'
args(
Var(name='i.4')
)
)
)
Expression(
FunctionCall(
name='putint'
args(
Var(name='i.4')
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(32)
)
)
)
Expression(
FunctionCall(
name='putint'
args(
Var(name='fact.5')
)
)
)
Expression(
FunctionCall(
name='putchar'
args(
Constant(10)
)
)
)
)
)
Return(
Constant(0)
)
)
)
)
)
Generated Intermeddiate Representation and Assembly
# ----------- IR Generation -----------
# Function[
# name='putint'
# parameters=[
# 'x.1'
# ]
# instructions=[
# tmp.6 = x.1 < 0
# jump_if_false tmp.6, end.1
# tmp.7 = putchar(45)
# tmp.8 = - x.1
# x.1 = tmp.8
# end.1:
# tmp.9 = x.1 >= 10
# jump_if_false tmp.9, end.2
# tmp.10 = x.1 / 10
# tmp.11 = putint(tmp.10)
# end.2:
# tmp.12 = x.1 % 10
# tmp.13 = 48 + tmp.12
# tmp.14 = putchar(tmp.13)
# return 0
# return 0
# ]
# ]
# Function[
# name='factorial'
# parameters=[
# 'n.2'
# ]
# instructions=[
# tmp.15 = n.2 <= 1
# jump_if_false tmp.15, else.3
# ret.3 = 1
# jump end.4
# else.3:
# tmp.16 = n.2 - 1
# tmp.17 = factorial(tmp.16)
# tmp.18 = n.2 * tmp.17
# ret.3 = tmp.18
# end.4:
# return ret.3
# return 0
# ]
# ]
# Function[
# name='main'
# parameters=[]
# instructions=[
# tmp.19 = putchar(72)
# tmp.20 = putchar(101)
# tmp.21 = putchar(108)
# tmp.22 = putchar(108)
# tmp.23 = putchar(111)
# tmp.24 = putchar(44)
# tmp.25 = putchar(32)
# tmp.26 = putchar(87)
# tmp.27 = putchar(111)
# tmp.28 = putchar(114)
# tmp.29 = putchar(108)
# tmp.30 = putchar(100)
# tmp.31 = putchar(33)
# tmp.32 = putchar(10)
# i.4 = 1
# start_for.0:
# tmp.33 = i.4 <= 5
# jump_if_false tmp.33, break_for.0
# tmp.34 = factorial(i.4)
# fact.5 = tmp.34
# tmp.35 = putint(i.4)
# tmp.36 = putchar(32)
# tmp.37 = putint(fact.5)
# tmp.38 = putchar(10)
# continue_for.0:
# tmp.39 = i.4 + 1
# i.4 = tmp.39
# jump start_for.0
# break_for.0:
# return 0
# return 0
# ]
# ]
# -------------------------------------
.globl putint
putint:
pushq %rbp
movq %rsp, %rbp
subq $48, %rsp
movl %edi, -4(%rbp)
cmpl $0, -4(%rbp)
movl $0, -8(%rbp)
setl -8(%rbp)
cmpl $0, -8(%rbp)
je end.1
movl $45, %edi
call putchar@PLT
movl %eax, -12(%rbp)
movl -4(%rbp), %r10d
movl %r10d, -16(%rbp)
negl -16(%rbp)
movl -16(%rbp), %r10d
movl %r10d, -4(%rbp)
end.1:
cmpl $10, -4(%rbp)
movl $0, -20(%rbp)
setge -20(%rbp)
cmpl $0, -20(%rbp)
je end.2
movl -4(%rbp), %eax
cdq
movl $10, %r10d
idivl %r10d
movl %eax, -24(%rbp)
movl -24(%rbp), %edi
call putint
movl %eax, -28(%rbp)
end.2:
movl -4(%rbp), %eax
cdq
movl $10, %r10d
idivl %r10d
movl %edx, -32(%rbp)
movl $48, -36(%rbp)
movl -32(%rbp), %r10d
addl %r10d, -36(%rbp)
movl -36(%rbp), %edi
call putchar@PLT
movl %eax, -40(%rbp)
movl $0, %eax
movq %rbp, %rsp
popq %rbp
ret
movl $0, %eax
movq %rbp, %rsp
popq %rbp
ret
.globl factorial
factorial:
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl %edi, -4(%rbp)
cmpl $1, -4(%rbp)
movl $0, -8(%rbp)
setle -8(%rbp)
cmpl $0, -8(%rbp)
je else.3
movl $1, -12(%rbp)
jmp end.4
else.3:
movl -4(%rbp), %r10d
movl %r10d, -16(%rbp)
subl $1, -16(%rbp)
movl -16(%rbp), %edi
call factorial
movl %eax, -20(%rbp)
movl -4(%rbp), %r10d
movl %r10d, -24(%rbp)
movl -24(%rbp), %r11d
imull -20(%rbp), %r11d
movl %r11d, -24(%rbp)
movl -24(%rbp), %r10d
movl %r10d, -12(%rbp)
end.4:
movl -12(%rbp), %eax
movq %rbp, %rsp
popq %rbp
ret
movl $0, %eax
movq %rbp, %rsp
popq %rbp
ret
.globl main
main:
pushq %rbp
movq %rsp, %rbp
subq $96, %rsp
movl $72, %edi
call putchar@PLT
movl %eax, -4(%rbp)
movl $101, %edi
call putchar@PLT
movl %eax, -8(%rbp)
movl $108, %edi
call putchar@PLT
movl %eax, -12(%rbp)
movl $108, %edi
call putchar@PLT
movl %eax, -16(%rbp)
movl $111, %edi
call putchar@PLT
movl %eax, -20(%rbp)
movl $44, %edi
call putchar@PLT
movl %eax, -24(%rbp)
movl $32, %edi
call putchar@PLT
movl %eax, -28(%rbp)
movl $87, %edi
call putchar@PLT
movl %eax, -32(%rbp)
movl $111, %edi
call putchar@PLT
movl %eax, -36(%rbp)
movl $114, %edi
call putchar@PLT
movl %eax, -40(%rbp)
movl $108, %edi
call putchar@PLT
movl %eax, -44(%rbp)
movl $100, %edi
call putchar@PLT
movl %eax, -48(%rbp)
movl $33, %edi
call putchar@PLT
movl %eax, -52(%rbp)
movl $10, %edi
call putchar@PLT
movl %eax, -56(%rbp)
movl $1, -60(%rbp)
start_for.0:
cmpl $5, -60(%rbp)
movl $0, -64(%rbp)
setle -64(%rbp)
cmpl $0, -64(%rbp)
je break_for.0
movl -60(%rbp), %edi
call factorial
movl %eax, -68(%rbp)
movl -68(%rbp), %r10d
movl %r10d, -72(%rbp)
movl -60(%rbp), %edi
call putint
movl %eax, -76(%rbp)
movl $32, %edi
call putchar@PLT
movl %eax, -80(%rbp)
movl -72(%rbp), %edi
call putint
movl %eax, -84(%rbp)
movl $10, %edi
call putchar@PLT
movl %eax, -88(%rbp)
continue_for.0:
movl -60(%rbp), %r10d
movl %r10d, -92(%rbp)
addl $1, -92(%rbp)
movl -92(%rbp), %r10d
movl %r10d, -60(%rbp)
jmp start_for.0
break_for.0:
movl $0, %eax
movq %rbp, %rsp
popq %rbp
ret
movl $0, %eax
movq %rbp, %rsp
popq %rbp
ret
.section .note.GNU-stack, "",@progbits- Neural Networks => nn.ipynb
- Batch-Normalization and Layer-Normalization: Why When Where & How? => batchnorm.ipynb, layernorm.ipynb
- Dropout: Why When Where & How? => dropout.ipynb, dropout_scale.ipynb
- LeNet: Convolutional Neural Networks from scratch => train_lenet.ipynb
- Neural Network Optimization => optim.py — custom impl of SGD w-w/o Momentum, RMSProp, Adam, Muon
| Algorithms | Environment (Name & Goal) | Environment GIF | Plots |
|---|---|---|---|
| Policy Iteration | Frozen Lake: The player makes moves until they reach the goal or fall in a hole. The lake is slippery (unless disabled) so the player may move perpendicular to the intended direction sometimes. | ![]() |
- |
| Value Iteration | Taxi-v3: The taxi starts at a random location within the grid. The passenger starts at one of the designated pick-up locations. The passenger also has a randomly assigned destination (one of the four designated locations). | ![]() |
- |
| Monte Carlo Exploring Starts | Blackjack-v1: a card game where the goal is to beat the dealer by obtaining cards that sum to closer to 21 (without going over 21) than the dealer's cards | ![]() |
![]() |
| Sarsa | CliffWalking-v0: Reach goal without falling | ![]() |
Sarsa: Orange |
| Q-learning | CliffWalking-v0: Reach goal without falling | ![]() |
Q-learning: Blue |
| Expected Sarsa | CliffWalking-v0: Reach goal without falling | ![]() |
Expected Sarsa: Green |
| Double Q-learning | CliffWalking-v0: Reach goal without falling | ![]() |
Double Q-learning: Red |
| Dyna-Q | ShortcutMazeEnv (custom made env): Reach the goal dodging obstacles | ![]() |
![]() |
| Prioritized Sweeping | ShortcutMazeEnv (custom made env): Reach the goal dodging obstacles | ![]() |
![]() |
| Monte-Carlo Policy-Gradient | CartPole-v1: goal is to balance the pole by applying forces in the left and right direction on the cart. | ![]() |
![]() |
| One-Step Actor-Critic | CartPole-v1: goal is to balance the pole by applying forces in the left and right direction on the cart. | ![]() |
![]() |
| Year | Paper | Environment (Name & Goal) | Environment GIF | Plots |
|---|---|---|---|---|
| 2013 | Playing Atari with Deep Reinforcement Learning | ALE/Pong-v5 - You control the right paddle, you compete against the left paddle controlled by the computer. You each try to keep deflecting the ball away from your goal and into your opponent’s goal. | ![]() |
|
| 2014 | Deep Deterministic Policy Gradient (DDPG) | Pendulum-v1 - The pendulum starts in a random position and the goal is to apply torque on the free end to swing it into an upright position, with its center of gravity right above the fixed point. | ![]() |
![]() |
| 2017 | Proximal Policy Optimization (PPO) -- Discrete Action Space | LunarLander-v3: This environment is a classic rocket trajectory optimization problem. According to Pontryagin’s maximum principle, it is optimal to fire the engine at full throttle or turn it off | ![]() |
![]() |
| 2017 | Proximal Policy Optimization (PPO) -- Continuous Action Space | HalfCheetah-v5: The goal is to apply torque to the joints to make the cheetah run forward (right) as fast as possible, with a positive reward based on the distance moved forward and a negative reward for moving backward. | ![]() |
![]() |
| 2018 | Soft Actor-Critic (SAC) | InvertedDoublePendulum-v5: The cart can be pushed left or right, and the goal is to balance the second pole on top of the first pole, which is in turn on top of the cart, by applying continuous forces to the cart. | ![]() |
![]() |



































