Skip to content

Commit 53a008a

Browse files
authored
Merge pull request #150 from chengluyu/ucs-translation
2 parents ef969e0 + 301e4d0 commit 53a008a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+4023
-395
lines changed

compiler/shared/test/diff/Lifter.mls

+4-4
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,16 @@ class A<T, U>(x: Int): {a1: Int} & B<T> & D(x){
151151
}
152152
}
153153
//│ |#class| |B|‹|T|›| |{||}|↵|#class| |C| |{||}|↵|#class| |D|(|y|#:| |Int|)| |{||}|↵|#class| |A|‹|T|,| |U|›|(|x|#:| |Int|)|#:| |{|a1|#:| |Int|}| |&| |B|‹|T|›| |&| |D|(|x|)|{|→|#fun| |getA|(||)| |#=| |#new| |C|{|→|#fun| |foo|(|x|#:| |T|)| |#=| |x|←|↵|}|←|↵|}|
154-
//│ Parsed: {class B‹T›() {}; class C() {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): & ('{' {a1: Int} '}',) (& (B‹T›,) (D (x,),),) {fun getA = => new C() {fun foo = x: T, => x}}}
154+
//│ Parsed: {class B‹T›() {}; class C() {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): & (& ('{' {a1: Int} '}',) (B‹T›,),) (D (x,),) {fun getA = => new C() {fun foo = x: T, => x}}}
155155
//│ Parsed:
156-
//│ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(a1) = Var(Int))))), Tup(_: App(App(Var(&), Tup(_: TyApp(Var(B), List(TypeName(T))))), Tup(_: App(Var(D), Tup(_: Var(x)))))))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = x: T, => x))))))))
156+
//│ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (App(App(Var(&), Tup(_: App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(a1) = Var(Int))))), Tup(_: TyApp(Var(B), List(TypeName(T))))))), Tup(_: App(Var(D), Tup(_: Var(x)))))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = x: T, => x))))))))
157157
//│ Lifted:
158158
//│ TypingUnit {
159159
//│ class B$1[T]() {}
160160
//│ class C$2() {}
161161
//│ class D$3(y: Int,) {}
162162
//│ class A$4_C$1$5[T](par$A$4,): C$2 () {fun foo = x: T, => x}
163-
//│ class A$4[T,U](x: Int,): & ('{' {a1: Int} '}',) (& (B$1 ()‹T›,) (D$3 ((this).x,),),) {fun getA = => {new A$4_C$1$5(this,) {}}}
163+
//│ class A$4[T,U](x: Int,): & (& ('{' {a1: Int} '}',) (B$1 ()‹T›,),) (D$3 ((this).x,),) {fun getA = => {new A$4_C$1$5(this,) {}}}
164164
//│ }
165165
// │ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(a1) = Var(Int)})))), Tup(_: TyApp(Var(B), List(TypeName(T)))))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = x: T, => x))))))))
166166

