Skip to content

Commit 1dbc721

Browse files
committed
refine for MVP
1 parent 4d40f86 commit 1dbc721

File tree

9 files changed

+367
-104
lines changed

9 files changed

+367
-104
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: Contexts
3+
type: section
4+
description: This page describes symbols in the Scala 3 compiler.
5+
num: 18
6+
previous-page: arch-symbols
7+
next-page:
8+
---
9+
10+
> (The following is work in progress), adapted from dotty.epfl.ch
11+
12+
The `Context` contains the state of the compiler, for example
13+
14+
* `settings`
15+
* `freshNames` (`FreshNameCreator`)
16+
* `period` (run and phase id)
17+
* `compilationUnit`
18+
* `phase`
19+
* `tree` (current tree)
20+
* `typer` (current typer)
21+
* `mode` (type checking mode)
22+
* `typerState` (for example undetermined type variables)
23+
* ...
24+
25+
### Contexts in the typer
26+
The type checker passes contexts through all methods and adapts fields where
27+
necessary, e.g.
28+
29+
```scala
30+
case tree: untpd.Block => typedBlock(desugar.block(tree), pt)(ctx.fresh.withNewScope)
31+
```
32+
33+
A number of fields in the context are typer-specific (`mode`, `typerState`).
34+
35+
### In other phases
36+
Other phases need a context for many things, for example to access the
37+
denotation of a symbols (depends on the period). However they typically don't
38+
need to modify / extend the context while traversing the AST. For these phases
39+
the context can be simply an implicit class parameter that is then available in
40+
all members.
41+
42+
**Careful**: beware of memory leaks. Don't hold on to contexts in long lived
43+
objects.
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
title: Symbols
3+
type: section
4+
description: This page describes symbols in the Scala 3 compiler.
5+
num: 17
6+
previous-page: arch-time
7+
next-page: arch-context
8+
---
9+
10+
> (The following is work in progress), adapted from dotty.epfl.ch
11+
12+
## Symbols and SymDenotations
13+
14+
- why symbols are not enough: their contents change all the time
15+
- reference: string + sig
16+
17+
18+
`dotc` is different from most other compilers in that it is centered around the idea of
19+
maintaining views of various artifacts associated with code. These views are indexed
20+
by time.
21+
22+
A symbol refers to a definition in a source program. Traditionally,
23+
compilers store context-dependent data in a _symbol table_. The
24+
symbol then is the central reference to address context-dependent
25+
data. But for the requirements of `dotc` it turns out that symbols are
26+
both too little and too much for this task.
27+
28+
**Too little:** The attributes of a symbol depend on the phase. Examples:
29+
Types are gradually simplified by several phases. Owners are changed
30+
in phases `LambdaLift` (when methods are lifted out to an enclosing
31+
class) and Flatten (when all classes are moved to top level). Names
32+
are changed when private members need to be accessed from outside
33+
their class (for instance from a nested class or a class implementing
34+
a trait). So a functional compiler, a `Symbol` by itself met mean
35+
much. Instead we are more interested in the attributes of a symbol at
36+
a given phase.
37+
38+
**Too much:** If a symbol is used to refer to a definition in another
39+
compilation unit, we get problems for incremental recompilation. The
40+
unit containing the symbol might be changed and recompiled, which
41+
might mean that the definition referred to by the symbol is deleted or
42+
changed. This leads to the problem of stale symbols that refer to
43+
definitions that no longer exist in this form. Scala 2 compiler tried to
44+
address this problem by _rebinding_ symbols appearing in certain cross
45+
module references, but it turned out to be too difficult to do this
46+
reliably for all kinds of references. Scala 3 compiler attacks the problem at
47+
the root instead. The fundamental problem is that symbols are too
48+
specific to serve as a cross-module reference in a system with
49+
incremental compilation. They refer to a particular definition, but
50+
that definition may not persist unchanged after an edit.
51+
52+
`dotc` uses instead a different approach: A cross module reference is
53+
always type, either a `TermRef` or `TypeRef`. A reference type contains
54+
a prefix type and a name. The definition the type refers to is established
55+
dynamically based on these fields.
56+
57+
58+
<!-- a system where sources can be recompiled at any instance,
59+
60+
the concept of a `Denotation`.
61+
62+
Since definitions are transformed by phases, -->
63+
64+
## Symbols
65+
`dotc/core/Symbols.scala`
66+
67+
Symbols are references to definitions (e.g. of variables, fields, classes). Symbols can be used to refer to definitions for which we don't have ASTs (for example, from the Java standard library).
68+
69+
`NoSymbol` is used to indicate the lack of a symbol.
70+
71+
Symbols uniquely identify definitions, but they don't say what the definitions *mean*. To understand the meaning of a symbol
72+
we need to look at its *denotation* (spefically for symbols, a `SymDenotation`).
73+
74+
Symbols can not only represent terms, but also types (hence the `isTerm`/`isType` methods in the `Symbol` class).
75+
76+
## ClassSymbol
77+
78+
`ClassSymbol` represents either a `class`, or an `trait`, or an `object`. For example, an object
79+
```scala
80+
object O {
81+
val s = 1
82+
}
83+
```
84+
is represented (after `Typer`) as
85+
```scala
86+
class O$ { this: O.type =>
87+
val s = 1
88+
}
89+
val O = new O$
90+
```
91+
where we have a type symbol for `class O$` and a term symbol for `val O`. Notice the use of the selftype `O.type` to indicate that `this` has a singleton type.
92+
93+
94+
## SymDenotation
95+
`dotc/core/SymDenotations.scala`
96+
97+
Symbols contain `SymDenotation`s. The denotation, in turn, refers to:
98+
99+
* the source symbol (so the linkage is cyclic)
100+
* the "owner" of the symbol:
101+
- if the symbol is a variable, the owner is the enclosing method
102+
- if it's a field, the owner is the enclosing class
103+
- if it's a class, then the owner is the enclosing class
104+
* a set of flags that contain semantic information about the definition (e.g. whether it's a trait or mutable). Flags are defined in `Flags.scala`.
105+
* the type of the definition (through the `info` method)
106+
107+
## Denotation
108+
[Comment with a few details:][Denotations2]
109+
110+
A `Denotation` is the result of a name lookup during a given period
111+
112+
* Most properties of symbols are now in the denotation (name, type, owner,
113+
etc.)
114+
* Denotations usually have a reference to the selected symbol
115+
* Denotations may be overloaded (`MultiDenotation`). In this case the symbol
116+
may be `NoSymbol` (the two variants have symbols).
117+
* Non-overloaded denotations have an `info`
118+
119+
Denotations of methods have a [signature][Signature1], which
120+
uniquely identifies overloaded methods.
121+
122+
### Denotation vs. SymDenotation
123+
A `SymDenotation` is an extended denotation that has symbol-specific properties
124+
(that may change over phases)
125+
* `flags`
126+
* `annotations`
127+
* `info`
128+
129+
`SymDenotation` implements lazy types (similar to scalac). The type completer
130+
assigns the denotation's `info`.
131+
132+
[Denotations2]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Denotations.scala#L77-L103
133+
[Signature1]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Signature.scala#L9-L33

_overviews/scala3-contribution/arch-time.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ type: section
44
description: This page describes the concepts of time in the Scala 3 compiler.
55
num: 16
66
previous-page: arch-types
7-
next-page:
7+
next-page: arch-symbols
88
---
99

10+
> (The following is work in progress), adapted from dotty.epfl.ch
11+
1012
Conceptually, the `dotc` compiler's job is to maintain views of various
1113
artifacts associated with source code at all points in time. But what is
1214
*time* for `dotc`? In fact, it is a combination of compiler runs and compiler
@@ -23,7 +25,7 @@ in real time.
2325

2426
The *minutes* of the compiler's clocks are measured in phases. At every
2527
compiler run, the compiler cycles through a number of [phases]. The list of
26-
phases is defined in the [Compiler]object There are currently about 60 phases
28+
phases is defined in the [Compiler] object There are currently about 60 phases
2729
per run, so the minutes/hours analogy works out roughly. After every phase the
2830
view the compiler has of the world changes: trees are transformed, types are
2931
gradually simplified from Scala types to JVM types, definitions are rearranged,
@@ -95,3 +97,4 @@ As a sentinel value there's `Nowhere`, a period that is empty.
9597
[runs]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/Run.scala
9698
[phases]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Phases.scala
9799
[period]: https://github.com/lampepfl/dotty/blob/a527f3b1e49c0d48148ccfb2eb52e3302fc4a349/compiler/src/dotty/tools/dotc/core/Periods.scala
100+
[Compiler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala

_overviews/scala3-contribution/procedures-areas.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Look in [RefinedPrinter] (or its parent class [PlainPrinter]) for the implementa
2222

2323
You can find most error messages defined in [messages] (with IDs defined in [ErrorMessageID]). If the message
2424
is not defined there, try the `-Ydebug-error` compiler flag, which will print a stack trace leading to the
25-
production of the error.
25+
production of the error, and the contents of the message.
2626

2727
### Compiler Generated Given Instances
2828

_overviews/scala3-contribution/procedures-cheatsheet.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ For more in-depth explainations, see the rest of this chapter.
1212

1313
## sbt Commands
1414

15-
The following commands can be run within the shell after running `sbt` in the dotty directory.
15+
The following commands can be run within `sbt` in the dotty directory.
1616

1717
| Command | Description |
1818
|------------------------------------|------------------------------------------------------------------|
@@ -26,4 +26,10 @@ The following commands can be run within the shell after running `sbt` in the do
2626
| <code>scala3-compiler/Test/runMain<br/>dotty.tools.printTypes</code> | Print types underlying representation |
2727
| <code>scala3/scalac -print-tasty<br/>local/out/Foo.tasty</code> | Print the TASTy of top-level class `Foo` |
2828

29+
## Shell Commands
30+
31+
| Command | Description |
32+
|--------------------------------------|------------------------------------------------------------------|
33+
| `rm -rv *.tasty *.class out || true` | clean all compiled artifacts, from root dotty directory |
34+
2935
<!-- Todo: add cheatsheet for compiler flags, and places to go in code for certain issues -->

_overviews/scala3-contribution/procedures-inspection.md

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,21 @@ previous-page: procedures-areas
77
next-page: procedures-efficiency
88
---
99

10-
## Printing TASTy of a Class
11-
12-
If are working on an issue related to TASTy, it is good to know how to inspect
13-
the contents of a TASTy file, produced from compilation of Scala files.
14-
15-
In the following example, we compile in a file `local/Foo.scala`, with contents
16-
of `class Foo`, and then print its TASTy:
17-
18-
```bash
19-
$ sbt
20-
sbt:scala3> scala3/scalac -d local/out local/Foo.scala
21-
sbt:scala3> scala3/scalac -print-tasty local/out/Foo.tasty
22-
```
23-
We see output such as the following:
24-
25-
```
26-
--------------------------------------------------------------------------------
27-
local/foo/out/Foo.tasty
28-
--------------------------------------------------------------------------------
29-
Names:
30-
0: ASTs
31-
1: <empty>
32-
2: Foo
33-
3: <init>
34-
...
35-
```
36-
and so on.
10+
In this section, we take a closer look at how to debug the contents of certain objects
11+
in the compiler, and produced artifacts.
3712

3813
## Inspecting variables in-place
3914

40-
Frequently you need to know what a particular variable's value is. The most robust way to get this info is good old `println`.
15+
Frequently we need to know what a particular variable's value is. Often, it is sufficient to use `println`.
4116

42-
When printing a variable, it's always a good idea to call `show` on that variable: `println(x.show)`. `show` is defined on many types and returns a human-readable string. So, if called e.g. on a tree, you'll get the code that tree signifies as opposed to the bare AST.
17+
When printing a variable, it's always a good idea to call `show` on that variable: `println(x.show)`.
18+
Many objects of the compiler define `show`, returning a human-readable string.
19+
e.g. if called on a tree, the output will be the tree's representation as source code, rather than
20+
the raw data underlying.
4321

44-
Sometimes you need to print flags. Flags is a metadata attached to trees containing information such as whether a class is abstract, comes from Java, what modifiers a variable has (private, protected etc) and so on. Flags are stored in a single `Long` value each bit of which represents whether a particular flag is set.
22+
Sometimes you need to print flags. Flags are metadata attached to [symbols] containing information such as whether a
23+
class is abstract, comes from Java, what modifiers a variable has (private, protected etc) and so on.
24+
Flags are stored in a single `Long` value, each bit of which represents whether a particular flag is set.
4525

4626
To print flags, you can use the `flagsString` method, e.g. `println(x.flagsString)`.
4727

@@ -79,8 +59,42 @@ Sometimes you may want to stop the compiler after a certain phase, for example t
7959
knock-on errors from occurring from a bug in an earlier phase. Use the flag
8060
`-Ystop-after:<phase-name>` to prevent any phases executing afterwards.
8161

82-
> This flag is particularly useful when you want to inspect the effect of a single miniphase
83-
> of a phase group, use this in conjunction with the `-Xprint` flag.
62+
> e.g. `-Xprint:<phase>` where `phase` is a miniphase, will print after
63+
> the whole phase group is complete, which may several miniphases after `phase`.
64+
> Instead you can use `-Ystop-after:<phase> -Xprint:<phase>` to stop
65+
> immediately after the miniphase and see the trees that you intended.
66+
67+
## Printing TASTy of a Class
68+
69+
If are working on an issue related to TASTy, it is good to know how to inspect
70+
the contents of a TASTy file, produced from compilation of Scala files.
71+
72+
In the following example, we compile in an [issue directory][reproduce] `tasty/Foo.scala`,
73+
with contents of `class Foo`, and create a `tasty/launch.iss` file to print its TASTy
74+
with sbt command `issue tasty`:
75+
76+
```
77+
$ (rm -rv out || true) && mkdir out # clean up compiler output, create `out` dir.
78+
79+
scala3/scalac -d $here/out $here/Foo.scala
80+
81+
scala3/scalac -print-tasty $here/out/Foo.tasty
82+
```
83+
84+
We see output such as the following:
85+
86+
```
87+
--------------------------------------------------------------------------------
88+
local/foo/out/Foo.tasty
89+
--------------------------------------------------------------------------------
90+
Names:
91+
0: ASTs
92+
1: <empty>
93+
2: Foo
94+
3: <init>
95+
...
96+
```
97+
and so on.
8498

8599
## Inspecting representation of types
86100

@@ -168,3 +182,5 @@ class StealBox:
168182
[2]: {% link _overviews/scala3-contribution/arch-types.md %}
169183
[3]: {% link _overviews/scala3-contribution/arch-lifecycle.md %}/#phases
170184
[ScalaSettings.scala]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
185+
[symbols]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
186+
[reproduce]: {% link _overviews/scala3-contribution/procedures-reproduce.md %}/#dotty-issue-workspace

0 commit comments

Comments
 (0)