Skip to content

Commit

Permalink
WIP: Fix op parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
NeilKleistGao committed Oct 15, 2023
1 parent b234cd9 commit a645b6d
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 61 deletions.
80 changes: 38 additions & 42 deletions shared/src/main/scala/mlscript/NewParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -935,53 +935,49 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo

final def exprCont(acc: Term, prec: Int, allowNewlines: Bool)(implicit et: ExpectThen, fe: FoundErr, l: Line, qenv: Set[Str], quoted: IsQuoted): IfBody \/ Term = wrap(prec, s"`$acc`", allowNewlines) { l =>
cur match {
case (QUOTE, l0) :: _ if quoted === false => // TODO: refactor
case (QUOTE, l) :: (KEYWORD(opStr @ "=>"), l0) :: _ if opPrec(opStr)._1 > prec && quoted === false =>
consume
cur match {
case (KEYWORD(opStr @ "=>"), l0) :: _ if opPrec(opStr)._1 > prec =>
consume
val newQenv = declQenv(acc)
val rhs = expr(1)(fe, implicitly, qenv ++ newQenv, quoted)
val param = acc match {
case t: Tup => t
case _ => PlainTup(acc)
}
val res = rhs match {
case Quoted(rhs) => Quoted(Lam(param, rhs))
case _ => Quoted(Lam(param, Unquoted(rhs)))
}
exprCont(res, prec, allowNewlines)
case (br @ BRACKETS(Round, toks), loc) :: _ =>
consume
val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()).map {
case nme -> Fld(flgs, t) => t match {
case Quoted(t) => nme -> Fld(flgs, t)
case _ => nme -> Fld(flgs, Unquoted(t))
}
}
val res = acc match {
case Quoted(acc) => App(acc, Tup(as).withLoc(S(loc)))
case _ => App(Unquoted(acc), Tup(as).withLoc(S(loc)))
}
exprCont(Quoted(res), prec, allowNewlines)
case (IDENT(opStr, true), l0) :: _ if /* isInfix(opStr) && */ opPrec(opStr)._1 > prec =>
consume
val v = Var(opStr).withLoc(S(l0))
// printDbg(s">>> $opStr ${opPrec(opStr)}")
exprOrIf(opPrec(opStr)._2) match {
case L(rhs) =>
err((
msg"quote syntax is not supported yet." -> S(l0) :: Nil))
R(Var("<error>"))
case R(rhs) =>
// TODO: match opStr
exprCont(quoteOp(acc, rhs, v), prec, allowNewlines)
}
case _ =>
consume
val newQenv = declQenv(acc)
val rhs = expr(1)(fe, implicitly, qenv ++ newQenv, quoted)
val param = acc match {
case t: Tup => t
case _ => PlainTup(acc)
}
val res = rhs match {
case Quoted(rhs) => Quoted(Lam(param, rhs))
case _ => Quoted(Lam(param, Unquoted(rhs)))
}
exprCont(res, prec, allowNewlines)
case (QUOTE, l) :: (br @ BRACKETS(Round, toks), loc) :: _ if quoted === false =>
consume
consume
val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()).map {
case nme -> Fld(flgs, t) => t match {
case Quoted(t) => nme -> Fld(flgs, t)
case _ => nme -> Fld(flgs, Unquoted(t))
}
}
val res = acc match {
case Quoted(acc) => App(acc, Tup(as).withLoc(S(loc)))
case _ => App(Unquoted(acc), Tup(as).withLoc(S(loc)))
}
exprCont(Quoted(res), prec, allowNewlines)
case (QUOTE, l) :: (IDENT(opStr, true), l0) :: _ if /* isInfix(opStr) && */ opPrec(opStr)._1 > prec && quoted === false =>
consume
consume
val v = Var(opStr).withLoc(S(l0))
// printDbg(s">>> $opStr ${opPrec(opStr)}")
exprOrIf(opPrec(opStr)._2) match {
case L(rhs) =>
err((
msg"quote syntax is not supported yet." -> S(l0) :: Nil))
R(Var("<error>"))
case R(rhs) =>
// TODO: match opStr to support with etc.
exprCont(quoteOp(acc, rhs, v), prec, allowNewlines)
}
case (QUOTE, l) :: _ => R(acc)
case (KEYWORD(opStr @ "=>"), l0) :: (NEWLINE, l1) :: _ if opPrec(opStr)._1 > prec =>
consume
val rhs = Blk(typingUnit.entities)
Expand Down
32 changes: 13 additions & 19 deletions shared/src/test/diff/qq/NuSyntax.mls
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ run(x `=> x)(42)
`(1 + 1)
//│ Code[Int, nothing]


`1 `* `2 `+ `3
//│ Code[Int, nothing]

x `=> x `+ `1
//│ Code[Int -> Int, nothing]

Expand All @@ -29,11 +33,11 @@ y `=> `0 `- y
:e
z `=> z + 1
//│ ╔══[ERROR] Type mismatch in operator application:
//│ ║ l.30: z `=> z + 1
//│ ║ l.34: z `=> z + 1
//│ ║ ^^^^^
//│ ╙── expression of type `Code[?a, ?z]` is not an instance of `Int`
//│ ╔══[ERROR] Type mismatch in unquote:
//│ ║ l.30: z `=> z + 1
//│ ║ l.34: z `=> z + 1
//│ ║ ^^^^^
//│ ╙── operator application of type `Int` is not an instance of `Code[?a, ?z | ?b]`
//│ Code[anything -> error, nothing]
Expand All @@ -57,7 +61,7 @@ fun f(x: Code[Int, nothing]) =
:e
`let x = `0, y = 1 in x `+ y
//│ ╔══[ERROR] Type mismatch in unquote:
//│ ║ l.58: `let x = `0, y = 1 in x `+ y
//│ ║ l.62: `let x = `0, y = 1 in x `+ y
//│ ║ ^
//│ ╙── integer literal of type `1` is not an instance of type `Code`
//│ Code[Int, nothing]
Expand Down Expand Up @@ -87,27 +91,17 @@ fun foo(x) =
:pe
`(`42)
//│ ╔══[PARSE ERROR] Unexpected quote in expression position
//│ ║ l.88: `(`42)
//│ ║ l.92: `(`42)
//│ ╙── ^
//│ Code[42, nothing]

:pe
:e
:w
`(x `=> x)
//│ ╔══[PARSE ERROR] Unexpected quote in expression position
//│ ║ l.97: `(x `=> x)
//│ ╙── ^
//│ ╔══[PARSE ERROR] Unexpected '=>' in expression position
//│ ║ l.97: `(x `=> x)
//│ ╙── ^^
//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword
//│ ║ l.97: `(x `=> x)
//│ ╙── ^^^^^^^
//│ ╔══[ERROR] identifier not found: x
//│ ║ l.97: `(x `=> x)
//│ ╙── ^
//│ ╔══[PARSE ERROR] Unexpected quote here
//│ ║ l.100: `(x `=> x)
//│ ╙── ^
//│ ╔══[ERROR] identifier not found: x
//│ ║ l.97: `(x `=> x)
//│ ╙── ^
//│ ║ l.100: `(x `=> x)
//│ ╙── ^
//│ Code[error, nothing]

0 comments on commit a645b6d

Please sign in to comment.