aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Namer.scala
blob: a024ba953c8ba10d0966573093a4e4a3f25912d4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package dotty.tools
package dotc
package typer

import core._
import ast._
import Trees._, Constants._, StdNames._
import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._
import util.Positions._
import util.SourcePosition
import language.implicitConversions

class Namer {

  import untpd._

  implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition =
    ctx.source.atPos(pos)

  implicit def posToCoord(pos: Position): Coord = positionCoord(pos)

  def privateWithinClass(mods: Modifiers)(implicit ctx: Context): Symbol = {
    val pw = mods.privateWithin
    if (pw.isEmpty) NoSymbol
    else {
      val cls = ctx.owner.enclosingClassNamed(pw)
      if (!cls.exists) ctx.error(s"no enclosing class or object is named $pw", mods.pos)
      cls
    }
  }

  def createSymbol(tree: Tree)(implicit ctx: Context): Symbol = tree match {
    case tree: ModDefTree =>
      val sym = ctx.newSymbol(
        ctx.owner, tree.name, tree.mods.flags, new Completer(tree),
        privateWithinClass(tree.mods), tree.pos)
      ctx.scope.enter(sym)
      sym
  }


  def expansion(tree: Tree)(implicit ctx: Context): Tree = {

    def expandCaseClass(tree: Tree, companion: Tree): Tree = {
      val ClassDef(mods, cname, tparams, impl @ Template(constr, parents, self, stats)) = tree
      val constr1 =
        if (constr.vparamss.nonEmpty) constr
        else {
          ctx.error("case classes need to have at least one parameter list")
          constr.derivedDefDef(constr.mods, constr.name, constr.tparams, ListOfNil, constr.tpt, constr.rhs)
        }
      val caseParams = constr1.vparamss.head
      val caseParamsArray = caseParams.toArray
      val isDefinedMeth = syntheticProperty(nme.isDefined, Literal(Constant(true)))
      val productArityMeth = syntheticProperty(nme.productArity, Literal(Constant(caseParamsArray.length)))
      val productElemMeths = for (i <- 0 until caseParamsArray.length) yield
          syntheticProperty(("_" + (i + 1)).toTermName, Select(This(EmptyTypeName), caseParamsArray(i).name))
      val clsTypeRef = AppliedTypeTree(Ident(cname), tparams map refOfDef)
      val methTparams = for (tparam <- tparams) yield
          tparam.derivedTypeDef(Modifiers(TypeParam), tparam.name, tparam.tparams, tparam.rhs)
      val (copyMeths, applyMeths) =
        if (mods is Abstract) (Nil, Nil)
        else {
          val creator = New(clsTypeRef, constr1.vparamss map (_ map refOfDef))
          val copyFirstParams = caseParams.map(vparam =>
            vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, refOfDef(vparam)))
          val copyRestParamss = constr1.vparamss.tail.nestedMap(vparam =>
            vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, EmptyTree))
          val applyParamss = constr1.vparamss.nestedMap(vparam =>
            vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, vparam.rhs))
          val copyMeth =
            DefDef(Modifiers(Synthetic), nme.copy, methTparams, copyFirstParams :: copyRestParamss, EmptyTree, creator)
          val applyMeth =
            DefDef(Modifiers(Synthetoc), nme.apply, methTparams, applyParamss, EmptyTree, creator)
          (copyMeth :: Nil, applyMeth :: Nil)
      }
      val unapplyMeth = {
        val unapplyParam = makeSyntheticParameter(tpt = clsTypeRef)
        DefDef(Modifiers(Synthetic), nme.unapply, methTparams, (unapplyParam :: Nil) :: Nil, clsTypeRef, This(EmptyTypeName))
      }
      val newClassDefs = copyMeths ++ isDefinedMeth :: productArityMeth :: productElemMeths.toList
      val newModuleDefs = applyMeths ++ unapplyMeth :: Nil
      val cls1 = tree.derivedClassDef(mods, cname, tparams,
          impl.derivedTemplate(constr, parents, self, stats ++ newClassDefs))
      val companion1 = companion match {
        case ModuleDef(mods, name, impl @ Template(constr, parents, self, stats)) =>
          companion.derivedModuleDef(mods, name,
              impl.derivedTemplate(constr, parents, self, stats ++ newModuleDefs))
        case _ =>

      }
        if (companion.isEmpty)
        else {

        }

      val applyMeth = {
        val applyVparamss =
        DefDef(Modifiers(Synthetic), nme.apply, methTparams, applyVparamss, EmptyTree, )
      }

      }

  }


    tree match {
    case ValDef(mods, name, tpt, rhs) =>
      if (!ctx.owner.isClass || (mods is Private)) tree
      else {
        val lname = name.toLocalName
        val field = tree.derivedValDef(mods, lname, tpt, rhs)
        val getter = tree.derivedDefDef(mods, name, Nil, Nil, tpt, Ident(lname))
        if (!(mods is Mutable)) Thicket(field, getter)
        else {
          val setterParam = makeSyntheticParameter(tpt = TypeTree(field))
          val setter = tree.derivedDefDef(
            mods, name.getterToSetter, Nil, (setterParam :: Nil) :: Nil, EmptyTree, refOfDef(setterParam))
          Thicket(field, getter, setter)
        }
      }
    case tree: ModuleDef =>
      desugarModuleDef(tree)
    case tree: ClassDef if tree.mods is Case =>
      expandCaseClass(tree)
  }

  def syntheticProperty(name: TermName, rhs: Tree) = DefDef(Modifiers(Synthetic), name, Nil, Nil, EmptyTree, rhs)

  class Completer(tree: Tree) extends LazyType {
    def complete(sym: Symbol) =>
      ???
  }

  def enter(tree: Tree)(implicit ctx: Context) = tree match {
    case Import(expr, selectors) =>
      ???
    case DefDef


  }

}