ContentsThe library

Turning Text Into Instructions

The Stage That Finds Out Whether Your Names Refer to Anything

Last timeFrom Pieces to a Tree

A correct shape is not a correct program. This stage works out what every name refers to and what type every node has, and it is the last one that can refuse.

What a name refers to

After the previous stage the program has a shape. It does not yet have a

meaning. The tree contains names, and nothing so far has asked whether those

names refer to anything at all.

A name is resolved by looking it up, and the lookup is not a single table. It

is a chain of them, one per enclosing region of the program, searched from the

inside out.

FIG 1Three scopes and one name
plaintext
file scope
    count is declared here, a whole number

    function scope
        count is declared here too, a decimal

        block scope
            nothing named count declared

            the use of count inside this block
            finds the decimal, because the search
            stops at the first scope that has it

    a use of count out here finds the whole number
Two declarations of the same name, both legal, and which one a use refers to depends only on where the use is written. Nothing is overwritten and nothing is in conflict. The inner declaration simply makes the outer one unreachable from inside.
FIG 2Resolving one name
The whole mechanism is a loop outwards with an early stop. Every behaviour people describe as a scoping rule, including shadowing and the error for an unknown name, is a reading of this one picture.
FIG 3Cost of resolving one name
time to resolve one name
how many scopes out the declaration is
the cost of one scope lookup
Depth is rarely more than five or six, so this is cheap, but it is per name and there are a great many names. A large file resolves millions of them, which is why compilers keep the inner tables small and hash them.

Types from the leaves upward

With every name pointing at a declaration, every leaf of the tree has a type.

A literal number has one from its form, and a name has one from the

declaration it was just linked to.

Type checking is then one pass upwards. Each kind of operation carries a rule

saying what types it accepts and what type it produces, and the checker applies

that rule at every node using the types already computed for the children.

FIG 4Typing the tree for a plus b times c
stepstepnodetypes of the childrentype producedwhat happened
11leaf bnone, it is a leafwhole numberFrom the declaration the previous phase linked it to. Leaves are where types enter the tree, and everything above is derived.
22leaf cnone, it is a leafdecimalA different type from its sibling, which is going to force a decision one level up.
33multiplywhole number and decimaldecimalThe rule for multiplication accepts a mixed pair and produces the wider of the two, inserting a conversion into the tree. In a stricter language the same node would be an error instead.
44addwhole number and decimaldecimalThe same rule again, using the type the child produced rather than anything written in the source. Four nodes, one pass, every node typed.
4 steps
Nothing here required looking ahead or backtracking. Each node needed only its children, which is why this stage costs about the same as parsing and why type errors can be reported with a precise position.

The interesting part is what the checker does when the rule does not fit. In a

permissive language it inserts a conversion, which is why mixed arithmetic

works and also why a decimal can quietly lose its fractional part. In a strict

one it reports an error. The difference between those two languages is not a

difference of philosophy at this stage, it is a difference of a few lines in

the rule for each operator.

The lesson stops here

3 more paragraphs to go

You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.

The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.

See the planThe contents

This is the reading half

Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.

The contents

The rest of this course

  1. 01Before It Can Read Your Program It Has to Decide Where the Words End
  2. 02Precedence Is Not a Table You Memorise, It Is the Shape of the Rulesopening only
  3. 03The Stage That Finds Out Whether Your Names Refer to Anythingyou are here
  4. 04One Neutral Form in the Middle Turns a Multiplication Into an Additionopening only
  5. 05Every Transformation Obeys One Rule, and the Rule Is Narrower Than You Thinkopening only
  6. 06The Compiler Deleted Your Safety Check Because You Had Already Broken the Ruleopening only
  7. 07Thousands of Values and Sixteen Places to Keep Themopening only
  8. 08Your Instructions Arrive in Order and Are Executed in Whatever Order Suitsopening only

Read alongside