Skip to content

Commit 3f73fad

Browse files
committed
Export: syntax and parsing
1 parent cdb6250 commit 3f73fad

File tree

5 files changed

+46
-22
lines changed

5 files changed

+46
-22
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1403,7 +1403,7 @@ object Trees {
14031403
this(x, rhs)
14041404
case tree @ Template(constr, parents, self, _) if tree.derived.isEmpty =>
14051405
this(this(this(this(x, constr), parents), self), tree.body)
1406-
case Import(importImplied, expr, selectors) =>
1406+
case Import(_, expr, _) =>
14071407
this(x, expr)
14081408
case PackageDef(pid, stats) =>
14091409
this(this(x, pid), stats)(localCtx)

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
103103
case class GenAlias(pat: Tree, expr: Tree)(implicit @constructorOnly src: SourceFile) extends Tree
104104
case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree])(implicit @constructorOnly src: SourceFile) extends TypTree
105105
case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree)(implicit @constructorOnly src: SourceFile) extends DefTree
106+
case class Export(impliedOnly: Boolean, expr: Tree, selectors: List[Tree])(implicit @constructorOnly src: SourceFile) extends Tree
107+
108+
/** Short-lived usage in typer, does not need copy/transform/fold infrastructure */
106109
case class DependentTypeTree(tp: List[Symbol] => Type)(implicit @constructorOnly src: SourceFile) extends Tree
107110