@@ -269,7 +269,7 @@ new B{
269269
//│ |#class| |A| |{|→|#fun| |getA| |#=| |0|↵|#fun| |funcA| |#=| |10|←|↵|}|↵|#class| |B|#:| |A|{|→|#fun| |getA| |#=| |1|↵|#fun| |funcB| |#=| |11|←|↵|}|↵|#new| |A|↵|#new| |B|↵|#fun| |f|(|x|)| |#=| |#if| |x| |is| |A| |#then| |0| |#else| |1|↵|f|(|#new| |A|{|→|#fun| |getA| |#=| |2|←|↵|}|)|↵|#new| |B|{|→|#fun| |getA| |#=| |funcB|←|↵|}|
270270
//│ Parsed: {class A() {fun getA = 0; fun funcA = 10}; class B(): A {fun getA = 1; fun funcB = 11}; new A() {}; new B() {}; fun f = x, => if (is (x,) (A,)) then 0 else 1; f (new A() {fun getA = 2},); new B() {fun getA = funcB}}
271271
//│ Parsed:
272-
//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, getA, [], IntLit(0)), NuFunDef(None, funcA, [], IntLit(10)))), NuTypeDef(class, B, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, getA, [], IntLit(1)), NuFunDef(None, funcB, [], IntLit(11)))), New(Some((TypeName(A),)), TypingUnit(List())), New(Some((TypeName(B),)), TypingUnit(List())), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If((is (x,) (A,)) then 0, Some(IntLit(1))))), App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List(fun getA = 2))))), New(Some((TypeName(B),)), TypingUnit(List(fun getA = funcB))))
272+
//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, getA, [], IntLit(0)), NuFunDef(None, funcA, [], IntLit(10)))), NuTypeDef(class, B, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, getA, [], IntLit(1)), NuFunDef(None, funcB, [], IntLit(11)))), New(Some((TypeName(A),)), TypingUnit(List())), New(Some((TypeName(B),)), TypingUnit(List())), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If(IfThen(App(App(Var(is), Tup(_: Var(x))), Tup(_: Var(A))), IntLit(0), Some(IntLit(1))))), App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List(fun getA = 2))))), New(Some((TypeName(B),)), TypingUnit(List(fun getA = funcB))))
273273
//│ Lifted:
274274
//│ TypingUnit {
275275
//│ class A$1() {fun getA = 0; fun funcA = 10}

compiler/shared/test/diff/LifterBlks.mls

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ fun f(x,y,z) =
132132
fun boo = (new A).bar1 + B().bar2 + z
133133
}
134134
//│ |#fun| |f|(|x|,|y|,|z|)| |#=| |→|#class| |C|{|→|#class| |A|{|→|#fun| |foo| |#=| |#new| |B|↵|#fun| |bar1| |#=| |x|←|↵|}|↵|#class| |B|{|→|#fun| |foo| |#=| |#new| |A|↵|#fun| |bar2| |#=| |y|←|↵|}|↵|#fun| |boo| |#=| |(|#new| |A|)|.bar1| |+| |B|(||)|.bar2| |+| |z|←|↵|}|←|
135-
//│ Parsed: {fun f = x, y, z, => {class C() {class A() {fun foo = new B() {}; fun bar1 = x}; class B() {fun foo = new A() {}; fun bar2 = y}; fun boo = + (('(' new A() {}, ')').bar1,) (+ ((B ()).bar2,) (z,),)}}}
135+
//│ Parsed: {fun f = x, y, z, => {class C() {class A() {fun foo = new B() {}; fun bar1 = x}; class B() {fun foo = new A() {}; fun bar2 = y}; fun boo = + (+ (('(' new A() {}, ')').bar1,) ((B ()).bar2,),) (z,)}}}
136136
//│ Parsed:
137137
//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x), _: Var(y), _: Var(z)), Blk(...))))
138138
//│ Lifted:
@@ -146,7 +146,7 @@ fun f(x,y,z) =
146146
//│ fun bar2 = ((this).par$C$1).y
147147
//│ }
148148
//│ class C$1(x, y, z,) {
149-
//│ fun boo = + (('(' new C$1_A$2(this,) {}, ')').bar1,) (+ ((C$1_B$3 (this,)).bar2,) ((this).z,),)
149+
//│ fun boo = + (+ (('(' new C$1_A$2(this,) {}, ')').bar1,) ((C$1_B$3 (this,)).bar2,),) ((this).z,)
150150
//│ }
151151
//│ fun f = x, y, z, => {}
152152
//│ }

