Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Allow primes at the end of identifiers. #29

Merged
merged 1 commit into from
Sep 6, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,10 @@ trait Scanners extends ScannersCommon {
putChar(ch)
nextChar()
getIdentOrOperatorRest()
case '\'' =>
putChar(ch)
nextChar()
getPrimeRest()
case SU => // strangely enough, Character.isUnicodeIdentifierPart(SU) returns true!
finishNamed()
case _ =>
Expand All @@ -649,6 +653,13 @@ trait Scanners extends ScannersCommon {
}
}

private def getPrimeRest(): Unit =
if (ch == '\'') {
putChar(ch)
nextChar()
getPrimeRest()
} else finishNamed()

private def getOperatorRest(): Unit = (ch: @switch) match {
case '~' | '!' | '@' | '#' | '%' |
'^' | '*' | '+' | '-' | '<' |
Expand Down
1 change: 1 addition & 0 deletions src/library/scala/reflect/NameTransformer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ object NameTransformer {
enterOp('\\', "$bslash")
enterOp('?', "$qmark")
enterOp('@', "$at")
enterOp('\'', "$prime")

/** Replace operator symbols by corresponding `\$opname`.
*
Expand Down
7 changes: 7 additions & 0 deletions test/files/neg/primed-identifiers.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
primed-identifiers.scala:4: error: value b' is not a member of object a1
a1 b'c' // parses as a1 b' c'
^
primed-identifiers.scala:4: error: not found: value c'
a1 b'c' // parses as a1 b' c'
^
two errors found
13 changes: 13 additions & 0 deletions test/files/neg/primed-identifiers.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
object a1 {
def b(c: Char) = ???

a1 b'c' // parses as a1 b' c'
}

object a2 {
def b'(c: Int) = ???
def b(c: Char) = ???

val c' = 23
a2 b'c' // parses as a2 b' c'
}
48 changes: 48 additions & 0 deletions test/files/pos/primed-identifiers.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
object Test {
val l = List("Identifiers", "with", "primes", "!")

val l' = l map(_.length)

val l'' = l zip l'

val l''' = l''.reverse

object a1 {
def b(c: Char) = ???

a1 b 'c'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scalac would parse a1 b'c' as a1.b('c'), while the Typelevel compiler would parse it as a1.b'(c'). Not sure if this is something permitted under your compatibility guidelines, but you should probably warn this (or require a language import).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a1 b'c' parsing correctly sort of strikes me as a bug, though? Shouldn't it require a space?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, Iulian! It's also an issue with symbol literals, unsurprisingly.

Regardless of whether it's considered a bug (in Scalac) or not, it's a
difference, so we'll need to put it under a -Z flag.

Given there are likely to be several very subtle parsing differences like
this -- which in all likelihood don't affect anyone that much -- would it
make sense to group them under a single -Z flag?

On 18 September 2014 13:15, Nami-Doc notifications@github.com wrote:

In test/files/pos/primed-identifiers.scala:

@@ -0,0 +1,48 @@
+object Test {

  • val l = List("Identifiers", "with", "primes", "!")
  • val l' = l map(_.length)
  • val l'' = l zip l'
  • val l''' = l''.reverse
  • object a1 {
  • def b(c: Char) = ???
  • a1 b 'c'

a1 b'c' parsing correctly sort of strikes me as a bug, though? Shouldn't
it require a space?


Reply to this email directly or view it on GitHub
https://github.com/typelevel/scala/pull/29/files#r17723052.

Jon Pretty | @propensive

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Nami-Doc it's not a bug, according to the grammar in the SLS. Generally, space is not required between tokens (that's why you can write foo(x) without any space between the 4 tokens).

@propensive a -Z flag would work, but why not an import language.typelevel.syntax, or something like that?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dragos language flags work by using implicits, they're not in scope during the parser (i.e. it hasn't even gotten to typing, yet) - we need to figure out a solution for this.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've only got my/Martin's suggestion of passing both possible parsings
through to the typer, somehow. But I can't imagine how this could be any
less terrible than it sounds.
On 18 Sep 2014 15:14, "Brian McKenna" notifications@github.com wrote:

In test/files/pos/primed-identifiers.scala:

@@ -0,0 +1,48 @@
+object Test {

  • val l = List("Identifiers", "with", "primes", "!")
  • val l' = l map(_.length)
  • val l'' = l zip l'
  • val l''' = l''.reverse
  • object a1 {
  • def b(c: Char) = ???
  • a1 b 'c'

@dragos https://github.com/dragos language flags work by using
implicits, they're not in scope during the parser (i.e. it hasn't even
gotten to typing, yet) - we need to figure out a solution for this.


Reply to this email directly or view it on GitHub
https://github.com/typelevel/scala/pull/29/files#r17728891.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I'm pretty certain that aint gonna happen.

Notice that the name is MutableSettings, though. What if the Parser were to... mutate them? 👿

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, the name MutableSettings was intended as documentation, not as guidance.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@puffnfresh spot on about imports... too bad.

}

object a2 {
def b'(c: Int) = ???
def b(c: Char) = ???

a2 b' 23
a2 b'23

val i = 23
a2 b'i

val c' = 23
a2 b'c' // parses as a2 b' c'

a2 b 'c'
}

case object Foo'
case class Bar'(i: Int)

((): Any) match {
case foo': String => ???
case Foo' => ???
case Bar'(foo') => ???
}

val (x', y') = (13, 23)

for (z' <- List(x', y')) x'*2

type T' = Int
def foo[U', F'[_]](ft: F'[T'], fu: F'[U']) = (ft, fu)
}