diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index a1c2cb5e2..66361644f 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -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("")) - 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("")) + 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) diff --git a/shared/src/test/diff/qq/NuSyntax.mls b/shared/src/test/diff/qq/NuSyntax.mls index 97df10788..e0a3d0d41 100644 --- a/shared/src/test/diff/qq/NuSyntax.mls +++ b/shared/src/test/diff/qq/NuSyntax.mls @@ -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] @@ -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] @@ -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] @@ -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]