From c6a992886250b3ee292ac73c3c2e72e10a7028e5 Mon Sep 17 00:00:00 2001 From: Tan Kian-ting Date: Thu, 21 Aug 2025 00:00:59 +0800 Subject: [PATCH] add Pass2 --- misc/test.jl | 100 +++++++++++++++++++++++++++++++++++++ passesInstrument.md | 13 +++++ src/TComp.jl | 119 +++++++++++++++++++++++++++++++++++--------- src/parser.jl | 6 +-- test/prog1.tc | 4 +- 5 files changed, 214 insertions(+), 28 deletions(-) create mode 100644 misc/test.jl create mode 100644 passesInstrument.md diff --git a/misc/test.jl b/misc/test.jl new file mode 100644 index 0000000..bbdede2 --- /dev/null +++ b/misc/test.jl @@ -0,0 +1,100 @@ +prog1 = ["prm", "+", [7, ["+", [5, 4]]]] +prog2 = ["prm","+", [["prm", "+", [5, 4]], ["prm","+", [7, 8]]]] + +prog3 = ["prm","+", [["prm","+", [["cal", "foo", 999], 4]], 7]] +prog4 = ["prm","+", [1, 2]] + +prog5 = 5 + +for i in prog4[2] + println(i) +end + +struct SimpleExp + binds + body +end + + +function rmComplex(exp) + return rmComplexAux1(exp, 0) +end + + + + +function rmComplexAux1(exp, varNo) + if exp[1] == "let" + res = splitLet([], exp, varNo) + println("RES=~=~", res) + tup = rmComplexAux2(SimpleExp(res[1], res[2]), res[3]) + + else + tup = rmComplexAux2(SimpleExp([], exp), varNo) + + end + return tup +end + +function rmComplexAux2(exp, varNo) + if isa(exp.body, Int) || isa(exp.body, String) + return (exp, varNo) + elseif isa(exp.body, Array) & (exp.body[1] == "prm" || exp.body[1] == "cal") + newResList = exp.binds + new_exp_body = Any[exp.body[1], exp.body[2]] + new_exp_args = [] + println("exp_body", exp.body) + for i in exp.body[3] + res = rmComplexAux1(i, varNo) + println("res", res) + varNo = res[2] + newBind = res[1].binds + if newBind != [] + println("new~~", newBind) + newResList = vcat(newResList, newBind) + push!(new_exp_args, last(newBind)[2]) + else + push!(new_exp_args, i) + end + + end + push!(new_exp_body, new_exp_args) + + println(newResList) + newBindVar = "tmp" * string(varNo) + varNo += 1 + newBind = ["%let", newBindVar, new_exp_body] + push!(newResList, newBind) + return (SimpleExp(newResList, newBindVar), varNo) + else + return (exp, varNo) + end +end + + +function splitLet(binds, exp, varNo) + if exp[1] == "let" + res = rmComplexAux1(exp[3], varNo) + binds = vcat(binds, res[1].binds) + new_exp = res[1].body + new_bind = ["%let", exp[2], new_exp] + push!(binds, new_bind) + + + varNo = res[2] + return splitLet(binds, exp[4], varNo) + else + return (binds, exp, varNo) + end +end + +prog6 = ["let", "x", ["prm", "-", [10, 3]], ["let", "y", ["cal", "foo", [12]], ["prm", "+", [33, "x"]]]] +println("SPLITLET: ", splitLet([], prog6, 0)) + +println(rmComplex(prog1), "\n\n") + +println(rmComplex(prog2), "\n\n") +println(rmComplex(prog3), "\n\n") +println(rmComplex(prog4), "\n\n") +println(rmComplex(prog5), "\n\n") +println(rmComplex(prog6), "\n\n") diff --git a/passesInstrument.md b/passesInstrument.md new file mode 100644 index 0000000..bcb035e --- /dev/null +++ b/passesInstrument.md @@ -0,0 +1,13 @@ + 1. **OK**: uniquify deals with the shadowing of variables by renaming every variable to a +unique name. + 2. **OK** remove_complex_operands ensures that each subexpression of a primitive operation or + function call is a variable or integer, that is, an atomic expression. We refer +to nonatomic expressions as complex. This pass introduces temporary variables +to hold the results of complex subexpressions. + 3. **OK** explicate_control makes the execution order of the program explicit. It converts +the abstract syntax tree representation into a graph in which each node is a +labeled sequence of statements and the edges are goto statements. + 4. select_instructions handles the difference between LVar operations and x86 +instructions. This pass converts each LVar operation to a short sequence of +instructions that accomplishes the same task. +assign_homes \ No newline at end of file diff --git a/src/TComp.jl b/src/TComp.jl index a719774..89b2908 100644 --- a/src/TComp.jl +++ b/src/TComp.jl @@ -3,6 +3,11 @@ include("./parser.jl") using .Parser using Match +# For pass 2 +struct SimpleExp + binds + body +end inp = ARGS f = open(ARGS[1], "r") @@ -15,8 +20,8 @@ tmp_var_no = 0 -# Pass 1 duplicated varname unified -function unifyVar(parsed, env) +# 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 @@ -26,35 +31,28 @@ function unifyVar(parsed, env) envNew = env push!(envNew, var[1]) # push x of var = ("x", "id") in newEnv res = [("%let", "id"), - [ty, unifyVar(var, envNew)], - unifyVar(val, env), - unifyVar(body, envNew)] + [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 - return (index, "id") + newVar = var * string(index) + return (newVar, "id") end - [(plus, "plus"), lhs, rhs] => + [("%prime", "id"), op, [lhs, rhs]] => begin - lhs_new = unifyVar(lhs, env) - rhs_new = unifyVar(rhs, env) - return [(plus, "plus"), lhs_new, rhs_new] - - end - [(minus, "minus"), lhs, rhs] => - begin - lhs_new = unifyVar(lhs, env) - rhs_new = unifyVar(rhs, env) - return [(minus, "minus"), lhs_new, rhs_new] - + lhs_new = uniquifyVar(lhs, env) + rhs_new = uniquifyVar(rhs, env) + return [("%prime", "id"), op, [lhs_new, rhs_new]] end [("%call", "id"), callee, args...] => begin - unifiedCallee = unifyVar(callee, env) - unifiedArgs = map(x ->unifyVar(x, env), args[1]) + unifiedCallee = uniquifyVar(callee, env) + unifiedArgs = map(x ->uniquifyVar(x, env), args[1]) return vcat([("%call", "id"), unifiedCallee], [unifiedArgs]) end @@ -63,11 +61,86 @@ function unifyVar(parsed, env) end end -emptyEnv = [] -res = unifyVar(parsed, emptyEnv) -print(res) +# 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 + 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 != [] + newResList = vcat(newResList, newBind) + push!(new_exp_args, last(newBind)[2]) + else + push!(new_exp_args, i) + end + + end + push!(new_exp_body, new_exp_args) + + println(newResList) + newBindVar = "tmp" * string(varNo) + 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 + + return rmComplex(prog)[1] +end + +emptyEnv = [] +res = uniquifyVar(parsed, emptyEnv) +println("PASS1", res) +res2 = explicitControlRemoveComplex(res) +println("PASS2", Parser.prettyStringLisp(res2.binds), ", ", Parser.prettyStringLisp(res2.body)) + close(f) diff --git a/src/parser.jl b/src/parser.jl index 488ae7e..608fc5f 100644 --- a/src/parser.jl +++ b/src/parser.jl @@ -147,7 +147,7 @@ function prettyStringLisp(ele) if isa(ele, String) return ele elseif isa(ele, Tuple) - res = prettyStringLisp(ele[1]) + res = string(prettyStringLisp(ele[1])) return res elseif isa(ele, Array) mappedEle = map(prettyStringLisp, ele) @@ -303,7 +303,7 @@ function longTermAux(input) rawFunc = seq([factor, (typ("mul") | typ("div")), factor]) rawRes = rawFunc.fun(input) if rawRes != nothing - matched = [rawRes.matched[2], rawRes.matched[1], rawRes.matched[3]] + matched = [("%prime", "id"), rawRes.matched[2], [rawRes.matched[1], rawRes.matched[3]]] res = ParserResult(matched, rawRes.remained) return res else @@ -325,7 +325,7 @@ function longExpAux(input) rawFunc = seq([term, (typ("plus") | typ("minus")), term]) rawRes = rawFunc.fun(input) if rawRes != nothing - matched = [rawRes.matched[2], rawRes.matched[1], rawRes.matched[3]] + matched = [("%prime", "id"), rawRes.matched[2], [rawRes.matched[1], rawRes.matched[3]]] res = ParserResult(matched, rawRes.remained) return res else diff --git a/test/prog1.tc b/test/prog1.tc index 02c43fd..cbf2d92 100644 --- a/test/prog1.tc +++ b/test/prog1.tc @@ -1,5 +1,5 @@ int a = 12; -int b = 12; -int a = 15; +int b = (12 + (0 - a)); +int a = (15 + b); int d = 20; a + d((0 - a), b) \ No newline at end of file