Skip to content
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
21 changes: 2 additions & 19 deletions effekt/shared/src/main/scala/effekt/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -291,18 +291,6 @@ object Namer extends Phase[Parsed, NameResolved] {
}

case f @ source.ExternDef(capture, id, tparams, vparams, bparams, ret, bodies) =>
if (!bodies.supportedByFeatureFlags(Context.compiler.supportedFeatureFlags)) {
val featureFlags = bodies.map(_.featureFlag)
Context.warning(pp"Extern definition ${id} is not supported as it is only defined for feature flags ${featureFlags.mkString(", ")}," +
pp"but the current backend only supports ${Context.compiler.supportedFeatureFlags.mkString(", ")}.")
}
bodies.foreach {
case source.ExternBody.StringExternBody(ff, _) if ff.isDefault =>
Context.warning(pp"Extern definition ${id} contains extern string without feature flag. This will likely not work in other backends, "
+ pp"please annotate it with a feature flag (Supported by the current backend: ${Context.compiler.supportedFeatureFlags.mkString(", ")})")
case _ => ()
}

val sym = f.symbol
Context scoped {
sym.tparams.foreach { p => Context.bind(p) }
Expand All @@ -311,6 +299,7 @@ object Namer extends Phase[Parsed, NameResolved] {
bodies.foreach {
case source.ExternBody.StringExternBody(ff, body) => body.args.foreach(resolveGeneric)
case source.ExternBody.EffektExternBody(ff, body) => resolveGeneric(body)
case u: source.ExternBody.Unsupported => u
}
}

Expand Down Expand Up @@ -381,13 +370,7 @@ object Namer extends Phase[Parsed, NameResolved] {
case source.ExternType(id, tparams) => ()
case source.ExternInterface(id, tparams) => ()
case source.ExternResource(id, tpe) => ()
case source.ExternInclude(ff, path, _, _) =>
if (ff.isDefault) {
val supported = Context.compiler.supportedFeatureFlags.mkString(", ")
Context.warning("Found extern include without feature flag. It is likely that this will fail in other backends, "
+ s"please annotate it with a feature flag (Supported in current backend: ${supported})")
}
()
case source.ExternInclude(ff, path, _, _) => ()

case source.If(guards, thn, els) =>
Context scoped { guards.foreach(resolve); resolveGeneric(thn) }
Expand Down
1 change: 1 addition & 0 deletions effekt/shared/src/main/scala/effekt/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ object Typer extends Phase[NameResolved, Typechecked] {
body.args.foreach { arg => checkExpr(arg, None) }
case source.ExternBody.EffektExternBody(ff, body) =>
checkStmt(body, Some(expectedReturnType))
case u: source.ExternBody.Unsupported => u
}

}
Expand Down
2 changes: 1 addition & 1 deletion effekt/shared/src/main/scala/effekt/core/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class CoreParsers(positions: Positions, names: Names) extends EffektLexers(posit
case captures ~ (id, tparams, cparams, vparams, bparams, result) ~ body =>
Extern.Def(id, tparams, cparams, vparams, bparams, result, captures, body match {
case ff ~ (body: String) =>
ExternBody(ff, Template(List(body), Nil))
ExternBody.StringExternBody(ff, Template(List(body), Nil))
})
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ object PolymorphismBoxing extends Phase[CoreTransformed, CoreTransformed] {
case Extern.Def(id, tparams, cparams, vparams, bparams, ret, annotatedCapture, body) =>
Extern.Def(id, tparams, cparams, vparams map transform, bparams map transform, transform(ret),
annotatedCapture, body match {
case ExternBody(ff, bbody) => ExternBody(ff, Template(bbody.strings, bbody.args map transform))
case ExternBody.StringExternBody(ff, bbody) => ExternBody.StringExternBody(ff, Template(bbody.strings, bbody.args map transform))
case e @ ExternBody.Unsupported(_) => e
} )
case Extern.Include(ff, contents) => Extern.Include(ff, contents)
}
Expand Down
3 changes: 2 additions & 1 deletion effekt/shared/src/main/scala/effekt/core/PrettyPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ object PrettyPrinter extends ParenPrettyPrinter {
def toDoc(e: Extern): Doc = e match {
case Extern.Def(id, tps, cps, vps, bps, ret, capt, bodies) =>
"extern" <+> toDoc(capt) <+> "def" <+> toDoc(id) <+> "=" <+> paramsToDoc(tps, vps, bps) <> ":" <+> toDoc(ret) <+> "=" <+> (bodies match {
case ExternBody(ff, body) => toDoc(ff) <+> toDoc(body)
case ExternBody.StringExternBody(ff, body) => toDoc(ff) <+> toDoc(body)
case ExternBody.Unsupported(err) => s"unsupported(${err.toString})"
})
case Extern.Include(ff, contents) => emptyDoc // right now, do not print includes.
}
Expand Down
4 changes: 3 additions & 1 deletion effekt/shared/src/main/scala/effekt/core/Transformer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
case p: Pure => p: Pure
case _ => Context.abort("Spliced arguments need to be pure expressions.")
}
ExternBody(ff, Template(body.strings, args))
ExternBody.StringExternBody(ff, Template(body.strings, args))
case source.ExternBody.Unsupported(err) :: Nil =>
ExternBody.Unsupported(err)
case _ =>
Context.abort("Externs should be resolved and desugared before core.Transformer")
}
Expand Down
14 changes: 6 additions & 8 deletions effekt/shared/src/main/scala/effekt/core/Tree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package core
import effekt.source.FeatureFlag
import effekt.util.Structural
import effekt.util.messages.INTERNAL_ERROR
import effekt.util.messages.ErrorReporter

/**
* Tree structure of programs in our internal core representation.
Expand Down Expand Up @@ -129,17 +130,14 @@ enum Extern extends Tree {
case Def(id: Id, tparams: List[Id], cparams: List[Id], vparams: List[Param.ValueParam], bparams: List[Param.BlockParam], ret: ValueType, annotatedCapture: Captures, body: ExternBody)
case Include(featureFlag: FeatureFlag, contents: String)
}
case class ExternBody(featureFlag: FeatureFlag, contents: Template[Pure]) extends Tree

extension(self: List[ExternBody]) {
def forFeatureFlags(flags: List[String]): Option[ExternBody] = flags match {
case Nil => self.find( _.featureFlag.isDefault )
case flag :: other =>
self.find( _.featureFlag.matches(flag, false) ) orElse { self.forFeatureFlags(other) }
sealed trait ExternBody extends Tree
object ExternBody {
case class StringExternBody(featureFlag: FeatureFlag, contents: Template[Pure]) extends ExternBody
case class Unsupported(err: util.messages.EffektError) extends ExternBody {
def report(using E: ErrorReporter): Unit = E.report(err)
}
}


enum Definition extends Tree {
def id: Id

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ package chez

import effekt.context.Context
import effekt.symbols.{Module, Symbol}
import effekt.util.messages.ErrorReporter
import kiama.output.PrettyPrinterTypes.Document
import kiama.util.Source

class ChezSchemeMonadic extends ChezScheme {
def compilationUnit(mainSymbol: Symbol, mod: Module, decl: core.ModuleDecl): chez.Block =
def compilationUnit(mainSymbol: Symbol, mod: Module, decl: core.ModuleDecl)(using ErrorReporter): chez.Block =
chez.TransformerMonadic.compilationUnit(mainSymbol, mod, decl)

override def supportedFeatureFlags: List[String] = List("chezMonadic", "chez")
}


class ChezSchemeCallCC extends ChezScheme {
def compilationUnit(mainSymbol: Symbol, mod: Module, decl: core.ModuleDecl): chez.Block =
def compilationUnit(mainSymbol: Symbol, mod: Module, decl: core.ModuleDecl)(using ErrorReporter): chez.Block =
chez.TransformerCallCC.compilationUnit(mainSymbol, mod, decl)

override def supportedFeatureFlags: List[String] = List("chezCallCC", "chez")
Expand All @@ -25,7 +26,7 @@ class ChezSchemeCallCC extends ChezScheme {

trait ChezScheme extends Compiler[String] {

def compilationUnit(mainSymbol: Symbol, mod: Module, decl: core.ModuleDecl): chez.Block
def compilationUnit(mainSymbol: Symbol, mod: Module, decl: core.ModuleDecl)(using ErrorReporter): chez.Block

// Implementation of the Compiler Interface:
// -----------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import effekt.context.Context
import effekt.core.*
import effekt.symbols.{ Module, Symbol, TermSymbol, Wildcard }
import effekt.util.paths.*
import effekt.util.messages.ErrorReporter
import kiama.output.PrettyPrinterTypes.Document
import util.messages.{ INTERNAL_ERROR, NOT_SUPPORTED }

Expand Down Expand Up @@ -50,14 +51,14 @@ trait Transformer {
def state(id: ChezName, init: chez.Expr, body: chez.Block): chez.Expr =
Builtin("state", init, chez.Lambda(List(id), body))

def compilationUnit(mainSymbol: Symbol, mod: Module, core: ModuleDecl): chez.Block = {
def compilationUnit(mainSymbol: Symbol, mod: Module, core: ModuleDecl)(using ErrorReporter): chez.Block = {
val definitions = toChez(core)
chez.Block(generateStateAccessors(pure) ++ definitions, Nil, runMain(nameRef(mainSymbol)))
}

def toChez(p: Param): ChezName = nameDef(p.id)

def toChez(module: ModuleDecl): List[chez.Def] = {
def toChez(module: ModuleDecl)(using ErrorReporter): List[chez.Def] = {
val decls = module.declarations.flatMap(toChez)
val externs = module.externs.map(toChez)
// TODO FIXME, once there is a let _ = ... in there, we are doomed!
Expand Down Expand Up @@ -131,11 +132,17 @@ trait Transformer {
generateConstructor(id, operations.map(op => op.id))
}

def toChez(decl: core.Extern): chez.Def = decl match {
case Extern.Def(id, tpe, cps, vps, bps, ret, capt, ExternBody(_, body)) =>
def toChez(decl: core.Extern)(using ErrorReporter): chez.Def = decl match {
case Extern.Def(id, tpe, cps, vps, bps, ret, capt, body) =>
val tBody = body match {
case ExternBody.StringExternBody(featureFlag, contents) => toChez(contents)
case u: ExternBody.Unsupported =>
u.report
chez.Builtin("hole")
}
chez.Constant(nameDef(id),
chez.Lambda((vps ++ bps) map { p => nameDef(p.id) },
toChez(body)))
tBody))

case Extern.Include(ff, contents) =>
RawDef(contents)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import effekt.context.Context
import effekt.lifted.*
import effekt.symbols.{ Module, Symbol, Wildcard, TermSymbol }
import effekt.util.paths.*
import effekt.util.messages.ErrorReporter
import effekt.symbols.builtins

import kiama.output.PrettyPrinterTypes.Document
Expand All @@ -25,7 +26,7 @@ object TransformerLift {
if (monomorphized) chez.Call(chez.Call(main), List(CPS.id))
else chez.Call(chez.Call(main, CPS.id), List(CPS.id))

def compilationUnit(mainSymbol: Symbol, mod: Module, core: ModuleDecl): chez.Block = {
def compilationUnit(mainSymbol: Symbol, mod: Module, core: ModuleDecl)(using ErrorReporter): chez.Block = {
val definitions = toChez(core)
chez.Block(generateStateAccessors ++ definitions, Nil, runMain(nameRef(mainSymbol)))
}
Expand All @@ -38,7 +39,7 @@ object TransformerLift {
case e: lifted.Evidence => toChez(e)
}

def toChez(module: ModuleDecl): List[chez.Def] = {
def toChez(module: ModuleDecl)(using ErrorReporter): List[chez.Def] = {
val decls = module.decls.flatMap(toChez)
val externs = module.externs.map(toChez)
// TODO FIXME, once there is a let _ = ... in there, we are doomed!
Expand Down Expand Up @@ -195,13 +196,18 @@ object TransformerLift {
generateConstructor(id, operations.map(_.id))
}

def toChez(decl: lifted.Extern): chez.Def = decl match {
case Extern.Def(id, tparams, params, ret, ExternBody(_, body)) =>
def toChez(decl: lifted.Extern)(using ErrorReporter): chez.Def = decl match {
case Extern.Def(id, tparams, params, ret, body) =>
chez.Constant(nameDef(id),
chez.Lambda( params.flatMap {
case p: Param.EvidenceParam => None
case p => Some(nameDef(p.id)) },
toChez(body)))
body match {
case ExternBody.StringExternBody(_, contents) => toChez(contents)
case u: ExternBody.Unsupported =>
u.report
chez.Builtin("hole")
}))

case Extern.Include(ff, contents) =>
RawDef(contents)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,14 @@ object TransformerDirect extends Transformer {
}

def toJS(e: core.Extern)(using TransformerContext): js.Stmt = e match {
case Extern.Def(id, tps, cps, vps, bps, ret, capt, ExternBody(featureFlag, contents)) =>
js.Function(nameDef(id), (vps ++ bps) map externParams, List(js.Return(toJS(contents))))
case Extern.Def(id, tps, cps, vps, bps, ret, capt, body) =>
body match {
case ExternBody.StringExternBody(featureFlag, contents) =>
js.Function(nameDef(id), (vps ++ bps) map externParams, List(js.Return(toJS(contents))))
case u: ExternBody.Unsupported =>
u.report
js.Stmt.Return($effekt.call("hole"))
}

case Extern.Include(ff, contents) =>
js.RawStmt(contents)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,14 @@ trait TransformerMonadic extends Transformer {
def toJS(p: Param): JSName = nameDef(p.id)

def toJS(e: core.Extern)(using DeclarationContext, Context): js.Stmt = e match {
case Extern.Def(id, tps, cps, vps, bps, ret, capt, ExternBody(featureFlag, contents)) =>
js.Function(nameDef(id), (vps ++ bps) map toJS, List(js.Return(toJS(contents))))
case Extern.Def(id, tps, cps, vps, bps, ret, capt, body) =>
body match {
case ExternBody.StringExternBody(_, contents) =>
js.Function(nameDef(id), (vps ++ bps) map toJS, List(js.Return(toJS(contents))))
case u: ExternBody.Unsupported =>
u.report
js.Function(nameDef(id), (vps ++ bps) map toJS, List(js.Return(monadic.Run(monadic.Builtin("hole")))))
}

case Extern.Include(ff, contents) =>
js.RawStmt(contents)
Expand Down Expand Up @@ -176,14 +182,26 @@ trait TransformerMonadic extends Transformer {

case DirectApp(f: core.Block.BlockVar, targs, vargs, Nil) if canInline(f) =>
val extern = D.getExternDef(f.id)
inlineExtern(vargs, extern.vparams, extern.body.contents)
extern.body match {
case ExternBody.StringExternBody(_, contents) =>
inlineExtern(vargs, extern.vparams, contents)
case u: ExternBody.Unsupported =>
u.report
monadic.Run(monadic.Builtin("hole"))
}

case DirectApp(f, targs, vargs, bargs) =>
js.Call(toJS(f), vargs.map(toJS) ++ bargs.map(toJS))

case PureApp(f: core.Block.BlockVar, targs, vargs) if canInline(f) =>
val extern = D.getExternDef(f.id)
inlineExtern(vargs, extern.vparams, extern.body.contents)
extern.body match {
case ExternBody.StringExternBody(_, contents) =>
inlineExtern(vargs, extern.vparams, contents)
case u: ExternBody.Unsupported =>
u.report
monadic.Run(monadic.Builtin("hole"))
}

case PureApp(f, targs, vargs) =>
js.Call(toJS(f), vargs.map(toJS))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package llvm

import effekt.machine
import effekt.util.intercalate
import effekt.util.messages.ErrorReporter
import effekt.machine.analysis.*

import scala.collection.mutable
Expand All @@ -12,7 +13,7 @@ object Transformer {

val llvmFeatureFlags: List[String] = List("llvm")

def transform(program: machine.Program): List[Definition] = program match {
def transform(program: machine.Program)(using ErrorReporter): List[Definition] = program match {
case machine.Program(declarations, statement) =>
given MC: ModuleContext = ModuleContext();
given FC: FunctionContext = FunctionContext();
Expand Down Expand Up @@ -40,12 +41,23 @@ object Transformer {
private def FC(using FC: FunctionContext): FunctionContext = FC
private def BC(using BC: BlockContext): BlockContext = BC

def transform(declaration: machine.Declaration): Definition =
def transform(declaration: machine.Declaration)(using ErrorReporter): Definition =
declaration match {
case machine.Extern(functionName, parameters, returnType, machine.ExternBody(_, body)) =>
VerbatimFunction(transform(returnType), functionName, parameters.map {
case machine.Variable(name, tpe) => Parameter(transform(tpe), name)
}, transform(body))
case machine.Extern(functionName, parameters, returnType, body ) =>
body match {
case machine.ExternBody.StringExternBody(_, contents) =>
VerbatimFunction(transform(returnType), functionName, parameters.map {
case machine.Variable(name, tpe) => Parameter(transform(tpe), name)
}, transform(contents))
case u: machine.ExternBody.Unsupported =>
u.report
VerbatimFunction(transform(returnType), functionName, parameters.map {
case machine.Variable(name, tpe) => Parameter(transform(tpe), name)
},
"""call void @hole()
|unreachable
|""".stripMargin)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phischu can you look at this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks ok

case machine.Include(ff, content) =>
Verbatim(content)
}
Expand Down
15 changes: 11 additions & 4 deletions effekt/shared/src/main/scala/effekt/generator/ml/Transformer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import effekt.lifted.*
import effekt.core.Id
import effekt.symbols.{ Module, Symbol, TermSymbol, Wildcard }
import effekt.util.messages.INTERNAL_ERROR
import effekt.util.messages.ErrorReporter
import effekt.util.paths.*
import kiama.output.PrettyPrinterTypes.Document

Expand Down Expand Up @@ -52,7 +53,7 @@ object Transformer {
case e: lifted.Evidence => toML(e)
}

def toML(module: ModuleDecl)(using TransformerContext): List[ml.Binding] = {
def toML(module: ModuleDecl)(using TransformerContext, ErrorReporter): List[ml.Binding] = {
val decls = sortDeclarations(module.decls).flatMap(toML)
val externs = module.externs.map(toML)
val rest = sortDefinitions(module.definitions).map(toML)
Expand Down Expand Up @@ -183,9 +184,15 @@ object Transformer {
dataDecl :: accessors
}

def toML(ext: Extern)(using TransformerContext): ml.Binding = ext match {
case Extern.Def(id, tparams, params, ret, ExternBody(featureFlag, body)) =>
ml.FunBind(name(id), params map { p => ml.Param.Named(name(p.id)) }, toML(body))
def toML(ext: Extern)(using TransformerContext, ErrorReporter): ml.Binding = ext match {
case Extern.Def(id, tparams, params, ret, body) =>

ml.FunBind(name(id), params map { p => ml.Param.Named(name(p.id)) }, body match {
case ExternBody.StringExternBody(_, contents) => toML(contents)
case u: ExternBody.Unsupported =>
u.report
ml.RawExpr("raise Hole")
})
case Extern.Include(ff, contents) =>
RawBind(contents)
}
Expand Down
Loading