|
Go: Easy to Read, Hard to Compile |
|
Corner cases when compiling Go |
|
|
|
Ian Lance Taylor |
|
Google |
|
iant@golang.org |
|
|
|
* Introduction |
|
|
|
- To really learn a language, write a compiler for it |
|
- Compiler bugs imply language complexity |
|
- Or, compiler bugs imply differences from C/C++ |
|
- Sometimes simpler for users is harder for compilers |
|
- Fortunately Go is much simpler to compile than C++ or even C |
|
|
|
This talk is based on Go compiler bugs encountered over the years. |
|
|
|
* Recursive Types |
|
|
|
Names in Go packages are defined in the entire package, so Go types |
|
can refer to themselves recursively. |
|
|
|
.code compiling/rtype1.go /1 START OMIT/,/1 END OMIT/ |
|
|
|
This is not permitted in C/C++, except for the special case of a |
|
struct/union/class field which is a pointer/reference. |
|
|
|
All Go compiler code that walks over types has to be careful to avoid |
|
endless loops. |
|
|
|
* Recursive Types |
|
|
|
What good is a recursive pointer type? It can only be nil or a |
|
pointer to itself. That's enough for Peano arithmetic. |
|
|
|
.code compiling/rtype1.go /2 START OMIT/,/2 END OMIT/ |
|
|
|
* Recursive Types |
|
|
|
Actually, a recursive pointer can have a bit more information: it can |
|
have a finalizer. |
|
|
|
.play compiling/rtype1.go /3 START OMIT/,/3 END OMIT/ |
|
|
|
* Recursive Types |
|
|
|
Recursive function types are actually useful: they can implement a |
|
state machine. |
|
|
|
.code compiling/rtype2.go /1 START OMIT/,/1 END OMIT/ |
|
|
|
* Recursive types |
|
|
|
.play compiling/rtype2.go /2 START OMIT/,/2 END OMIT/ |
|
|
|
* Recursive Types |
|
|
|
Simple rule: all names at package scope are visible in the entire |
|
package. |
|
|
|
Complex consequence: compiler must handle recursive types (also |
|
recursive initializers). |
|
|
|
* Constants |
|
|
|
Go has both typed and untyped constants. They follow the same rules, |
|
except that a typed constant must be representable in its type. |
|
|
|
This is reasonably clear for integers, less so for floats. |
|
|
|
.play compiling/const1.go /1 START OMIT/,/1 END OMIT/ |
|
|
|
* Constants |
|
|
|
Go's floating point variables follow IEEE-754 rules. |
|
|
|
Constants do not. |
|
|
|
.play compiling/const2.go /1 START OMIT/,/1 END OMIT/ |
|
|
|
* Constants |
|
|
|
The special unsafe.Sizeof function returns a constant. |
|
|
|
.play compiling/const3.go /1 START OMIT/,/1 END OMIT/ |
|
|
|
* Constants |
|
|
|
Simple rule: constants are untyped; they are mathematically exact and |
|
do not require type conversions. |
|
|
|
Complex consequence: exact floating point behavior depends on the |
|
type. |
|
|
|
* Name Lookup |
|
|
|
Name lookup in a Go compiler is simple compared to many languages. |
|
For every name the scope in which to look it up is obvious. This |
|
makes parsing Go quite simple. |
|
|
|
With one exception. What is the scope for i? |
|
|
|
.code compiling/name1.go /1 START OMIT/,/1 END OMIT/ |
|
|
|
* Name Lookup |
|
|
|
One possibility. |
|
|
|
.play compiling/name1.go /2 START OMIT/,/2 END OMIT/ |
|
|
|
* Name Lookup |
|
|
|
Another possibility. |
|
|
|
.play compiling/name2.go /2 START OMIT/,/2 END OMIT/ |
|
|
|
* Name Lookup |
|
|
|
Simple rule: in a struct composite literal you can use field names as |
|
keys. |
|
|
|
Complex consequence: if you don't know the type of the composite |
|
literal, the lookup scope of names used as keys is unclear when |
|
parsing. |
|
|
|
* Methods |
|
|
|
Any named type can have methods. Any struct type can inherit methods |
|
from an embedded field. It follows that you can sometimes call |
|
methods on a variable even if it has an unnamed type. |
|
|
|
.play compiling/var1.go /1 START OMIT/,/1 END OMIT/ |
|
|
|
* Methods |
|
|
|
Simple rules: named types can have methods; structs can have embedded |
|
fields. |
|
|
|
Complex consequence: unnamed types can have methods. |
|
|
|
* Conclusion |
|
|
|
- Go is simpler to compile than most languages |
|
- There are still complexities for the compiler |
|
- Most complexities stem from making Go easier to write |