go.talks: add 2014/compiling talk from Google I/O

LGTM=dave, adg
R=golang-codereviews, dave, dan.kortschak, christoph, adg
CC=golang-codereviews
https://golang.org/cl/117720043
diff --git a/2014/compiling.slide b/2014/compiling.slide
new file mode 100644
index 0000000..cf19a8c
--- /dev/null
+++ b/2014/compiling.slide
@@ -0,0 +1,145 @@
+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
diff --git a/2014/compiling/const1.go b/2014/compiling/const1.go
new file mode 100644
index 0000000..6b18693
--- /dev/null
+++ b/2014/compiling/const1.go
@@ -0,0 +1,20 @@
+// +build ignore
+
+package main
+
+import "fmt"
+
+// 1 START OMIT
+const C1 = 1e-323
+
+const C2 = C1 / 100
+const C3 = C2 * 100
+
+const C4 float64 = C1 / 100
+const C5 = C4 * 100
+
+func main() {
+	fmt.Println(C3, C5)
+}
+
+// 1 END OMIT
diff --git a/2014/compiling/const2.go b/2014/compiling/const2.go
new file mode 100644
index 0000000..762252f
--- /dev/null
+++ b/2014/compiling/const2.go
@@ -0,0 +1,20 @@
+// +build ignore
+
+package main
+
+import "fmt"
+
+// 1 START OMIT
+const C1 = 1e+308
+const C2 = C1 * 10
+const C3 = C2 / 10
+
+var V1 = C1
+var V2 = V1 * 10
+var V3 = V2 / 10
+
+func main() {
+	fmt.Println(C3, V3)
+}
+
+// 1 END OMIT
diff --git a/2014/compiling/const3.go b/2014/compiling/const3.go
new file mode 100644
index 0000000..59d3f16
--- /dev/null
+++ b/2014/compiling/const3.go
@@ -0,0 +1,19 @@
+// +build ignore
+
+package main
+
+import (
+	"fmt"
+	"unsafe"
+)
+
+// 1 START OMIT
+var V1 = 0x01020304
+var V2 [unsafe.Sizeof(V1)]byte
+
+func main() {
+	*(*int)(unsafe.Pointer(&V2)) = V1
+	fmt.Println(V2)
+}
+
+// 1 END OMIT
diff --git a/2014/compiling/name1.go b/2014/compiling/name1.go
new file mode 100644
index 0000000..9a82f24
--- /dev/null
+++ b/2014/compiling/name1.go
@@ -0,0 +1,23 @@
+// +build ignore
+
+package main
+
+import "fmt"
+
+// 2 START OMIT
+// 1 START OMIT
+func main() {
+	i := 1
+	f := func() T {
+		return T{
+			i: 1, // HL
+		}
+	}
+	fmt.Println(i, f())
+}
+
+// 1 END OMIT
+
+type T map[int]int
+
+// 2 END OMIT
diff --git a/2014/compiling/name2.go b/2014/compiling/name2.go
new file mode 100644
index 0000000..9a8a7fb
--- /dev/null
+++ b/2014/compiling/name2.go
@@ -0,0 +1,23 @@
+// +build ignore
+
+package main
+
+import "fmt"
+
+// 2 START OMIT
+// 1 START OMIT
+func main() {
+	i := 1
+	f := func() T {
+		return T{
+			i: 1, // HL
+		}
+	}
+	fmt.Println(i, f())
+}
+
+// 1 END OMIT
+
+type T struct{ i int }
+
+// 2 END OMIT
diff --git a/2014/compiling/rtype1.go b/2014/compiling/rtype1.go
new file mode 100644
index 0000000..af62df9
--- /dev/null
+++ b/2014/compiling/rtype1.go
@@ -0,0 +1,60 @@
+// +build ignore
+
+package main
+
+import (
+	"fmt"
+	"runtime"
+)
+
+// 1 START OMIT
+type P *P
+type S []S
+type C chan C
+type M map[int]M
+
+// 1 END OMIT
+
+// 2 START OMIT
+func Val(p *P) int {
+	if p == nil {
+		return 0
+	} else {
+		return 1 + Val(*p)
+	}
+}
+
+func Add(a, b *P) *P {
+	if b == nil {
+		return a
+	} else {
+		a1 := new(P)
+		*a1 = a // a1 == a + 1
+		return Add(a1, *b) // a + b == Add(a+1, b-1)
+	}
+}
+
+// 2 END OMIT
+
+// 3 START OMIT
+
+func Print(p *P) {
+	fmt.Println(Val(p))
+}
+
+func Allocate() {
+	p := new(P); *p = new(P); **p = new(P)
+	runtime.SetFinalizer(p, Print)
+	runtime.SetFinalizer(*p, Print)
+	runtime.SetFinalizer(**p, Print)
+}
+
+func main() {
+	Allocate()
+	for i := 0; i < 5; i++ {
+		runtime.GC()
+		runtime.Gosched()
+	}
+}
+
+// 3 END OMIT
diff --git a/2014/compiling/rtype2.go b/2014/compiling/rtype2.go
new file mode 100644
index 0000000..a341061
--- /dev/null
+++ b/2014/compiling/rtype2.go
@@ -0,0 +1,40 @@
+// +build ignore
+
+package main
+
+import "fmt"
+
+// 1 START OMIT
+type F func(*State) F
+
+type State int
+
+func Begin(s *State) F {
+	*s = 1
+	return Middle
+}
+
+func Middle(s *State) F {
+	*s++
+	if *s >= 10 {
+		return End
+	}
+	return Middle
+}
+// 1 END OMIT
+
+// 2 START OMIT
+func End(s *State) F {
+	fmt.Println(*s)
+	return nil
+}
+
+func main() {
+	var f F = Begin
+	var s State
+	for f != nil {
+		f = f(&s)
+	}
+}
+
+// 2 END OMIT
diff --git a/2014/compiling/var1.go b/2014/compiling/var1.go
new file mode 100644
index 0000000..9a5cac3
--- /dev/null
+++ b/2014/compiling/var1.go
@@ -0,0 +1,21 @@
+// +build ignore
+
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+// 1 START OMIT
+var V = struct {
+	name string
+	os.FileMode
+}{
+	name: "hello.go",
+}
+
+func main() {
+	fmt.Println(V)
+}
+// 1 END OMIT