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

Improvements and fixes for UCS #157

Merged
merged 58 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
d93e0d6
Add examples from meeting
LPTK Feb 21, 2023
d76b9b0
Add `ne` and `eq` to the JS polyfill
chengluyu Mar 11, 2023
4f0f870
No longer report inexhaustiveness when there is a default branch
chengluyu Mar 11, 2023
f7f0418
Add an incomplete implementation of untyped lambda calculus
chengluyu Mar 11, 2023
03a28b8
Support alias clauses and complete the ULC test cases
chengluyu Mar 12, 2023
d30b9c9
Update test files due to previous commits
chengluyu Mar 12, 2023
2a7a5a7
Add incomplete SLTC and built-in string comparison functions
chengluyu Mar 12, 2023
3d1018b
Fix missing interleaved let bindings in nested branches
chengluyu Mar 12, 2023
67513c1
Fix unhygienically extracting positional class parameters
chengluyu Mar 12, 2023
84b9ba7
Merge remote-tracking branch 'lptk-fork/new-definition-typing' into u…
chengluyu Mar 12, 2023
e4dbbf7
Use `:NewDefs` in lambda calculus test cases
chengluyu Mar 13, 2023
3c9f9a1
Gather lambda calculus test files
chengluyu Mar 13, 2023
a9c80d8
Add incomplete JSON test cases and support escape chars in `Lexer`
chengluyu Mar 14, 2023
e7a9dd5
Merge remote-tracking branch 'lptk-fork/new-definition-typing' into u…
chengluyu Mar 14, 2023
556eb26
Append test file updates
chengluyu Mar 14, 2023
32c70de
No duplication when the else branch is taken at least once
chengluyu Mar 14, 2023
c8ddd6e
Add a more essential test case
chengluyu Mar 14, 2023
aab8d27
Remove syntax highlight overrides for .mls files
chengluyu Mar 15, 2023
fef2c0c
No longer translate literal patterns to `==` applications
chengluyu Mar 15, 2023
8ac73ee
Categorize let bindings so no longer missing alias patterns
chengluyu Mar 15, 2023
c8707c5
Improve warnings of duplicated branches
chengluyu Mar 15, 2023
73dee4c
Improve the debug display of `MutCaseOf`
chengluyu Mar 15, 2023
e0f426a
Fix duplicated interleaved bindings and missing alias bindings
chengluyu Mar 16, 2023
1784ecb
Gather exhaustiveness information on the fly
chengluyu Mar 16, 2023
09a0fb9
Support basic `else if` composition
chengluyu Mar 16, 2023
ae1ca13
Support wildcard followed by more clauses
chengluyu Mar 17, 2023
281bb1d
Ignore .DS_Store :^(
chengluyu Mar 17, 2023
6283351
Add more `_ and t`-like test cases
chengluyu Mar 17, 2023
14344e6
Support wildcard followed by clauses by copying existing wildcard
chengluyu Mar 17, 2023
9997ddf
Fix making module names (e.g. `None`) as positional binding names
chengluyu Mar 17, 2023
f5ba540
Use the new definition typing on `SplitAroundOp.mls`
chengluyu Mar 17, 2023
f036769
Add an interesting case in `LitUCS.mls`.
chengluyu Mar 17, 2023
d972ee3
Add an interleaved let example revealing a code generation problem
chengluyu Mar 17, 2023
a2a5180
Improve the warning message for duplicated branches
chengluyu Mar 17, 2023
15d0c57
Fix all warnings
chengluyu Mar 17, 2023
24c4386
Fix warnings and make CI happy :-P
chengluyu Mar 17, 2023
1bd5ee7
Mark expected errors and warnings
chengluyu Mar 17, 2023
572e618
Fix the parameter error in the previous CI fix
chengluyu Mar 17, 2023
4963caa
Remove two `FIXME` in `MultiwayIf.mls`
chengluyu Mar 18, 2023
8b40fec
Fix temporary name generation in `JSBackend`
chengluyu Mar 18, 2023
9eb14bd
Always check the exhaustiveness of the outer if-then-else first
chengluyu Mar 18, 2023
e227ec3
Add test cases in the poster and gather parse failures
chengluyu Mar 22, 2023
9a8e6aa
Support subclass refinement and preemptive wildcard branches
chengluyu Mar 23, 2023
522f8fb
Consume `MatchAny` and try to merge inexhaustive branches
chengluyu Mar 23, 2023
a35a416
Add new UCS test cases
LPTK Mar 23, 2023
96cdb81
Add zipWith tests
LPTK Mar 26, 2023
73dcda1
Add a couple small test cases
LPTK Apr 4, 2023
b7a7cd5
Support negative integers
chengluyu Apr 26, 2023
d168eb5
Add some examples of unhygienic let bindings
chengluyu Apr 30, 2023
f6021f4
Merge remote-tracking branch 'lptk-fork/new-definition-typing' into u…
chengluyu May 5, 2023
2ff4c7b
Fix `undefined` is a keyword
chengluyu May 5, 2023
ee1ab19
Merge branch 'new-definition-typing' into ucs-paper
chengluyu May 5, 2023
66d41f2
Fix comments
chengluyu May 12, 2023
34b1864
Update CI: run on all PRs
LPTK May 17, 2023
70fd442
Fix minor problems mentioned in PR comments
chengluyu May 18, 2023
b89fa16
Fix the warning in UCS source files
chengluyu May 18, 2023
14a232a
Try to fix more warnings
chengluyu May 18, 2023
17d05de
Describe `FIXME` without actual errors
chengluyu May 22, 2023
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: 2 additions & 2 deletions shared/src/main/scala/mlscript/NewLexer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
else (cur.reverseIterator.mkString, i)

@tailrec final
def str(i: Int, escapeMode: Bool = false, cur: Ls[Char] = Nil): (Str, Int) =
def str(i: Int, escapeMode: Bool, cur: Ls[Char] = Nil): (Str, Int) =
if (escapeMode)
if (i < length)
bytes(i) match {
Expand Down Expand Up @@ -106,7 +106,7 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {
lex(j, ind, next(j, COMMA))
case '"' =>
val j = i + 1
val (chars, k) = str(j)
val (chars, k) = str(j, false)
val k2 = if (bytes.lift(k) === Some('"')) k + 1 else {
pe(msg"unclosed quotation mark")
k
Expand Down
12 changes: 6 additions & 6 deletions shared/src/main/scala/mlscript/ucs/Clause.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,33 @@ object Clause {
override val scrutinee: Scrutinee,
literal: SimpleTerm
)(override val locations: Ls[Loc]) extends MatchClause {
override def toString(): String = s"«$scrutinee is $literal" + bindingsToString
override def toString: String = s"«$scrutinee is $literal" + bindingsToString
}

final case class MatchAny(override val scrutinee: Scrutinee)(override val locations: Ls[Loc]) extends MatchClause {
override def toString(): String = s"«$scrutinee is any" + bindingsToString
override def toString: String = s"«$scrutinee is any" + bindingsToString
}

final case class MatchClass(
override val scrutinee: Scrutinee,
className: Var,
fields: Ls[Str -> Var]
)(override val locations: Ls[Loc]) extends MatchClause {
override def toString(): String = s"«$scrutinee is $className»" + bindingsToString
override def toString: String = s"«$scrutinee is $className»" + bindingsToString
}

final case class MatchTuple(
scrutinee: Scrutinee,
arity: Int,
fields: Ls[Str -> Var]
)(override val locations: Ls[Loc]) extends Clause {
override def toString(): String = s"«$scrutinee is Tuple#$arity»" + bindingsToString
override def toString: String = s"«$scrutinee is Tuple#$arity»" + bindingsToString
}

final case class BooleanTest(test: Term)(
override val locations: Ls[Loc]
) extends Clause {
override def toString(): String = s"«$test»" + bindingsToString
override def toString: String = s"«$test»" + bindingsToString
}

/**
Expand All @@ -73,6 +73,6 @@ object Clause {
final case class Binding(name: Var, term: Term, isField: Bool)(
override val locations: Ls[Loc]
) extends Clause {
override def toString(): String = s"«$name = $term»" + bindingsToString
override def toString: String = s"«$name = $term»" + bindingsToString
}
}
2 changes: 1 addition & 1 deletion shared/src/main/scala/mlscript/ucs/Conjunction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import scala.annotation.tailrec
* A `Conjunction` represents a list of `Clause`s.
*/
final case class Conjunction(clauses: Ls[Clause], trailingBindings: Ls[LetBinding]) {
override def toString(): String =
override def toString: String =
clauses.mkString("", " and ", "") + {
(if (trailingBindings.isEmpty) "" else " ") +
(trailingBindings match {
Expand Down
53 changes: 0 additions & 53 deletions shared/src/main/scala/mlscript/ucs/Desugarer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -765,48 +765,6 @@ class Desugarer extends TypeDefs { self: Typer =>
}
}(_ => s"[checkExhaustive] ${t.describe}")

// private def summarizePatterns(t: MutCaseOf)(implicit ctx: Ctx, raise: Raise): ExhaustivenessMap = traceUCS("[summarizePatterns]") {
// val m = MutMap.empty[Str \/ Int, MutMap[Var, MutCase]]
// def rec(t: MutCaseOf): Unit = traceUCS(s"[rec] ${t.describe}") {
// t match {
// case Consequent(term) => ()
// case MissingCase => ()
// case IfThenElse(_, whenTrue, whenFalse) =>
// rec(whenTrue)
// rec(whenFalse)
// case Match(scrutinee, branches, default) =>
// val key = getScurtineeKey(scrutinee)
// val patternMap = m.getOrElseUpdate(key, MutMap.empty)
// branches.foreach {
// case mutCase @ MutCase.Literal(literal, consequent) =>
// literal match {
// case tof @ Var(n) if n === "true" || n === "false" =>
// if (!patternMap.contains(tof)) {
// patternMap += ((tof, mutCase))
// }
// case _ => () // TODO: Summarize literals.
// }
// rec(consequent)
// case mutCase @ MutCase.Constructor((className, _), consequent) =>
// if (!patternMap.contains(className)) {
// patternMap += ((className, mutCase))
// }
// rec(consequent)
// }
// default.foreach(rec)
// }
// }()
// rec(t)
// printlnUCS("Summarized patterns")
// if (m.isEmpty)
// printlnUCS(" <Empty>")
// else
// m.foreach { case (scrutinee, patterns) =>
// printlnUCS(s" * $scrutinee => " + patterns.keysIterator.mkString(", "))
// }
// Map.from(m.iterator.map { case (key, patternMap) => key -> Map.from(patternMap) })
// }(_ => "[summarizePatterns]")

/**
* Make a term from a mutable case tree.
* This should be called after exhaustiveness checking.
Expand Down Expand Up @@ -993,17 +951,6 @@ class Desugarer extends TypeDefs { self: Typer =>
className -> td.baseClasses.iterator.map(_.name).toList
} |> Map.from
Desugarer.transitiveClosure(superClassMap)
// ctx.tyDefs2
// val superClassMap = ctx.tyDefs2.iterator.map { case (className, dti) =>
// className -> dti.decl.body
// } |> Map.from
// printlnUCS("• ctx.tyDefs")
// if (superClassMap.isEmpty)
// printlnUCS(" * <Empty>")
// else
// superClassMap.foreach { case (className, superClassNames) =>
// printlnUCS(s" * $className <- ${superClassNames.mkString(", ")}")
// }
}(_ => "[getClassHierarchy]")
}

Expand Down
6 changes: 3 additions & 3 deletions shared/src/main/scala/mlscript/ucs/LetBinding.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ object LetBinding {

object Kind {
case object ScrutineeAlias extends Kind {
override def toString(): String = "scrutinee alias"
override def toString: String = "scrutinee alias"
}
case object FieldExtraction extends Kind {
override def toString(): String = "pattern destruction"
override def toString: String = "pattern destruction"
}
case object InterleavedLet extends Kind {
override def toString(): String = "interleaved let"
override def toString: String = "interleaved let"
}
}
}
Expand Down
1 change: 0 additions & 1 deletion shared/src/test/diff/nu/repro_EvalNegNeg.mls
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ fun mk(n) = if n is
//│ where
//│ 'E :> Add['E] | Lit | Neg['E]

// TODO support this in UCS
:stats
TestLang.eval(mk(0))
//│ int
Expand Down
21 changes: 0 additions & 21 deletions shared/src/test/diff/tapl/NuSimplyTyped.mls
Original file line number Diff line number Diff line change
@@ -1,27 +1,6 @@
:NewParser
:NewDefs

:escape
// You can push debug messages to this magic array.
let Array: { from: anything => { push: anything => anything, join: string => string } }
let _Array = Array
let logs: { push: anything => anything, join: string => string } = _Array.from([])
let debug: anything => anything = x => logs.push(x)
fun showDebug = logs.join("\n")
//│ let Array: {from: anything -> {join: string -> string, push: anything -> anything}}
//│ let _Array: {from: anything -> {join: string -> string, push: anything -> anything}}
//│ let logs: {join: string -> string, push: anything -> anything}
//│ let debug: anything -> anything
//│ fun showDebug: string
//│ Array
//│ = <missing implementation>
//│ _Array
//│ = [Function: Array]
//│ logs
//│ = []
//│ debug
//│ = [Function: debug]

let str = toString
fun concat2(a, b) = concat(a)(b)
fun concat3(a, b, c) = concat2(a, concat2(b, c))
Expand Down
21 changes: 0 additions & 21 deletions shared/src/test/diff/tapl/NuUntyped.mls
Original file line number Diff line number Diff line change
@@ -1,27 +1,6 @@
:NewParser
:NewDefs

:escape
// You can push debug messages to this magic array.
let Array: { from: anything => { push: anything => anything, join: string => string } }
let _Array = Array
let logs: { push: anything => anything, join: string => string } = _Array.from([])
let debug: anything => anything = x => logs.push(x)
fun showDebug = logs.join("\n")
//│ let Array: {from: anything -> {join: string -> string, push: anything -> anything}}
//│ let _Array: {from: anything -> {join: string -> string, push: anything -> anything}}
//│ let logs: {join: string -> string, push: anything -> anything}
//│ let debug: anything -> anything
//│ fun showDebug: string
//│ Array
//│ = <missing implementation>
//│ _Array
//│ = [Function: Array]
//│ logs
//│ = []
//│ debug
//│ = [Function: debug]

fun concat2(a, b) = concat(a)(b)
fun concat3(a, b, c) = concat2(a, concat2(b, c))
fun concat4(a, b, c, d) = concat2(a, concat3(b, c, d))
Expand Down
Loading