108111
@sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY)(NoSource) with WithoutTypeOrPos[Untyped] {
@@ -532,6 +535,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
532535
case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
533536
case _ => finalize(tree, untpd.PatDef(mods, pats, tpt, rhs)(tree.source))
534537
}
538+
def Export(tree: Tree)(impliedOnly: Boolean, expr: Tree, selectors: List[Tree])(implicit ctx: Context): Tree = tree match {
539+
case tree: Export if (impliedOnly == tree.impliedOnly) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree
540+
case _ => finalize(tree, untpd.Export(impliedOnly, expr, selectors)(tree.source))
541+
}
535542
def TypedSplice(tree: Tree)(splice: tpd.Tree)(implicit ctx: Context): ProxyTree = tree match {
536543
case tree: TypedSplice if splice `eq` tree.splice => tree
537544
case _ => finalize(tree, untpd.TypedSplice(splice)(ctx))
@@ -584,6 +591,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
584591
cpy.ContextBounds(tree)(transformSub(bounds), transform(cxBounds))
585592
case PatDef(mods, pats, tpt, rhs) =>
586593
cpy.PatDef(tree)(mods, transform(pats), transform(tpt), transform(rhs))
594+
case Export(impliedOnly, expr, selectors) =>
595+
cpy.Export(tree)(impliedOnly, transform(expr), selectors)
587596
case TypedSplice(_) =>
588597
tree
589598
case _ =>
@@ -637,6 +646,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
637646
this(this(x, bounds), cxBounds)
638647
case PatDef(mods, pats, tpt, rhs) =>
639648
this(this(this(x, pats), tpt), rhs)
649+
case Export(_, expr, _) =>
650+
this(x, expr)
640651
case TypedSplice(splice) =>
641652
this(x, splice)
642653
case _ =>

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2225,13 +2225,16 @@ object Parsers {
22252225
def finalizeDef(md: MemberDef, mods: Modifiers, start: Int): md.ThisTree[Untyped] =
22262226
md.withMods(mods).setComment(in.getDocComment(start))
22272227

2228+
type ImportConstr = (Boolean, Tree, List[Tree]) => Tree
2229+
22282230
/** Import ::= import [implied] [ImportExpr {`,' ImportExpr}
2231+
* Export ::= export [implied] [ImportExpr {`,' ImportExpr}
22292232
*/
2230-
def importClause(): List[Tree] = {
2231-
val offset = accept(IMPORT)
2233+
def importClause(leading: Token, mkTree: ImportConstr): List[Tree] = {
2234+
val offset = accept(leading)
22322235
val importImplied = in.token == IMPLIED
22332236
if (importImplied) in.nextToken()
2234-
commaSeparated(importExpr(importImplied)) match {
2237+
commaSeparated(importExpr(importImplied, mkTree)) match {
22352238
case t :: rest =>
22362239
// The first import should start at the start offset of the keyword.
22372240
val firstPos =
@@ -2244,23 +2247,28 @@ object Parsers {
22442247

22452248
/** ImportExpr ::= StableId `.' (id | `_' | ImportSelectors)
22462249
*/
2247-
def importExpr(importImplied: Boolean): () => Import = {
2250+
def importExpr(importImplied: Boolean, mkTree: ImportConstr): () => Tree = {
22482251

22492252
val handleImport: Tree => Tree = { tree: Tree =>
2250-
if (in.token == USCORE) Import(importImplied, tree, importSelector() :: Nil)
2251-
else if (in.token == LBRACE) Import(importImplied, tree, inBraces(importSelectors()))
2253+
if (in.token == USCORE) mkTree(importImplied, tree, importSelector() :: Nil)
2254+
else if (in.token == LBRACE) mkTree(importImplied, tree, inBraces(importSelectors()))
22522255
else tree
22532256
}
22542257

2255-
() => path(thisOK = false, handleImport) match {
2256-
case imp: Import =>
2257-
imp
2258-
case sel @ Select(qual, name) =>
2259-
val selector = atSpan(pointOffset(sel)) { Ident(name) }
2260-
cpy.Import(sel)(importImplied, qual, selector :: Nil)
2261-
case t =>
2262-
accept(DOT)
2263-
Import(importImplied, t, Ident(nme.WILDCARD) :: Nil)
2258+
def derived(impExp: Tree, qual: Tree, selectors: List[Tree]) =
2259+
mkTree(impliedOnly, qual, selectors).withSpan(impExp.span)
2260+
2261+
() => {
2262+
val p = path(thisOK = false, handleImport)
2263+
p match {
2264+
case _: Import | _: Export => p
2265+
case sel @ Select(qual, name) =>
2266+
val selector = atSpan(pointOffset(sel)) { Ident(name) }
2267+
mkTree(importImplied, qual, selector :: Nil).withSpan(sel.span)
2268+
case t =>
2269+
accept(DOT)
2270+
mkTree(importImplied, t, Ident(nme.WILDCARD) :: Nil)
2271+
}
22642272
}
22652273
}
22662274

@@ -2769,7 +2777,7 @@ object Parsers {
27692777
else stats += packaging(start)
27702778
}
27712779
else if (in.token == IMPORT)
2772-
stats ++= importClause()
2780+
stats ++= importClause(IMPORT, Import)
27732781
else if (in.token == AT || isDefIntro(modifierTokens))
27742782
stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens))
27752783
else if (!isStatSep) {
@@ -2816,7 +2824,9 @@ object Parsers {
28162824
while (!isStatSeqEnd && !exitOnError) {
28172825
setLastStatOffset()
28182826
if (in.token == IMPORT)
2819-
stats ++= importClause()
2827+
stats ++= importClause(IMPORT, Import)
2828+
else if (in.token == EXPORT)
2829+
stats ++= importClause(EXPORT, Export.apply)
28202830
else if (isExprIntro)
28212831
stats += expr1()
28222832
else if (isDefIntro(modifierTokensOrCase))
@@ -2888,7 +2898,7 @@ object Parsers {
28882898
while (!isStatSeqEnd && in.token != CASE && !exitOnError) {
28892899
setLastStatOffset()
28902900
if (in.token == IMPORT)
2891-
stats ++= importClause()
2901+
stats ++= importClause(IMPORT, Import)
28922902
else if (in.token == GIVEN)
28932903
stats += implicitClosure(in.offset, Location.InBlock, modifiers(closureMods))
28942904
else if (isExprIntro)

compiler/src/dotty/tools/dotc/parsing/Tokens.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ object Tokens extends TokensCommon {
180180
final val ERASED = 63; enter(ERASED, "erased")
181181
final val IMPLIED = 64; enter(IMPLIED, "implied")
182182
final val GIVEN = 65; enter(GIVEN, "given")
183-
final val MACRO = 66; enter(MACRO, "macro") // TODO: remove
183+
final val EXPORT = 66; enter(EXPORT, "export")
184+
final val MACRO = 67; enter(MACRO, "macro") // TODO: remove
184185

185186
/** special symbols */
186187
final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
@@ -240,7 +241,7 @@ object Tokens extends TokensCommon {
240241
final val modifierFollowers = modifierTokens | defIntroTokens
241242

242243
/** Is token only legal as start of statement (eof also included)? */
243-
final val mustStartStatTokens: TokenSet = defIntroTokens | modifierTokens | BitSet(IMPORT, PACKAGE)
244+
final val mustStartStatTokens: TokenSet = defIntroTokens | modifierTokens | BitSet(IMPORT, EXPORT, PACKAGE)
244245

245246
final val canStartStatTokens: TokenSet = canStartExpressionTokens | mustStartStatTokens | BitSet(
246247
AT, CASE)

docs/docs/internals/syntax.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ Import ::= ‘import’ [‘implied’] ImportExpr {‘,’ ImportEx
334334
ImportExpr ::= StableId ‘.’ (id | ‘_’ | ImportSelectors) Import(expr, sels)
335335
ImportSelectors ::= ‘{’ {ImportSelector ‘,’} (ImportSelector | ‘_’) ‘}’
336336
ImportSelector ::= id [‘=>’ id | ‘=>’ ‘_’] Ident(name), Pair(id, id)
337+
Export ::= ‘export’ [‘implied’] ImportExpr {‘,’ ImportExpr}
337338
```
338339

339340
### Declarations and Definitions
@@ -370,7 +371,8 @@ DefDef ::= DefSig [(‘:’ | ‘<:’) Type] ‘=’ Expr
370371
TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef
371372
| [‘case’] ‘object’ ObjectDef
372373
| ‘enum’ EnumDef
373-
| ‘witness’ WitnessDef
374+
| ‘implied’ InstanceDef
375+
| Export
374376
ClassDef ::= id ClassConstr [Template] ClassDef(mods, name, tparams, templ)
375377
ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat
376378
ConstrMods ::= {Annotation} [AccessModifier]

0 commit comments

Comments
 (0)