Skip to content

Commit

Permalink
Start to support pattern matching
Browse files Browse the repository at this point in the history
  • Loading branch information
b-studios committed Nov 27, 2023
1 parent 6eb01fc commit 86834d8
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,15 @@ object PrettyPrinter extends ParenPrettyPrinter {
case If(cond, thn, els) => "if" <+> parens(toDoc(cond)) <+> toDoc(thn) <+> "else" <+> toDoc(els)
case Try(prog, id, handler) => "try" <+> jsBlock(prog.map(toDoc)) <+> "catch" <+> parens(toDoc(id)) <+> jsBlock(handler.map(toDoc))
case Throw(expr) => "throw" <+> toDoc(expr) <> ";"
case Break() => "break;"
case Switch(sc, branches, default) => "switch" <+> parens(toDoc(sc)) <+> jsBlock(branches.map {
case (tag, body) => "case" <+> toDoc(tag) <> ":" <+> toDoc(body)
} ++ default.toList.map { body => "default:" <+> toDoc(body) })
case (tag, stmts) => "case" <+> toDoc(tag) <> ":" <+> nested(stmts map toDoc)
} ++ default.toList.map { stmts => "default:" <+> nested(stmts map toDoc) })
}

def toDoc(pattern: Pattern): Doc = pattern match {
case Pattern.Variable(name) => toDoc(name)
case Pattern.Array(ps) => brackets(ps map toDoc)
}

// some helpers
Expand All @@ -60,6 +66,8 @@ object PrettyPrinter extends ParenPrettyPrinter {

def nested(content: Doc): Doc = group(nest(line <> content))

def nested(docs: List[Doc]): Doc = group(nest(line <> vcat(docs)))

def parens(docs: List[Doc]): Doc = parens(hsep(docs, comma))

def brackets(docs: List[Doc]): Doc = brackets(hsep(docs, comma))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ object Transformer {
val sw = js.Switch(js.Member(scrutinee, `tag`), clauses map {
// f17.apply(null, sc.__data)
case (c, block) =>
(tagFor(c), js.Return(js.MethodCall(toJS(block), JSName("apply"), js.RawExpr("null"), js.Member(scrutinee, `data`))))
(tagFor(c), List(js.Return(js.MethodCall(toJS(block), JSName("apply"), js.RawExpr("null"), js.Member(scrutinee, `data`)))))
}, None)

val (stmts, ret) = default.map(toJSStmt).getOrElse((Nil, monadic.Pure(js.RawExpr("null"))))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ object TransformerDS {

val defs = definitions.flatMap {
case d : Definition.Def =>
//Context.panic("Local definitions should have been lambda lifted already.")
Context.panic("Local definitions should have been lambda lifted already.")
val stmts = toJS(d)
stmts
case d : Definition.Let =>
Expand All @@ -139,17 +139,19 @@ object TransformerDS {

// (function () { switch (sc.tag) { case 0: return f17.apply(null, sc.data) }
case Match(sc, clauses, default) =>
Context.panic("Not implemented yet")
// val scrutinee = toJS(sc)
//
// val sw = js.Switch(js.Member(scrutinee, `tag`), clauses map {
// // f17.apply(null, sc.__data)
// case (c, block) =>
// (tagFor(c), js.Return(js.MethodCall(toJS(block), JSName("apply"), js.RawExpr("null"), js.Member(scrutinee, `data`))))
// }, None)
//
// val (stmts, ret) = default.map(toJSStmt).getOrElse((Nil, monadic.Pure(js.RawExpr("null"))))
// (sw :: stmts, ret)
Bind { k =>
val scrutinee = toJS(sc)
js.Switch(js.Member(scrutinee, `tag`), clauses map {
case (c, core.BlockLit(_, _, Nil, _, body)) =>
(tagFor(c), toJS(body)(k) :+ js.Break())
case (c, core.BlockLit(_, _, vparams, _, body)) =>
(tagFor(c), {
// { const [x, y, z] = sc.__data; [[ body ]] }; break
val const = js.Const(js.Pattern.Array(vparams.map { p => js.Pattern.Variable(nameDef(p.id)) }), js.Member(scrutinee, `data`))
(const :: toJS(body)(k)) :+ js.Break()
})
}, default.map(s => toJS(s)(k))) :: Nil
}


// this is the whole reason for the Bind monad
Expand Down Expand Up @@ -259,6 +261,9 @@ object TransformerDS {
case Definition.Let(Wildcard(), core.Run(s)) =>
toJS(s)(x => js.ExprStmt(x))

case Definition.Let(id, core.Run(s)) =>
js.Let(nameDef(id), js.Undefined) :: toJS(s)(x => js.Assign(nameRef(id), x))

case Definition.Let(Wildcard(), binding) =>
List(js.ExprStmt(toJS(binding)))

Expand Down
17 changes: 14 additions & 3 deletions effekt/shared/src/main/scala/effekt/generator/js/Tree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ enum Expr {
}
export Expr.*

enum Pattern {
case Variable(name: JSName)
case Array(ps: List[Pattern])
}

enum Stmt {
// e.g. { <STMT>* }
case Block(stmts: List[Stmt])
Expand All @@ -120,10 +125,10 @@ enum Stmt {
case RawStmt(raw: String)

// e.g. const x = <EXPR>
case Const(name: JSName, binding: Expr)
case Const(pattern: Pattern, binding: Expr)

// e.g. let x = <EXPR>
case Let(name: JSName, binding: Expr)
case Let(pattern: Pattern, binding: Expr)

// e.g. <EXPR> = <EXPR>
case Assign(target: Expr, value: Expr)
Expand All @@ -132,7 +137,7 @@ enum Stmt {
case Destruct(names: List[JSName], binding: Expr)

// e.g. switch (sc) { case <EXPR>: <STMT>; ...; default: <STMT> }
case Switch(scrutinee: Expr, branches: List[(Expr, Stmt)], default: Option[Stmt])
case Switch(scrutinee: Expr, branches: List[(Expr, List[Stmt])], default: Option[List[Stmt]]) // TODO maybe flatten?

// e.g. function <NAME>(x, y) { <STMT>* }
case Function(name: JSName, params: List[JSName], stmts: List[Stmt])
Expand All @@ -146,11 +151,17 @@ enum Stmt {
// e.g. throw e
case Throw(expr: Expr)

// e.g. break
case Break()

// e.g. <EXPR>;
case ExprStmt(expr: Expr)
}
export Stmt.*

def Const(name: JSName, binding: Expr): Stmt = js.Const(Pattern.Variable(name), binding)
def Let(name: JSName, binding: Expr): Stmt = js.Let(Pattern.Variable(name), binding)

// Some smart constructors
def MethodCall(receiver: Expr, method: JSName, args: Expr*): Expr = Call(Member(receiver, method), args.toList)

Expand Down

0 comments on commit 86834d8

Please sign in to comment.