Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternative: implement transformation in machine-transformer #602

Merged
merged 2 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions effekt/jvm/src/test/scala/effekt/LLVMTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class LLVMTests extends EffektTests {
// Valgrind leak, unclear
examplesDir / "llvm" / "polymorphism_map.effekt",
examplesDir / "pos" / "type_parameters_blocks.effekt",

// Valgrind leak in array_new
examplesDir / "benchmarks" / "are_we_fast_yet" / "sieve.effekt",
examplesDir / "benchmarks" / "are_we_fast_yet" / "nbody.effekt",
Expand Down Expand Up @@ -67,9 +67,7 @@ class LLVMTests extends EffektTests {
examplesDir / "pos" / "records.effekt",

// toplevel def and let bindings
examplesDir / "pos" / "toplevelval.effekt",
examplesDir / "pos" / "capture" / "mbed.effekt",
examplesDir / "pos" / "lib_test.effekt",

// unsafe cont
examplesDir / "pos" / "propagators.effekt",
Expand Down
29 changes: 24 additions & 5 deletions effekt/shared/src/main/scala/effekt/machine/Transformer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ object Transformer {
val transformedDefinitions = definitions.foldLeft(mainEntry) {
case (rest, core.Definition.Def(id, core.BlockLit(tparams, cparams, vparams, bparams, body))) =>
Def(Label(transform(id), vparams.map(transform) ++ bparams.map(transform)), transform(body), rest)
case (rest, core.Definition.Let(id, tpe, binding)) =>
Def(BC.globals(id), transform(binding).run { value => Return(List(value)) }, rest)
case (rest, d) =>
ErrorReporter.abort(s"Toplevel def and let bindings not yet supported: ${d}")
ErrorReporter.abort(s"Toplevel object definitions not yet supported: ${d}")
}

Program(declarations, transformedDefinitions)
Expand Down Expand Up @@ -377,7 +379,16 @@ object Transformer {
transform(pure)
}

def transform(expr: core.Expr)(using BlocksParamsContext, DeclarationContext, ErrorReporter): Binding[Variable] = expr match {
def transform(expr: core.Expr)(using BC: BlocksParamsContext, DC: DeclarationContext, E: ErrorReporter): Binding[Variable] = expr match {

case core.ValueVar(id, tpe) if BC.globals contains id =>
val variable = Variable(freshName("run"), transform(tpe))
Binding { k =>
// TODO this might introduce too many pushes.
PushFrame(Clause(List(variable), k(variable)),
Substitute(Nil, Jump(BC.globals(id))))
}

case core.ValueVar(id, tpe) =>
pure(Variable(transform(id), transform(tpe)))

Expand Down Expand Up @@ -542,9 +553,12 @@ object Transformer {

def findToplevelBlocksParams(definitions: List[core.Definition])(using BlocksParamsContext, ErrorReporter): Unit =
definitions.foreach {
case Definition.Def(blockName, core.BlockLit(tparams, cparams, vparams, bparams, body)) =>
noteDefinition(blockName, vparams.map(transform) ++ bparams.map(transform), Nil)
case Definition.Def(id, core.BlockLit(tparams, cparams, vparams, bparams, body)) =>
noteDefinition(id, vparams.map(transform) ++ bparams.map(transform), Nil)
noteParameters(bparams)
case Definition.Let(id, tpe, binding) =>
noteDefinition(id, Nil, Nil)
noteGlobal(id)
case other => ()
}

Expand All @@ -553,7 +567,9 @@ object Transformer {
*/

class BlocksParamsContext() {
var info: Map[Symbol, BlockInfo] = Map()
var info: Map[Symbol, BlockInfo] = Map.empty

var globals: Map[Id, Label] = Map.empty

def definition(id: Id): BlockInfo.Definition = info(id) match {
case d : BlockInfo.Definition => d
Expand Down Expand Up @@ -589,6 +605,9 @@ object Transformer {
case core.BlockParam(id, tpe, capt) => noteParameter(id, tpe)
}

def noteGlobal(id: Id)(using BC: BlocksParamsContext): Unit =
BC.globals += (id -> Label(transform(id), Nil))

def getBlocksParams(id: Id)(using BC: BlocksParamsContext): Environment = BC.definition(id) match {
case BlockInfo.Definition(freeParams, blockParams) => blockParams ++ freeParams
}
Expand Down
25 changes: 12 additions & 13 deletions effekt/shared/src/main/scala/effekt/machine/Tree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -144,33 +144,33 @@ enum Statement {
case Invoke(receiver: Variable, tag: Tag, arguments: Environment)

/**
* e.g. let x = allocate(42, region); s
*/
* e.g. let x = allocate(42, region); s
*/
case Allocate(name: Variable, init: Variable, region: Variable, rest: Statement)

/**
* e.g. let y = load(x); s
*/
* e.g. let y = load(x); s
*/
case Load(name: Variable, reference: Variable, rest: Statement)

/**
* e.g. store(x, 42); s
*/
* e.g. store(x, 42); s
*/
case Store(reference: Variable, value: Variable, rest: Statement)

/**
* e.g. var x = 42; s
* e.g. var x = 42; s
*/
case Var(name: Variable, init: Variable, returnType: Type, rest: Statement)

/**
* e.g. let y = loadVar(x); s
*/
* e.g. let y = loadVar(x); s
*/
case LoadVar(name: Variable, ref: Variable, rest: Statement)

/**
* e.g. storeVar(x, 42); s
*/
* e.g. storeVar(x, 42); s
*/
case StoreVar(ref: Variable, value: Variable, rest: Statement)

/**
Expand Down Expand Up @@ -208,8 +208,8 @@ enum Statement {
/**
* Pops stacks until it finds one labeled with `prompt`
*/

case PopStacks(name: Variable, prompt: Variable, rest: Statement)

/**
* let x = #infix_add(v1, ...); s
*/
Expand All @@ -219,7 +219,6 @@ enum Statement {
* let x = 42; s
*/
case LiteralInt(name: Variable, value: Long, rest: Statement)

case LiteralDouble(name: Variable, value: Double, rest: Statement)
case LiteralUTF8String(name: Variable, utf8: Array[Byte], rest: Statement)

Expand Down
1 change: 1 addition & 0 deletions examples/pos/toplevelval.check
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
3
5
9 changes: 8 additions & 1 deletion examples/pos/toplevelval.effekt
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
module toplevelval

def inc(y: Int) = y + 1

val x = 1 + 2

def main() = println(x)
val z = inc(inc(x))

def main() = {
println(x)
println(z)
}