GitHub PullRequestReviewCommentEvent at 2014-04-27 10:41:40
Repository: core
Actor: xeno-by
Payload: {"comment":{"url":"https://api.github.com/repos/scalareflect/core/pulls/comments/12028528","id":12028528,"diff_hunk":"@@ -18,329 +36,459 @@ import org.scalareflect.adt._\n // (Denys)    TODO: unhygienic quasiquotes\n // (Denys)    TODO: consider adding default values for case class fields whenever applicable\n // (Eugene)   TODO: pretty printer\n-// (Together) TODO: figure out which apis need to be moved to subclasses and which apis (Tree.annots, Type.typCtor, Type.args, Symbol.companion, Type.companion) need to be added for convenience\n+// (Together) TODO: figure out which apis need to be moved to subclasses and which apis (Tree.mods, Type.tpeCtor, Type.args, Symbol.companion, Type.companion) need to be added for convenience\n // (Together) TODO: implement scaladoc with palladium\n \n-@root trait Tree {\n-  def parent: Option[Tree] = ???\n-  override def equals(other: Any): Boolean = ???\n-  override def hashCode(): Int = ???\n-}\n \n-@branch trait Ref extends Tree {\n-  def sym: Symbol = ???\n-}\n+// TODO: invariants: tree should either have at least one non-trival token or be eq to it's empty value\n+// TODO: converter: double check conversion of `(f _)(x)` (bug 46)\n+// TODO: converter: need api to discern `class C` from `class C {}` as the second one has to have EmptyTree in the body\n \n-@branch trait Ident extends Ref {\n-  def value: String\n-  def isBackquoted: Boolean = ???\n-}\n+package core {\n+  @root trait Tree extends cbc.Trees.Tree {\n+    def parent: Option[Tree] = ???\n+    override def equals(other: Any): Boolean = ???\n+    override def hashCode(): Int = ???\n+  }\n \n-@branch trait Term extends Arg with Stmt.Template with Stmt.Block {\n-  def tpe: Type = ???\n-}\n-object Term {\n-  @branch trait Ref extends Term with core.Ref {\n-    def isPath: Boolean = isStableId || this.isInstanceOf[This]\n-    def isQualId: Boolean = this match {\n-      case _: Ident             => true\n-      case Select(qual: Ref, _) => qual.isQualId\n-      case _                    => false\n+  @branch trait Ref extends Tree {\n+    def sym: Symbol = ???\n+  }\n+\n+  @branch trait Ident extends Ref {\n+    def value: String\n+    def isBackquoted: Boolean\n+    def isRightAssocOp: Boolean = value.last != ':'\n+    def isUnaryOp: Boolean = unaryOps contains value\n+    def isAssignmentOp = value match {\n+      case \"!=\" | \"<=\" | \">=\" | \"\" => false\n+      case _                       => value.last == '=' && value.head != '=' && isOperatorPart(value.head)\n     }\n-    def isStableId: Boolean = this match {\n-      case _: Ident | _: SuperSelect => true\n-      case Select(qual: Ref, _)      => qual.isPath\n-      case _                         => false\n+    // opPrecedence?\n+    def precedence: Int =\n+      if (isAssignmentOp) 0\n+      else if (isScalaLetter(value.head)) 1\n+      else (value.head: @scala.annotation.switch) match {\n+        case '|'             => 2\n+        case '^'             => 3\n+        case '&'             => 4\n+        case '=' | '!'       => 5\n+        case '<' | '>'       => 6\n+        case ':'             => 7\n+        case '+' | '-'       => 8\n+        case '*' | '/' | '%' => 9\n+        case _               => 10\n+      }\n+    def isVarPattern: Boolean = this match {\n+      case _: Term.Ident => !isBackquoted && value.head.isLower && value.head.isLetter\n+      case _             => false\n     }\n-  }\n-  @leaf class This(qual: Option[core.Ident]) extends Ref\n-  @leaf class Ident(value: scala.Predef.String) extends core.Ident with Ref with Pat with Symbol {\n-    require(!keywords.contains(value) || isBackquoted)\n-    def isBinder: Boolean = ???\n-    def annots: List[Annot] = Nil\n-  }\n-  @leaf class SuperSelect(qual: Option[core.Ident], supertyp: Option[Type.Ident], selector: Term.Ident) extends Ref\n-  @leaf class Select(qual: Ref, selector: Term.Ident) extends Ref with Pat\n+    def isInterpolationId: Boolean = ???\n \n-  @leaf class Interpolate(prefix: Ident, parts: List[Lit.String] @nonEmpty, args: List[Term]) extends Term {\n-    // (Denys) TODO: also check that prefix is alphanumeric\n-    require(parts.length == args.length + 1)\n+    private def isOperatorPart(ch: Char) = ???\n+    private def isScalaLetter(ch: Char) = ???\n   }\n-  @leaf class Apply(fun: Term, args: List[Arg]) extends Term\n-  @leaf class ApplyRight(lhs: Term, op: Ident, rhs: Term) extends Term {\n-    require(op.value.last == ':')\n-  }\n-  @leaf class TypeApply(fun: Term, args: List[Type] @nonEmpty) extends Term\n-  @leaf class Assign(lhs: Term.Ref, rhs: Term) extends Term\n-  @leaf class Update(expr: Term, args: List[List[Term]] @nonEmpty) extends Term\n-  @leaf class Return(expr: Term) extends Term\n-  @leaf class Throw(expr: Term) extends Term\n-  @leaf class Ascribe(expr: Term, typ: Type) extends Term\n-  @leaf class Annotate(expr: Term, annots: List[Annot] @nonEmpty) extends Term with HasAnnots\n-  @leaf class Tuple(elements: List[Term] @nonEmpty) extends Term\n-  @leaf class Block(stats: List[Stmt.Block]) extends Term\n-  @leaf class If(cond: Term, thenp: Term, elsep: Term) extends Term\n-  @leaf class Match(scrut: Term, cases: List[Aux.Case] @nonEmpty) extends Term\n-  @leaf class Try(expr: Term, catchp: List[Aux.Case], finallyp: Option[Term]) extends Term\n-  @leaf class Function(params: List[Param.Function], body: Term) extends Term {\n-    require(params.length == 1 || !params.exists(_.annots.contains(Annot.Implicit)))\n-  }\n-  @leaf class PartialFunction(cases: List[Aux.Case] @nonEmpty) extends Term\n-  @leaf class While(expr: Term, body: Term) extends Term\n-  @leaf class Do(body: Term, expr: Term) extends Term\n-  @leaf class For(enums: List[Enum] @nonEmpty, body: Term) extends Term {\n-    require(enums.head.isInstanceOf[Enum.Generator])\n-  }\n-  @leaf class ForYield(enums: List[Enum] @nonEmpty, body: Term) extends Term\n-  @leaf class New(templ: Aux.Template) extends Term\n-  // (Denys) TODO: might need additional validation\n-  @leaf class Placeholder() extends Term\n-  @leaf class Eta(term: Term) extends Term\n-}\n \n-@branch trait Type extends Tree {\n-  def <:< (other: Type): Boolean = ???\n-  def weak_<:<(other: Type): Boolean = ???\n-  def widen: Type = ???\n-  def dealias: Type = ???\n-  def erasure: Type = ???\n-  // TODO: can we somehow inherit certain flags from type symbols here, s.t. we can write `t\"T\".isCaseClass`?\n-}\n-object Type {\n-  @branch trait Ref extends Type with core.Ref\n-  @leaf class Ident(value: String) extends core.Ident with Ref {\n-    require(!keywords.contains(value) || isBackquoted)\n+  @branch trait Term extends Arg with Stmt.Template with Stmt.Block with Aux.Catch {\n+    def tpe: Type = ???\n   }\n-  @leaf class Select(qual: Term.Ref, name: Type.Ident) extends Ref {\n-    require(qual.isPath)\n-  }\n-  @leaf class SuperSelect(qual: Option[core.Ident], supertyp: Option[Type.Ident], selector: Type.Ident) extends Ref\n-  @leaf class Project(qual: Type, name: Type.Ident) extends Ref\n-  @leaf class Singleton(ref: Term.Ref) extends Ref {\n-    require(ref.isPath)\n+  object Term {\n+    @branch trait Ref extends Term with core.Ref {\n+      def isPath: Boolean = isStableId || this.isInstanceOf[This]\n+      def isQualId: Boolean = this match {\n+        case _: Ident             => true\n+        case Select(qual: Ref, _) => qual.isQualId\n+        case _                    => false\n+      }\n+      def isStableId: Boolean = this match {\n+        case _: Ident | _: SuperSelect => true\n+        case Select(qual: Ref, _)      => qual.isPath\n+        case _                         => false\n+      }\n+    }\n+    @leaf class This(qual: Option[core.Ident]) extends Ref\n+    @leaf class Ident(value: scala.Predef.String @nonEmpty, isBackquoted: Boolean = false) extends core.Ident with Ref with Pat with Symbol {\n+      require(!keywords.contains(value) || isBackquoted)\n+      def isBinding: Boolean = ???\n+      def mods: List[Mod] = Nil\n+    }\n+    @leaf class SuperSelect(qual: Option[core.Ident], supertpe: Option[Type.Ident], selector: Term.Ident) extends Ref\n+    @leaf class Select(qual: Term, selector: Term.Ident) extends Ref with Pat\n+\n+    @leaf class Interpolate(prefix: Ident, parts: List[Lit.String] @nonEmpty, args: List[Term]) extends Term {\n+      require(prefix.isInterpolationId)\n+      require(parts.length == args.length + 1)\n+    }\n+    @leaf class Apply(fun: Term, args: List[Arg]) extends Term\n+    @leaf class ApplyType(fun: Term, args: List[Type] @nonEmpty) extends Term\n+    @leaf class ApplyRight(lhs: Term, op: Ident, targs: List[Type], rhs: Term) extends Term {\n+      require(op.isRightAssocOp)\n+    }\n+    @leaf class ApplyUnary(op: Ident, arg: Term) extends Term {\n+      require(op.isUnaryOp)\n+    }\n+    @leaf class Assign(lhs: Term.Ref, rhs: Term) extends Term\n+    @leaf class Update(lhs: Apply, rhs: Term) extends Term\n+    @leaf class Return(expr: Term) extends Term\n+    @leaf class Throw(expr: Term) extends Term\n+    @leaf class Ascribe(expr: Term, acsribedTpe: Type) extends Term\n+    @leaf class Annotate(expr: Term, mods: List[Mod] @nonEmpty) extends Term with Has.Mods\n+    @leaf class Tuple(elements: List[Term] @nonEmpty) extends Term\n+    @leaf class Block(stats: List[Stmt.Block]) extends Term\n+    @leaf class If(cond: Term, thenp: Term, elsep: Term) extends Term\n+    @leaf class Match(scrut: Term, cases: Aux.Cases @nonEmpty) extends Term\n+    @leaf class Try(expr: Term, catchp: Option[Aux.Catch], finallyp: Option[Term]) extends Term\n+    @leaf class Function(params: List[Aux.Param], body: Term) extends Term {\n+      require(params.forall(_.default.isEmpty))\n+      require(params.length == 1 || !params.exists(_.mods.contains(Mod.Implicit)))\n+    }\n+    @leaf class PartialFunction(cases: Aux.Cases) extends Term\n+    @leaf class While(expr: Term, body: Term) extends Term\n+    @leaf class Do(body: Term, expr: Term) extends Term\n+    @leaf class For(enums: List[Enum] @nonEmpty, body: Term) extends Term {\n+      require(enums.head.isInstanceOf[Enum.Generator])\n+    }\n+    @leaf class ForYield(enums: List[Enum] @nonEmpty, body: Term) extends Term\n+    @leaf class New(templ: Aux.Template) extends Term\n+    // (Denys) TODO: might need additional validation\n+    @leaf class Placeholder() extends Term\n+    @leaf class Eta(term: Term) extends Term\n   }\n \n-  // TODO: validate that typ can actually be applied\n-  @leaf class Apply(typ: Type, args: List[Type] @nonEmpty) extends Type\n-  @leaf class Function(params: Type, res: Type) extends Type\n-  @leaf class Tuple(elements: List[Type] @nonEmpty) extends Type\n-  @leaf class Refine(typs: List[Type], stats: List[Stmt.Refine] @nonEmpty) extends Type\n-  @leaf class Existential(typ: Type, quants: List[Stmt.Existential] @nonEmpty) extends Type\n-  @leaf class Annotate(typ: Type, annots: List[Annot] @nonEmpty) extends Type with HasAnnots\n-  // (Denys) TODO: need to validate that placeholder appears within one of allowed contexts (e.g. `type T = _` is illegal)\n-  @leaf class Placeholder(bounds: Aux.TypeBounds) extends Type\n-}\n+  @branch trait Type extends Tree {\n+    def <:< (other: Type): Boolean = ???\n+    def weak_<:<(other: Type): Boolean = ???\n+    def widen: Type = ???\n+    def dealias: Type = ???\n+    def erasure: Type = ???\n+    def superclasses: List[Type] = ???\n+    def subclasses: List[Type] = ???\n+    // TODO: can we somehow inherit certain flags from type symbols here, s.t. we can write `t\"T\".isCaseClass`?\n+    // TODO: simple type validation\n+  }\n+  object Type {\n+    @branch trait Ref extends Type with core.Ref\n+    @leaf class Ident(value: String @nonEmpty, isBackquoted: Boolean = false) extends core.Ident with Ref {\n+      require(!keywords.contains(value) || isBackquoted)\n+    }\n+    @leaf class Select(qual: Term.Ref, name: Type.Ident) extends Ref {\n+      require(qual.isPath)\n+    }\n+    @leaf class SuperSelect(qual: Option[core.Ident], supertpe: Option[Type.Ident], selector: Type.Ident) extends Ref\n+    @leaf class Project(qual: Type, name: Type.Ident) extends Ref\n+    @leaf class Singleton(ref: Term.Ref) extends Ref {\n+      require(ref.isPath)\n+    }\n \n-@branch trait Pat extends Tree {\n-  // TODO: how should tpe look like? inTpe/outTpe?\n-}\n-object Pat {\n-  @leaf class Wildcard() extends Pat\n-  @leaf class SeqWildcard() extends Pat\n-  @leaf class Bind(lhs: Term.Ident, rhs: Pat) extends Pat\n-  @leaf class Alternative(lhs: Pat, rhs: Pat) extends Pat\n-  @leaf class Tuple(elements: List[Pat] @nonEmpty) extends Pat\n-  @leaf class Extract(ref: Term.Ref, elements: List[Pat]) extends Pat {\n-    require(ref.isStableId)\n+    // TODO: validate that tpe can actually be applied\n+    @leaf class Apply(tpe: Type, args: List[Type] @nonEmpty) extends Type\n+    @leaf class Function(params: List[Type], res: Type) extends Type\n+    @leaf class Tuple(elements: List[Type] @nonEmpty) extends Type\n+    @leaf class Compound(tpes: List[Type], refinement: List[Stmt.Refine] @nonEmpty) extends Type\n+    @leaf class Existential(tpe: Type, quants: List[Stmt.Existential] @nonEmpty) extends Type\n+    @leaf class Annotate(tpe: Type, mods: List[Mod] @nonEmpty) extends Type with Has.Mods\n+    // (Denys) TODO: need to validate that placeholder appears within one of allowed contexts (e.g. `type T = _` is illegal)\n+    @leaf class Placeholder(bounds: Aux.TypeBounds) extends Type\n   }\n-  @leaf class Interpolate(prefix: Term.Ident, parts: List[Lit.String] @nonEmpty, args: List[Pat]) extends Pat {\n-    // (Denys) TODO: check that prefix is alphanumeric\n-    require(parts.length == args.length + 1)\n+\n+  @branch trait Pat extends Tree {\n+    // TODO: how should tpe look like? inTpe/outTpe?\n   }\n-  @leaf class Ascribe(lhs: Pat, rhs: Type) extends Pat {\n-    require(lhs.isInstanceOf[Pat.Wildcard] || lhs.isInstanceOf[Term.Ident])\n+  object Pat {\n+    @leaf class Wildcard() extends Pat\n+    @leaf class SeqWildcard() extends Pat\n+    @leaf class Bind(lhs: Term.Ident, rhs: Pat) extends Pat\n+    @leaf class Alternative(lhs: Pat, rhs: Pat) extends Pat\n+    @leaf class Tuple(elements: List[Pat] @nonEmpty) extends Pat\n+    @leaf class Extract(ref: Term.Ref, targs: List[Type], elements: List[Pat]) extends Pat {\n+      require(ref.isStableId)\n+    }\n+    @leaf class Interpolate(prefix: Term.Ident, parts: List[Lit.String] @nonEmpty, args: List[Pat]) extends Pat {\n+      require(prefix.isInterpolationId)\n+      require(parts.length == args.length + 1)\n+    }\n+    @leaf class Typed(lhs: Pat, rhs: Type) extends Pat {\n+      require(lhs.isInstanceOf[Pat.Wildcard] || lhs.isInstanceOf[Term.Ident])\n+    }\n   }\n-}\n \n-@branch trait Symbol extends Tree with HasAnnots {\n-  def owner: Symbol = ???\n-  def ref: core.Ref = ???\n-  def overrides: List[Symbol] = ???\n-  // TODO: knownDirectSubclasses => can we replace this with an optimized query?\n-  // TODO: methods from Scope. do we need them here? how do we deduplicate wrt types?\n-}\n-\n-@branch trait Decl extends Symbol with Stmt.Template with Stmt.Refine\n-object Decl {\n-  @leaf class Val(annots: List[Annot], pats: List[Pat] @nonEmpty, typ: Type) extends Decl with Stmt.Existential\n-  @leaf class Var(annots: List[Annot], pats: List[Pat] @nonEmpty, typ: Type) extends Decl\n-  @leaf class Def(annots: List[Annot], name: Term.Ident, tparams: List[TypeParam.Def],\n-                  paramss: List[List[Param.Def]], implicits: List[Param.Def], typ: Option[Type]) extends Decl\n-  @leaf class Type(annots: List[Annot], name: core.Type.Ident, tparams: List[TypeParam.Type],\n-                   bounds: Aux.TypeBounds) extends Decl with Stmt.Existential\n-}\n-\n-@branch trait Defn extends Symbol\n-object Defn {\n-  @leaf class Val(annots: List[Annot], pats: List[Pat] @nonEmpty, typ: Option[Type], rhs: Term) extends Defn with Stmt.Block with Stmt.Template\n-  @leaf class Var(annots: List[Annot], pats: List[Pat] @nonEmpty, typ: Option[Type], rhs: Option[Term]) extends Defn with Stmt.Block with Stmt.Template {\n-    require(typ.nonEmpty || rhs.nonEmpty)\n-  }\n-  @leaf class Def(annots: List[Annot], name: Term.Ident, tparams: List[TypeParam.Def],\n-                  paramss: List[List[Param.Def]], implicits: List[Param.Def],\n-                  typ: Option[Type], body: Term) extends Defn with Stmt.Block with Stmt.Template\n-  @leaf class Macro(annots: List[Annot], name: Term.Ident, tparams: List[TypeParam.Def],\n-                    paramss: List[List[Param.Def]], implicits: List[Param.Def],\n-                    typ: Type, body: Term) extends Defn with Stmt.Block with Stmt.Template\n-  @leaf class Type(annots: List[Annot], name: core.Type.Ident, tparams: List[TypeParam.Type], body: Type)\n-                   extends Defn with Stmt.Refine with Stmt.Block with Stmt.Template\n-  @leaf class Class(annots: List[Annot], name: core.Type.Ident, tparams: List[TypeParam.Def],\n-                    val ctor: Option[Ctor.Primary], templ: Aux.Template)\n-                    extends Defn with Stmt.TopLevel with Stmt.Block with Stmt.Template {\n-    def companion: Option[Object] = ???\n+  @branch trait Symbol extends Tree with Has.Mods {\n+    def owner: Symbol = ???\n+    def ref: core.Ref = ???\n+    def overrides: List[Symbol] = ???\n+    def doc: Option[Mod.Doc] = ???\n+    // TODO: knownDirectSubclasses => can we replace this with an optimized query?\n+    // TODO: methods from Scope. do we need them here? how do we deduplicate wrt types?\n   }\n-  @leaf class Trait(annots: List[Annot], name: core.Type.Ident, tparams: List[TypeParam.Type],\n-                    templ: Aux.Template) extends Defn with Stmt.TopLevel with Stmt.Block with Stmt.Template {\n-    def isInterface: Boolean = templ.stats.forall(_.isInstanceOf[Decl])\n-    def companion: Option[Object] = ???\n+  object Symbol {\n+    @branch trait Field extends Symbol\n+    @branch trait Val extends Field with Has.DeclaredType\n+    @branch trait Var extends Field with Has.DeclaredType\n+    @branch trait Def extends Symbol with Stmt.Template\n+    @branch trait Type extends Symbol\n+    @branch trait Template extends Symbol with Stmt.TopLevel with Stmt.Block\n   }\n-  @leaf class Object(annots: List[Annot], name: Term.Ident, templ: Aux.Template)\n-                     extends Defn with Stmt.TopLevel with Stmt.Block with Stmt.Template {\n-    def companion: Option[Defn] = ??? // TODO: Class | Trait\n+\n+  @branch trait Decl extends Symbol with Stmt.Template with Stmt.Refine\n+  object Decl {\n+    @leaf class Val(mods: List[Mod],\n+                    pats: List[Term.Ident] @nonEmpty,\n+                    declTpe: Option[core.Type] @nonEmpty) extends Decl with Stmt.Existential with Symbol.Val\n+    @leaf class Var(mods: List[Mod],\n+                    pats: List[Term.Ident] @nonEmpty,\n+                    declTpe: Option[core.Type] @nonEmpty) extends Decl with Symbol.Var\n+    @leaf class Def(mods: List[Mod],\n+                    name: Term.Ident,\n+                    tparams: List[Aux.TypeParam],\n+                    paramss: List[List[Aux.Param]],\n+                    implicits: List[Aux.Param],\n+                    declTpe: Option[core.Type] @nonEmpty) extends Decl with Symbol.Def with Has.DeclaredType {\n+      require((paramss :+ implicits).flatten.forall(_.declTpe.nonEmpty))\n+    }\n+    @leaf class Procedure(mods: List[Mod],\n+                          name: Term.Ident,\n+                          tparams: List[Aux.TypeParam],\n+                          paramss: List[List[Aux.Param]],\n+                          implicits: List[Aux.Param]) extends Decl with Symbol.Def\n+    @leaf class Type(mods: List[Mod],\n+                     name: core.Type.Ident,\n+                     tparams: List[Aux.TypeParam],\n+                     bounds: Aux.TypeBounds) extends Decl with Stmt.Existential with Symbol.Type\n   }\n-  @leaf class Package(name: Term.Ref, stats: List[Stmt.TopLevel]) extends Defn with Stmt.TopLevel {\n-    require(name.isQualId)\n-    def annots: List[Annot] = Nil\n+\n+  @branch trait Defn extends Symbol with Stmt.Block with Stmt.Template\n+  object Defn {\n+    @leaf class Val(mods: List[Mod],\n+                    pats: List[Pat] @nonEmpty,\n+                    declTpe: Option[core.Type],\n+                    rhs: Term) extends Defn with Symbol.Val\n+    @leaf class Var(mods: List[Mod],\n+                    pats: List[Pat] @nonEmpty,\n+                    declTpe: Option[core.Type],\n+                    rhs: Option[Term]) extends Defn with Symbol.Var {\n+      require(rhs.nonEmpty || pats.forall(_.isInstanceOf[Term.Ident]))\n+      require(declTpe.nonEmpty || rhs.nonEmpty)\n+    }\n+    @leaf class Def(mods: List[Mod],\n+                    name: Term.Ident,\n+                    tparams: List[Aux.TypeParam],\n+                    paramss: List[List[Aux.Param]],\n+                    implicits: List[Aux.Param],\n+                    declTpe: Option[core.Type],\n+                    body: Term) extends Defn with Symbol.Def with Has.DeclaredType\n+    @leaf class Procedure(mods: List[Mod],\n+                          name: Term.Ident,\n+                          tparams: List[Aux.TypeParam],\n+                          paramss: List[List[Aux.Param]],\n+                          implicits: List[Aux.Param],\n+                          body: Term.Block) extends Defn with Symbol.Def\n+    @leaf class Type(mods: List[Mod],\n+                     name: core.Type.Ident,\n+                     tparams: List[Aux.TypeParam],\n+                     body: core.Type) extends Defn with Stmt.Refine with Symbol.Type\n+    @leaf class Class(mods: List[Mod],\n+                      name: core.Type.Ident,\n+                      tparams: List[Aux.TypeParam],\n+                      ctor: Ctor.Primary,\n+                      templ: Aux.Template) extends Defn with Symbol.Template {\n+      def companion: Option[Object] = ???\n+    }\n+    @leaf class Trait(mods: List[Mod],\n+                      name: core.Type.Ident,\n+                      tparams: List[Aux.TypeParam],\n+                      templ: Aux.Template) extends Defn with Symbol.Template {\n+      require(templ.parents.forall(_.argss.isEmpty))\n+      def isInterface: Boolean = templ.stats.forall(_.isInstanceOf[Decl])\n+      def companion: Option[Object] = ???\n+    }\n+    @leaf class Object(mods: List[Mod],\n+                       name: Term.Ident,\n+                       templ: Aux.Template) extends Defn with Symbol.Template {\n+      def companion: Option[Symbol.Template] = ??? // TODO: Class | Trait\n+    }\n   }\n-  @leaf class PackageObject(annots: List[Annot], name: Term.Ident, templ: Aux.Template) extends Defn with Stmt.TopLevel\n-}\n \n-@branch trait Ctor extends Symbol {\n-  def paramss: List[List[Param.Def]]\n-  def implicits: List[Param.Def]\n-}\n-object Ctor {\n-  @leaf class Primary(annots: List[Annot], paramss: List[List[Param.Def]] = Nil, implicits: List[Param.Def] = Nil) extends Ctor\n-  @leaf class Secondary(annots: List[Annot], paramss: List[List[Param.Def]], implicits: List[Param.Def],\n-                        primaryCtorArgss: List[List[Term]]) extends Ctor with Stmt.Template\n-}\n+  @branch trait Ctor extends Symbol\n+  object Ctor {\n+    @leaf class Primary(mods: List[Mod] = Nil,\n+                        paramss: List[List[Aux.Param]] = Nil,\n+                        implicits: List[Aux.Param] = Nil) extends Ctor\n+    @leaf class Secondary(mods: List[Mod] = Nil,\n+                          paramss: List[List[Aux.Param]] @nonEmpty = List(Nil),\n+                          implicits: List[Aux.Param] = Nil,\n+                          primaryCtorArgss: List[List[Arg]] = Nil,\n+                          stats: List[Stmt.Block] = Nil) extends Ctor with Stmt.Template {\n+    }\n+  }\n \n-object Stmt {\n-  @branch trait TopLevel extends Tree\n-  @branch trait Template extends Block\n-  @branch trait Block extends Refine\n-  @branch trait Refine extends Existential\n-  @branch trait Existential extends Tree\n-}\n+  object Stmt {\n+    @branch trait TopLevel extends Tree\n+    @branch trait Template extends Block\n+    @branch trait Block extends Refine\n+    @branch trait Refine extends Existential\n+    @branch trait Existential extends Tree\n+  }\n \n-@branch trait Scope extends Tree {\n   // TODO: design scopes\n   // should include parents, self, members, methods, types, etc\n   // where things like methods should be Iterable[Symbol] + have apply(ident) and apply(symbol)\n-}\n+  @branch trait Scope extends Tree\n \n-@branch trait Lit extends Term with Pat\n-object Lit {\n-  // TODO: def apply and maybe Lit.value of sorts\n-  @leaf class Bool(value: scala.Boolean) extends Lit with Type\n-  @leaf class Int(value: scala.Int) extends Lit with Type\n-  @leaf class Long(value: scala.Long) extends Lit with Type\n-  @leaf class Float(value: scala.Float) extends Lit with Type\n-  @leaf class Double(value: scala.Double) extends Lit with Type\n-  @leaf class Char(value: scala.Char) extends Lit with Type\n-  @leaf class String(value: Predef.String) extends Lit with Type\n-  // TODO: not all symbols are representable as literals, e.g. scala.Symbol(\"\")\n-  @leaf class Symbol(value: scala.Symbol) extends Lit with Type\n-  @leaf class Null() extends Lit\n-  @leaf class Unit() extends Lit\n-}\n+  @branch trait Lit extends Term with Pat\n+  object Lit {\n+    // TODO: maybe add overloaded apply(value)\n+    // TODO: maybe add unapply(lit): Option[Any]\n+    @branch trait Bool extends Lit\n+    @leaf class True() extends Bool\n+    @leaf class False() extends Bool\n+    @leaf class Int(value: scala.Int) extends Lit with Type\n+    @leaf class Long(value: scala.Long) extends Lit with Type\n+    @leaf class Float(value: scala.Float) extends Lit with Type\n+    @leaf class Double(value: scala.Double) extends Lit with Type\n+    @leaf class Char(value: scala.Char) extends Lit with Type\n+    @leaf class String(value: Predef.String) extends Lit with Type\n+    // TODO: not all symbols are representable as literals, e.g. scala.Symbol(\"\")\n+    @leaf class Symbol(value: scala.Symbol) extends Lit with Type\n+    @leaf class Null() extends Lit\n+    @leaf class Unit() extends Lit\n+  }\n+\n+  @leaf class Import(clauses: List[Import.Clause] @nonEmpty) extends Stmt.TopLevel with Stmt.Template with Stmt.Block\n+  object Import {\n+    // TODO: validate that wildcard import can only be the last one in the list of sels\n+    @leaf class Clause(ref: Term.Ref, sels: List[Selector] @nonEmpty) extends Tree {\n+      require(ref.isStableId)\n+    }\n+\n+    @branch trait Selector extends Tree\n+    object Selector {\n+      @leaf class Wildcard() extends Selector\n+      // TODO: needs some kind of idents here but they can neither be term nor type\n+      @leaf class Name(name: String) extends Selector\n+      @leaf class Rename(from: String, to: String) extends Selector\n+      @leaf class Unimport(name: String) extends Selector\n+    }\n+  }\n \n-@leaf class Import(clauses: List[Import.Clause] @nonEmpty) extends Stmt.TopLevel with Stmt.Template with Stmt.Block\n-object Import {\n-  @leaf class Clause(ref: Term.Ref, sels: List[Selector] @nonEmpty) extends Tree {\n-    require(ref.isStableId)\n+  @branch trait Arg extends Tree\n+  object Arg {\n+    @leaf class Named(name: Term.Ident, arg: Term) extends Arg\n+    @leaf class Seq(arg: Term) extends Arg\n   }\n \n-  @branch trait Selector extends Tree\n-  object Selector {\n-    @leaf class Wildcard() extends Selector\n-    @leaf class Name(name: String) extends Selector\n-    @leaf class Rename(from: String, to: String) extends Selector\n-    @leaf class Unimport(name: String) extends Selector\n+  @branch trait Enum extends Tree\n+  object Enum {\n+    @leaf class Generator(pat: Pat, rhs: Term) extends Enum\n+    @leaf class Val(pat: Pat, rhs: Term) extends Enum\n+    @leaf class Guard(cond: Term) extends Enum\n   }\n-}\n \n-@branch trait Arg extends Tree\n-object Arg {\n-  @leaf class Named(name: Term.Ident, arg: Term) extends Arg\n-  @leaf class Seq(arg: Term) extends Arg\n-}\n+  @branch trait Mod extends Tree\n+  object Mod {\n+    @leaf class Annot(tpe: Type, argss: List[List[Arg]]) extends Mod\n+    @leaf class Doc(doc: String) extends Mod // TODO: design representation for scaladoc\n+    @leaf class Private(within: String) extends Mod // TODO: design a name resolution API for these and imports\n+    @leaf class Protected(within: String) extends Mod\n+    @leaf class Implicit() extends Mod\n+    @leaf class Final() extends Mod\n+    @leaf class Sealed() extends Mod\n+    @leaf class Override() extends Mod\n+    @leaf class Case() extends Mod\n+    @leaf class Abstract() extends Mod\n+    @leaf class Covariant() extends Mod\n+    @leaf class Contravariant() extends Mod\n+    @leaf class Lazy() extends Mod\n+    @leaf class AbstractOverride() extends Mod\n+    @leaf class Macro() extends Mod\n+    @leaf class ByNameParam() extends Mod\n+    @leaf class VarargParam() extends Mod\n+    @leaf class ValParam() extends Mod\n+    @leaf class VarParam() extends Mod\n+  }\n \n-@branch trait Enum extends Tree\n-object Enum {\n-  @leaf class Generator(pat: Pat, rhs: Term) extends Enum\n-  @leaf class Val(pat: Pat, rhs: Term) extends Enum\n-  @leaf class Guard(cond: Term) extends Enum\n-}\n+  object Aux {\n+    @branch trait Catch extends Tree\n+    @leaf class Case(pat: Pat, cond: Option[Term] = None, body: Term = Lit.Unit()) extends Tree\n+    @leaf class Cases(cases: List[Case] @nonEmpty) extends Catch\n+    @leaf class Parent(tpe: Type, argss: List[List[Arg]] = Nil) extends Ref\n+    @leaf class Template(early: List[Defn.Val] = Nil, parents: List[Parent] = Nil,\n+                         self: Self = Self.empty, stats: List[Stmt.Template] = Nil) extends Tree {\n+      require(parents.isEmpty || !parents.tail.exists(_.argss.nonEmpty))\n+      def noBody: Boolean = ???\n+    }\n+    @leaf class Self(name: Option[Term.Ident] = None, tpe: Option[Type] = None) extends Symbol {\n+      require(name.nonEmpty || tpe.nonEmpty)\n+      def mods: List[Mod] = Nil\n+    }\n+    @leaf class Param(mods: List[Mod] = Nil, name: Option[Term.Ident] = None,\n+                      declTpe: Option[Type] = None, default: Option[Term] = None) extends Symbol\n+    @leaf class TypeParam(mods: List[Mod] = Nil,\n+                          name: Option[core.Type.Ident] = None,\n+                          tparams: List[Aux.TypeParam] = Nil,\n+                          contextBounds: List[core.Type] = Nil,\n+                          viewBounds: List[core.Type] = Nil,\n+                          bounds: Aux.TypeBounds = Aux.TypeBounds.empty) extends Symbol\n+    @leaf class TypeBounds(lo: Option[Type] = None, hi: Option[Type] = None) extends Tree\n+  }\n \n-@branch trait Param extends Symbol\n-object Param {\n-  @leaf class Function(annots: List[Annot] = Nil, name: Option[Term.Ident] = None, typ: Option[Type] = None) extends Param\n-  @leaf class Def(annots: List[Annot] = Nil, name: Option[Term.Ident] = None, typ: Type, default: Option[Term] = None) extends Param\n-}\n+  object Has {\n+    @branch trait Mods extends Tree {\n+      def mods: List[Mod]","path":"core/src/main/scala/scala/reflect/core/Trees.scala","position":654,"original_position":654,"commit_id":"e8505e74cc43a18d4fd88123a172a9094e2d250d","original_commit_id":"e8505e74cc43a18d4fd88123a172a9094e2d250d","user":{"login":"xeno-by","id":609152,"avatar_url":"https://avatars.githubusercontent.com/u/609152?","gravatar_id":"69e339fd10a5ad804c45e22c819c67ad","url":"https://api.github.com/users/xeno-by","html_url":"https://github.com/xeno-by","followers_url":"https://api.github.com/users/xeno-by/followers","following_url":"https://api.github.com/users/xeno-by/following{/other_user}","gists_url":"https://api.github.com/users/xeno-by/gists{/gist_id}","starred_url":"https://api.github.com/users/xeno-by/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xeno-by/subscriptions","organizations_url":"https://api.github.com/users/xeno-by/orgs","repos_url":"https://api.github.com/users/xeno-by/repos","events_url":"https://api.github.com/users/xeno-by/events{/privacy}","received_events_url":"https://api.github.com/users/xeno-by/received_events","type":"User","site_admin":false},"body":"What about `hasMod`?","created_at":"2014-04-27T10:41:40Z","updated_at":"2014-04-27T10:41:40Z","html_url":"https://github.com/scalareflect/core/pull/37#discussion_r12028528","pull_request_url":"https://api.github.com/repos/scalareflect/core/pulls/37","_links":{"self":{"href":"https://api.github.com/repos/scalareflect/core/pulls/comments/12028528"},"html":{"href":"https://github.com/scalareflect/core/pull/37#discussion_r12028528"},"pull_request":{"href":"https://api.github.com/repos/scalareflect/core/pulls/37"}}}}