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

Add support for Dotty enums #901

Closed
xeno-by opened this issue May 28, 2017 · 11 comments
Closed

Add support for Dotty enums #901

xeno-by opened this issue May 28, 2017 · 11 comments

Comments

@xeno-by xeno-by modified the milestone: v1.9.0 Jun 5, 2017
@jonas
Copy link
Contributor

@jonas jonas commented Jun 8, 2017

@olafurpg
Copy link
Member

@olafurpg olafurpg commented Jun 26, 2017

After brainstorming with @allanrenucci on this ticket, here is our proposal.

  • New token: Token.Enum() extends Keyword
  • New Defn tree nodes:
Defn.Case(Name, Template) extends Stat with Member.Type
Defn.Enum(Mods, name: Name, Ctor.Primary, parents: Seq[Ctor.Call], Seq[Defn.Case]) extends Defn with Member.Type
  • Defn.Enum is used for plain enum (not enum class) like here
@annot enum Foo(x: Int) extends Bar {
  case Baz, Qux
  case Mux extends Foo() {
    def bar
  }
  // any other statement than Defn.Case is not allowed.
  def foo = 2 // ERROR
}
  • A new modifier, Mod.Enum(), which is used for "enum class", are regular Defn.Class
// enum class is a Defn.Class just like case classes
enum class Foo(x: Int) // Defn.Class(List(Mod.Enum()), Foo, ...)
  • Up for debate: should the parser validate Defn.Case in these cases?
// 1.
// case in companion of enum class must "extends"
enum class Foo
object Foo {
  case Bar extends Foo // OK
  case Buz // Error
}

// 2.
// comma separated cases cannot have templates or ctors
enum Foo {
  case Bar(x: Int), Buz           // Error
  case Muz[T], Buz                // Error
  case Baz extends Maan, Buz      // Error
  case Baz { def hello = 1 }, Buz // Error
  case Baz { def hello = 1 }      // OK
}
@xeno-by
Copy link
Member Author

@xeno-by xeno-by commented Jun 26, 2017

  1. How does one model a template for an enum class, e.g. in enum Option[+T] { case Some[+T](x: T); case None }? This doesn't seem to be included in the proposed data model.

  2. I don't think we can validate extends Foo in the parser. This requires name resolution, right?

  3. comma separated cases cannot have templates or ctors. This looks validatable, so I'd prefer we handled this early.

@olafurpg
Copy link
Member

@olafurpg olafurpg commented Jun 26, 2017

  1. plain enums don't have templates, early initializers are not supported, self annotations and non-Defn.Enum statements are not allowed in the template body.
  2. I was thinking of requiring at least one parent inside the companion, no naming resolution required
  3. sounds good
@xeno-by
Copy link
Member Author

@xeno-by xeno-by commented Jun 26, 2017

  1. Oh wait, I just realized that you're proposing to have both Defn.Enum and Mod.Enum. Why's that?
@allanrenucci
Copy link
Contributor

@allanrenucci allanrenucci commented Jun 26, 2017

Mod.Enum is for enum class as they seem to parse like normal case classes. Defn.Enum however can only contain Defn.Case

@xeno-by
Copy link
Member Author

@xeno-by xeno-by commented Jun 26, 2017

Ah I see. This makes sense.

@xeno-by
Copy link
Member Author

@xeno-by xeno-by commented Jun 26, 2017

Please wait a little bit before working on this. I'd like to get #907 in first.

@xeno-by xeno-by modified the milestones: v3.0, v2.0 Jul 5, 2017
@xeno-by xeno-by added the Trees label Jul 11, 2017
@xeno-by xeno-by removed this from the v3.0 milestone Jul 13, 2017
@allanrenucci
Copy link
Contributor

@allanrenucci allanrenucci commented Jul 22, 2017

I am not sure about the actual proposal for Defn.Case. Defn.Case are just like classes. They can have modifiers, type parameters and constructors.
Should we represent them as a modifier on Defn.Class (and Defn.Object when there is no constructor)?

@MasseGuillaume
Copy link
Collaborator

@MasseGuillaume MasseGuillaume commented Feb 17, 2018

The syntax might change a bit: lampepfl/dotty#4003

@olafurpg
Copy link
Member

@olafurpg olafurpg commented Oct 12, 2018

After discussions with @allanrenucci and @samuelchassot we came to this design for the current Dotty enums:

object Defn {
  // Identical to Defn.Class except `.templ.stats` can contain `Enum.Case` and `Enum.RepeatedCase`
  @ast class Enum(mods: List[Mod],
                  name: Type.Name,
                  tparams: List[Type.Param],
                  ctor: Ctor.Primary,
                  templ: Template) extends Defn with Member.Type
  object Enum {
    @ast class Name(value: Predef.String @nonEmpty)
      extends scala.meta.Name with Term.Ref with Member.Term
    // example:
    // enum Try {
    //   case Success(value: String)
    //   case Failure(e: Throwable)
    // }
    @ast class Case(mods: List[Mod],
                    name: Term.Name /* not Type.Name because only companion is visible */,
                    tparams: List[Type.Param],
                    ctor: Ctor.Primary,
                    inits: List[Init]) extends Defn with Member.Term {
      checkFields(
        parent.isEmpty || {
          val p = parent.get
          p.is[Template] && (p.parent.isEmpty || p.parent.get.is[Defn.Enum])
        }
      )
    }
    // example:
    // enum Color {
    //   case Red, Blue, Green
    // }
    @ast class RepeatedCase(mods: List[Mod], cases: List[Enum.Name]) extends Defn {
      checkFields(
        parent.isEmpty || {
          val p = parent.get
          p.is[Template] && (p.parent.isEmpty || p.parent.get.is[Defn.Enum])
        }
      )
    }
  }
}

@samuelchassot will work on this ticket over the coming weeks.

Currently, it's very un-ergonomic to extend the parser because every change requires recompiling semanticdb-scalac resulting in >1 minute turnaround times for tweaking the parser.

To make it faster to iterate on parser changes I created a new repository https://github.com/scalameta/trees that contains only the syntactic APIs. The repo is a fork of the main repo and only removes the SemanticDB-related tests. All source files are located in the same location as in the main repository.

tgodzik pushed a commit that referenced this issue Jun 24, 2020
First part supporting:

- Enums (based on, fixes #901)
- Union/Intersection types (implemented previously, verified nothing changed and new TCs)
- Given/Using (without given imports)
- Extension methods / blocks
- Opaque types
- Open classes
- Named type arguments (fixes #903) removed from dotty in the end
- Type Lambdas (implemented previously but syntax changed, aligned with new syntax - fixes #1332)
- Top level statements
- Macros
- inline functions and parameters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Linked pull requests

Successfully merging a pull request may close this issue.

5 participants
You can’t perform that action at this time.