js/src/main/scala/Main.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ object Main {
311311
subsume(ty_sch, sign)(ctx, raise, TypeProvenance(d.toLoc, "def definition"))
312312
// Note: keeping the less precise declared type signature here (no ctx update)
313313
case N =>
314-
ctx += nme.name -> ty_sch
314+
ctx += nme.name -> VarSymbol(ty_sch, nme)
315315
}
316316
res ++= formatBinding(d.nme.name, ty_sch)
317317
results append S(d.nme.name) -> htmlize(getType(ty_sch).show)
@@ -327,22 +327,22 @@ object Main {
327327
}
328328
val ty_sch = PolymorphicType(0, typeType(rhs)(ctx.nextLevel, raise,
329329
vars = tps.map(tp => tp.name -> freshVar(noProv/*FIXME*/)(1)).toMap))
330-
ctx += nme.name -> ty_sch
330+
ctx += nme.name -> VarSymbol(ty_sch, nme)
331331
declared += nme -> ty_sch
332332
results append S(d.nme.name) -> htmlize(getType(ty_sch).show)
333333
case s: DesugaredStatement =>
334334
typer.typeStatement(s, allowPure = true) match {
335335
case R(binds) =>
336336
binds.foreach { case (nme, pty) =>
337-
ctx += nme -> pty
337+
ctx += nme -> VarSymbol(pty, Var(nme))
338338
res ++= formatBinding(nme, pty)
339339
results append S(nme) -> htmlize(getType(pty).show)
340340
}
341341
case L(pty) =>
342342
val exp = getType(pty)
343343
if (exp =/= TypeName("unit")) {
344344
val nme = "res"
345-
ctx += nme -> pty
345+
ctx += nme -> VarSymbol(pty, Var(nme))
346346
res ++= formatBinding(nme, pty)
347347
results append N -> htmlize(getType(pty).show)
348348
}

shared/src/main/scala/mlscript/JSBackend.scala

+25-11
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) {
137137
* Translate MLscript terms into JavaScript expressions.
138138
*/
139139
protected def translateTerm(term: Term)(implicit scope: Scope): JSExpr = term match {
140+
case _ if term.desugaredTerm.isDefined => translateTerm(term.desugaredTerm.get)
140141
case Var(name) => translateVar(name, false)
141142
case Lam(params, body) =>
142143
val lamScope = scope.derive("Lam")
@@ -178,15 +179,17 @@ class JSBackend(allowUnresolvedSymbols: Boolean) {
178179
)
179180
case Blk(stmts) =>
180181
val blkScope = scope.derive("Blk")
182+
val flattened = stmts.iterator.flatMap(_.desugared._2).toList
181183
JSImmEvalFn(
182184
N,
183185
Nil,
184-
R(blkScope.tempVars `with` (stmts flatMap (_.desugared._2) map {
185-
case t: Term => JSExprStmt(translateTerm(t))
186+
R(blkScope.tempVars `with` (flattened.iterator.zipWithIndex.map {
187+
case (t: Term, index) if index + 1 == flattened.length => translateTerm(t)(blkScope).`return`
188+
case (t: Term, index) => JSExprStmt(translateTerm(t)(blkScope))
186189
// TODO: find out if we need to support this.
187-
case _: Def | _: TypeDef | _: NuFunDef /* | _: NuTypeDef */ =>
188-
throw CodeGenError("unexpected definitions in blocks")
189-
})),
190+
case (_: Def | _: TypeDef | _: NuFunDef /* | _: NuTypeDef */, _) =>
191+
throw CodeGenError("unsupported definitions in blocks")
192+
}.toList)),
190193
Nil
191194
)
192195
// Pattern match with only one branch -> comma expression
@@ -235,7 +238,15 @@ class JSBackend(allowUnresolvedSymbols: Boolean) {
235238
case _ =>
236239
throw CodeGenError(s"illegal assignemnt left-hand side: ${inspect(lhs)}")
237240
}
238-
case _: Bind | _: Test | If(_, _) | New(_, _) | TyApp(_, _) | _: Splc =>
241+
case iff: If =>
242+
throw CodeGenError(s"if expression has not been desugared")
243+
case New(N, TypingUnit(Nil)) => JSRecord(Nil)
244+
case New(S(TypeName(className) -> Tup(args)), TypingUnit(Nil)) =>
245+
val callee = translateVar(className, true)
246+
callee(args.map { case (_, Fld(_, _, arg)) => translateTerm(arg) }: _*)
247+
case New(_, TypingUnit(_)) =>
248+
throw CodeGenError("custom class body is not supported yet")
249+
case _: Bind | _: Test | If(_, _) | TyApp(_, _) | _: Splc =>
239250
throw CodeGenError(s"cannot generate code for term ${inspect(term)}")
240251
}
241252

@@ -629,22 +640,23 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) {
629640
// Generate statements.
630641
val queries = otherStmts.map {
631642
case Def(recursive, Var(name), L(body), isByname) =>
643+
val bodyIsLam = body match { case _: Lam => true case _ => false }
632644
(if (recursive) {
633645
val isByvalueRecIn = if (isByname) None else Some(true)
634-
val sym = scope.declareValue(name, isByvalueRecIn, body.isInstanceOf[Lam])
646+
val sym = scope.declareValue(name, isByvalueRecIn, bodyIsLam)
635647
try {
636648
val translated = translateTerm(body)
637649
scope.unregisterSymbol(sym)
638650
val isByvalueRecOut = if (isByname) None else Some(false)
639-
R((translated, scope.declareValue(name, isByvalueRecOut, body.isInstanceOf[Lam])))
651+
R((translated, scope.declareValue(name, isByvalueRecOut, bodyIsLam)))
640652
} catch {
641653
case e: UnimplementedError =>
642654
scope.stubize(sym, e.symbol)
643655
L(e.getMessage())
644656
case e: Throwable =>
645657
scope.unregisterSymbol(sym)
646658
val isByvalueRecOut = if (isByname) None else Some(false)
647-
scope.declareValue(name, isByvalueRecOut, body.isInstanceOf[Lam])
659+
scope.declareValue(name, isByvalueRecOut, bodyIsLam)
648660
throw e
649661
}
650662
} else {
@@ -655,7 +667,7 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) {
655667
case e: Throwable => throw e
656668
}) map {
657669
val isByvalueRec = if (isByname) None else Some(false)
658-
expr => (expr, scope.declareValue(name, isByvalueRec, body.isInstanceOf[Lam]))
670+
expr => (expr, scope.declareValue(name, isByvalueRec, bodyIsLam))
659671
}
660672
}) match {
661673
case R((originalExpr, sym)) =>
@@ -736,7 +748,9 @@ object JSTestBackend {
736748
/**
737749
* Represents the result of code generation.
738750
*/
739-
abstract class Result
751+
abstract class Result {
752+
def showFirstResult(prefixLength: Int): Unit = ()
753+
}
740754

741755
/**
742756
* Emitted code.

shared/src/main/scala/mlscript/NewParser.scala

+9-6
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
9393
"",
9494
"",
9595
"",
96+
"",
9697
// ^ for keywords
9798
",",
9899
";",
@@ -116,10 +117,11 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
116117

117118
def opCharPrec(opChar: Char): Int = prec(opChar)
118119
def opPrec(opStr: Str): (Int, Int) = opStr match {
120+
case "is" => (4, 4)
119121
case "and" => (3, 3)
120122
case "or" => (2, 2)
121123
case _ if opStr.exists(_.isLetter) =>
122-
(4, 4)
124+
(5, 5)
123125
case _ =>
124126
val r = opStr.last
125127
(prec(opStr.head), prec(r) - (if (r === '@' || r === '/' || r === ',') 1 else 0))
@@ -652,25 +654,26 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
652654
}
653655
case _ => ???
654656
})
655-
exprCont(res, 0, allowNewlines)
657+
exprCont(res, prec, allowNewlines)
656658

657659
case (br @ BRACKETS(Square, toks), loc) :: _ =>
658660
consume
659661
val idx = rec(toks, S(br.innerLoc), "subscript").concludeWith(_.expr(0))
660662
val res = Subs(acc, idx.withLoc(S(loc)))
661-
exprCont(res, 0, allowNewlines)
663+
exprCont(res, prec, allowNewlines)
662664

663665
case (br @ BRACKETS(Round, toks), loc) :: _ =>
664666
consume
665667
val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented())
666668
val res = App(acc, Tup(as).withLoc(S(loc)))
667-
exprCont(res, 0, allowNewlines)
669+
exprCont(res, prec, allowNewlines)
670+
668671
case (KEYWORD("of"), _) :: _ =>
669672
consume
670673
val as = argsMaybeIndented()
671674
// val as = argsOrIf(Nil) // TODO
672675
val res = App(acc, Tup(as))
673-
exprCont(res, 0, allowNewlines)
676+
exprCont(res, prec, allowNewlines)
674677

675678
case c @ (h :: _) if (h._1 match {
676679
case KEYWORD(";" | "of") | BRACKETS(Round | Square, _)
@@ -686,7 +689,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
686689
val res = App(acc, Tup(as))
687690
raise(WarningReport(msg"Paren-less applications should use the 'of' keyword"
688691
-> res.toLoc :: Nil))
689-
exprCont(res, 0, allowNewlines)
692+
exprCont(res, prec, allowNewlines)
690693

691694
case _ => R(acc)
692695
}

shared/src/main/scala/mlscript/TypeDefs.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ class TypeDefs extends NuTypeDefs { self: Typer =>
181181
val (bodyTy, tvars) =
182182
typeType2(td.body, simplify = false)(ctx.copy(lvl = 0), raise, tparamsargs.map(_.name -> _).toMap, newDefsInfo)
183183
val td1 = TypeDef(td.kind, td.nme, tparamsargs.toList, tvars, bodyTy,
184-
td.mthDecls, td.mthDefs, baseClassesOf(td), td.toLoc, Nil)
184+
td.mthDecls, td.mthDefs, baseClassesOf(td), td.toLoc, td.positionals.map(_.name))
185185
allDefs += n -> td1
186186
S(td1)
187187
}
@@ -337,7 +337,7 @@ class TypeDefs extends NuTypeDefs { self: Typer =>
337337
singleTup(tv), tv & nomTag & RecordType.mk(tparamTags)(noProv)
338338
)(originProv(td.nme.toLoc, "trait constructor", td.nme.name)))
339339
}
340-
ctx += n.name -> ctor
340+
ctx += n.name -> VarSymbol(ctor, Var(n.name))
341341
}
342342
true
343343
}
@@ -491,7 +491,7 @@ class TypeDefs extends NuTypeDefs { self: Typer =>
491491
def go(md: MethodDef[_ <: Term \/ Type]): (Str, MethodType) = {
492492
val thisTag = TraitTag(Var("this"))(noProv)
493493
val thisTy = thisTag & tr
494-
thisCtx += "this" -> thisTy
494+
thisCtx += "this" -> VarSymbol(thisTy, Var("this"))
495495
val MethodDef(rec, prt, nme, tparams, rhs) = md
496496
val prov: TypeProvenance = tp(md.toLoc,
497497
(if (!top) "inherited " else "")

0 commit comments

Comments
 (0)