TComp/src/TComp.jl

205 lines
5.5 KiB
Julia
Raw Normal View History

2025-07-28 22:40:06 +08:00
module TComp
include("./parser.jl")
using .Parser
using Match
2025-08-21 00:00:59 +08:00
# For pass 2
struct SimpleExp
binds
body
end
inp = ARGS
f = open(ARGS[1], "r")
prog = read(f, String)
print(prog)
parsed = Parser.totalParse(prog)
print(parsed)
tmp_var_no = 0
2025-08-21 00:00:59 +08:00
# Pass 1: Duplicated varname uniquified
function uniquifyVar(parsed, env)
@match parsed begin
# letrec is not considered
#[("%let", "id"), [ty, var], val, [("%lambda", "id"), args, body]] => nothing
[("%let", "id"), [ty, var], val, body] =>
begin
envNew = env
push!(envNew, var[1]) # push x of var = ("x", "id") in newEnv
res = [("%let", "id"),
2025-08-21 00:00:59 +08:00
[ty, uniquifyVar(var, envNew)],
uniquifyVar(val, env),
uniquifyVar(body, envNew)]
return res
end
(var, "id") =>
begin
reversedEnv = reverse(env)
index = length(env) - findfirst(e -> e == var, reversedEnv) + 1
2025-08-21 00:00:59 +08:00
newVar = var * string(index)
return (newVar, "id")
end
2025-08-21 00:00:59 +08:00
[("%prime", "id"), op, [lhs, rhs]] =>
begin
2025-08-21 00:00:59 +08:00
lhs_new = uniquifyVar(lhs, env)
rhs_new = uniquifyVar(rhs, env)
return [("%prime", "id"), op, [lhs_new, rhs_new]]
end
[("%call", "id"), callee, args...] =>
begin
2025-08-21 00:00:59 +08:00
unifiedCallee = uniquifyVar(callee, env)
unifiedArgs = map(x ->uniquifyVar(x, env), args[1])
return vcat([("%call", "id"), unifiedCallee], [unifiedArgs])
end
(c, "int") => return parsed
_ => "Error"
end
end
2025-08-21 00:00:59 +08:00
# PASS2 explicit Control and Remove Complex
function explicitControlRemoveComplex(prog)
function rmComplex(exp)
return rmComplexAux1(exp, 0)
end
function rmComplexAux1(exp, varNo)
if exp[1] == ("%let", "id")
res = splitLet([], exp, varNo)
tup = rmComplexAux2(SimpleExp(res[1], res[2]), res[3])
else
tup = rmComplexAux2(SimpleExp([], exp), varNo)
end
return tup
end
2025-08-21 00:00:59 +08:00
function rmComplexAux2(exp, varNo)
return @match exp.body begin
(c, "int") => return (exp, varNo)
(v, "id") => return (exp, varNo)
[(id, "id"), caller, callee] where (id == "%prime" || id == "%call") =>
begin
newResList = exp.binds
new_exp_body = Any[(id, "id"), caller]
new_exp_args = []
for i in callee
res = rmComplexAux1(i, varNo)
varNo = res[2]
newBind = res[1].binds
if newBind != []
2025-08-24 22:44:32 +08:00
println("NEW_BIND:", newBind)
2025-08-21 00:00:59 +08:00
newResList = vcat(newResList, newBind)
2025-08-24 22:44:32 +08:00
push!(new_exp_args, last(newBind)[2][2])
2025-08-21 00:00:59 +08:00
else
push!(new_exp_args, i)
end
end
push!(new_exp_body, new_exp_args)
println(newResList)
2025-08-24 22:44:32 +08:00
newBindVar = [("int", "id"), ("tmp" * string(varNo) , "id")]
2025-08-21 00:00:59 +08:00
varNo += 1
newBind = [("%let", "id"), newBindVar, new_exp_body]
push!(newResList, newBind)
return (SimpleExp(newResList, newBindVar), varNo)
end
_ => "Error"
end
end
function splitLet(binds, exp, varNo)
if exp[1] == ("%let", "id")
res = rmComplexAux1(exp[3], varNo)
binds = vcat(binds, res[1].binds)
new_exp = res[1].body
new_bind = [("%let", "id"), exp[2], new_exp]
push!(binds, new_bind)
varNo = res[2]
return splitLet(binds, exp[4], varNo)
else
return (binds, exp, varNo)
end
end
2025-08-24 22:44:32 +08:00
raw_res = rmComplex(prog)[1]
res = push!(raw_res.binds, raw_res.body)
return res
2025-08-21 00:00:59 +08:00
end
2025-08-24 22:44:32 +08:00
### PASS 3 assign x86 instruction
function assignInstruction(inp)
resList = []
for i in inp
println(i)
@match i begin
[("%let", "id"), [_ty, (id, "id")],
[("%prime", "id"), (op, _), [(rhs, _), (lhs, _)]]] =>
begin
instr = ""
ops = ["+", "-", "*", "/"]
instrs = ["addq", "subq", "mulq", "divq"]
opIndex = findfirst(x -> x == op, ops)
instr = instrs[opIndex]
if rhs == id
line1 = [instr, lhs, id]
push!(resList, line1)
else
line1 = ["movq", lhs, id]
line2 = [instr, rhs, id]
push!(resList, line1)
push!(resList, line2)
end
#TODO [("%call", "id"), (op, _), args] => ...
end
[("%let", "id"), [_ty, (id, "id")], (val, _)] =>
begin
line = ["movq", val, id]
push!(resList, line)
end
(c, "int") => push!(resList, [c])
(v, "id") => push!(resList, [v])
_ => println("Error")
end
end
return resList
end
2025-08-21 00:00:59 +08:00
emptyEnv = []
res = uniquifyVar(parsed, emptyEnv)
println("PASS1", res)
res2 = explicitControlRemoveComplex(res)
2025-08-24 22:44:32 +08:00
println("PASS2", Parser.prettyStringLisp(res2))
res3 = assignInstruction(res2)
println("PASS3", res3)
close(f)
2025-07-28 22:40:06 +08:00
end # module