|
| 1 | +package effekt |
| 2 | +package machine |
| 3 | + |
| 4 | +object DirectStyle { |
| 5 | + |
| 6 | + private var last = 0 |
| 7 | + private def fresh() = { last +=1; s"l_${last}" } |
| 8 | + |
| 9 | + def rewrite(p: Program): Program = |
| 10 | + val Program(decl, stmt) = p |
| 11 | + Program(decl, rewrite(stmt)) |
| 12 | + |
| 13 | + def rewrite(s: Statement): Statement = s match { |
| 14 | + case Statement.PushFrame(Clause(parameters, body), rest) => |
| 15 | + val rewrittenBody = rewrite(body) |
| 16 | + val rewrittenRest = rewrite(rest) |
| 17 | + |
| 18 | + if canBeDirect(rewrittenRest) then |
| 19 | + val env: Environment = analysis.freeVariables(rewrittenBody).filterNot { v => parameters.contains(v) }.toList |
| 20 | + val l = Label(fresh(), env ++ parameters) |
| 21 | + Def(l, rewrittenBody, toDirectStyle(rest, env, parameters, l)) |
| 22 | + else |
| 23 | + PushFrame(Clause(parameters, rewrittenBody), rewrittenRest) |
| 24 | + |
| 25 | + // Congruences |
| 26 | + case Statement.Def(label, body, rest) => Def(label, rewrite(body), rewrite(rest)) |
| 27 | + case Statement.Jump(label) => Jump(label) |
| 28 | + case Statement.Substitute(bindings, rest) => Substitute(bindings, rewrite(rest)) |
| 29 | + case Statement.Construct(name, tag, arguments, rest) => Construct(name, tag, arguments, rewrite(rest)) |
| 30 | + case Statement.Switch(scrutinee, clauses, default) => |
| 31 | + Switch(scrutinee, |
| 32 | + clauses.map { case (idx, Clause(env, body)) => (idx, Clause(env, rewrite(body))) }, |
| 33 | + default.map { case Clause(env, body) => Clause(env, rewrite(body)) }) |
| 34 | + case Statement.New(name, operations, rest) => New(name, operations, rewrite(rest)) |
| 35 | + case Statement.Invoke(receiver, tag, arguments) => Invoke(receiver, tag, arguments) |
| 36 | + case Statement.Var(name, init, returnType, rest) => Var(name, init, returnType, rewrite(rest)) |
| 37 | + case Statement.LoadVar(name, ref, rest) => LoadVar(name, ref, rewrite(rest)) |
| 38 | + case Statement.StoreVar(ref, value, rest) => StoreVar(ref, value, rewrite(rest)) |
| 39 | + case Statement.Return(arguments) => Return(arguments) |
| 40 | + case Statement.Reset(name, frame, rest) => Reset(name, frame, rewrite(rest)) |
| 41 | + case Statement.Resume(stack, rest) => Resume(stack, rewrite(rest)) |
| 42 | + case Statement.Shift(name, prompt, rest) => Shift(name, prompt, rewrite(rest)) |
| 43 | + case Statement.ForeignCall(name, builtin, arguments, rest) => ForeignCall(name, builtin, arguments, rewrite(rest)) |
| 44 | + case Statement.LiteralInt(name, value, rest) => LiteralInt(name, value, rewrite(rest)) |
| 45 | + case Statement.LiteralDouble(name, value, rest) => LiteralDouble(name, value, rewrite(rest)) |
| 46 | + case Statement.LiteralUTF8String(name, utf8, rest) => LiteralUTF8String(name, utf8, rewrite(rest)) |
| 47 | + case Statement.Hole => Hole |
| 48 | + } |
| 49 | + |
| 50 | + def toDirectStyle(stmt: Statement, env: Environment, params: Environment, label: Label): Statement = stmt match { |
| 51 | + case Statement.Return(arguments) => Substitute(env.map(x => x -> x) ++ params.zip(arguments), Jump(label)) |
| 52 | + case Statement.Hole => stmt |
| 53 | + case Statement.Jump(label) => stmt |
| 54 | + case Statement.Invoke(receiver, tag, arguments) => stmt |
| 55 | + |
| 56 | + case Statement.PushFrame(frame, rest) => stmt |
| 57 | + |
| 58 | + case Statement.Reset(name, frame, rest) => Reset(name, frame, rewrite(rest)) |
| 59 | + case Statement.Resume(stack, rest) => Resume(stack, rewrite(rest)) |
| 60 | + case Statement.Shift(name, prompt, rest) => Shift(name, prompt, rewrite(rest)) |
| 61 | + |
| 62 | + // Congruences |
| 63 | + case Statement.Def(label2, body, rest) => Def(label2, body, toDirectStyle(rest, env, params, label)) |
| 64 | + case Statement.Substitute(bindings, rest) => Substitute(bindings, toDirectStyle(rest, env, params, label)) |
| 65 | + case Statement.Construct(name, tag, arguments, rest) => Construct(name, tag, arguments, toDirectStyle(rest, env, params, label)) |
| 66 | + case Statement.Switch(scrutinee, clauses, default) => |
| 67 | + Switch(scrutinee, |
| 68 | + clauses.map { case (idx, Clause(env, body)) => (idx, Clause(env, toDirectStyle(body, env, params, label))) }, |
| 69 | + default.map { case Clause(env, body) => Clause(env, toDirectStyle(body, env, params, label)) }) |
| 70 | + case Statement.New(name, operations, rest) => New(name, operations, toDirectStyle(rest, env, params, label)) |
| 71 | + case Statement.Var(name, init, returnType, rest) => Var(name, init, returnType, toDirectStyle(rest, env, params, label)) |
| 72 | + case Statement.LoadVar(name, ref, rest) => LoadVar(name, ref, toDirectStyle(rest, env, params, label)) |
| 73 | + case Statement.StoreVar(ref, value, rest) => StoreVar(ref, value, toDirectStyle(rest, env, params, label)) |
| 74 | + case Statement.ForeignCall(name, builtin, arguments, rest) => ForeignCall(name, builtin, arguments, toDirectStyle(rest, env, params, label)) |
| 75 | + case Statement.LiteralInt(name, value, rest) => LiteralInt(name, value, toDirectStyle(rest, env, params, label)) |
| 76 | + case Statement.LiteralDouble(name, value, rest) => LiteralDouble(name, value, toDirectStyle(rest, env, params, label)) |
| 77 | + case Statement.LiteralUTF8String(name, utf8, rest) => LiteralUTF8String(name, utf8, toDirectStyle(rest, env, params, label)) |
| 78 | + } |
| 79 | + |
| 80 | + def canBeDirect(stmt: Statement): Boolean = stmt match { |
| 81 | + case Statement.Return(arguments) => true |
| 82 | + case Statement.Hole => true |
| 83 | + |
| 84 | + case Statement.Jump(label) => false |
| 85 | + case Statement.Invoke(receiver, tag, arguments) => false |
| 86 | + case Statement.PushFrame(frame, rest) => false |
| 87 | + |
| 88 | + case Statement.Reset(name, frame, rest) => false // canBeDirect(rest) // ??? |
| 89 | + case Statement.Resume(stack, rest) => false // canBeDirect(rest) // ??? |
| 90 | + case Statement.Shift(name, prompt, rest) => false // canBeDirect(rest) // ??? |
| 91 | + |
| 92 | + // Congruences |
| 93 | + case Statement.Def(label, body, rest) => canBeDirect(rest) |
| 94 | + case Statement.Substitute(bindings, rest) => canBeDirect(rest) |
| 95 | + case Statement.Construct(name, tag, arguments, rest) => canBeDirect(rest) |
| 96 | + case Statement.Switch(scrutinee, clauses, default) => |
| 97 | + clauses.forall { case (idx, Clause(_, body)) => canBeDirect(body) } && default.forall { case Clause(_, body) => canBeDirect(body) } |
| 98 | + case Statement.New(name, operations, rest) => canBeDirect(rest) |
| 99 | + case Statement.Var(name, init, returnType, rest) => canBeDirect(rest) |
| 100 | + case Statement.LoadVar(name, ref, rest) => canBeDirect(rest) |
| 101 | + case Statement.StoreVar(ref, value, rest) => canBeDirect(rest) |
| 102 | + case Statement.ForeignCall(name, builtin, arguments, rest) => canBeDirect(rest) |
| 103 | + case Statement.LiteralInt(name, value, rest) => canBeDirect(rest) |
| 104 | + case Statement.LiteralDouble(name, value, rest) => canBeDirect(rest) |
| 105 | + case Statement.LiteralUTF8String(name, utf8, rest) => canBeDirect(rest) |
| 106 | + } |
| 107 | +} |
0 commit comments