Repository: goplus/gop
Pull request #2050 (2024-12-27 13:15:25)

mini spec: Interface types


Patch:
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index 2553aacc..d96b74a3 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -51,7 +51,6 @@ dockers:
     build_flag_templates:
       - --platform=linux/386
       - --build-arg=USE_GORELEASER_ARTIFACTS=1
-      - --build-arg=GORELEASER_ARTIFACTS_TARBALL=./.dist/{{.ProjectName}}{{.Version}}.linux-386.tar.gz
     extra_files:
       - ./
   - goarch: amd64
@@ -61,7 +60,6 @@ dockers:
     build_flag_templates:
       - --platform=linux/amd64
       - --build-arg=USE_GORELEASER_ARTIFACTS=1
-      - --build-arg=GORELEASER_ARTIFACTS_TARBALL=./.dist/{{.ProjectName}}{{.Version}}.linux-amd64.tar.gz
     extra_files:
       - ./
   - goarch: arm64
@@ -71,7 +69,6 @@ dockers:
     build_flag_templates:
       - --platform=linux/arm64
       - --build-arg=USE_GORELEASER_ARTIFACTS=1
-      - --build-arg=GORELEASER_ARTIFACTS_TARBALL=./.dist/{{.ProjectName}}{{.Version}}.linux-arm64.tar.gz
     extra_files:
       - ./
 
diff --git a/Dockerfile b/Dockerfile
index 8b214ce7..bbca70c3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,18 +2,21 @@ ARG BASE_IMAGE=golang:1.22-bookworm
 
 FROM $BASE_IMAGE AS build
 ARG USE_GORELEASER_ARTIFACTS=0
-ARG GORELEASER_ARTIFACTS_TARBALL
 WORKDIR /usr/local/src/gop
 COPY . .
 ENV GOPROOT=/usr/local/gop
 RUN set -eux; \
-	mkdir $GOPROOT; \
+	mkdir -p $GOPROOT/bin; \
+	git ls-tree --full-tree --name-only -r HEAD | grep -vE "^\." | xargs -I {} cp --parents {} $GOPROOT/; \
 	if [ $USE_GORELEASER_ARTIFACTS -eq 1 ]; then \
-		tar -xzf "${GORELEASER_ARTIFACTS_TARBALL}" -C $GOPROOT; \
+		GOARCH=$(go env GOARCH); \
+		BIN_DIR_SUFFIX=linux_$GOARCH; \
+		[ $GOARCH = "amd64" ] && BIN_DIR_SUFFIX=${BIN_DIR_SUFFIX}_v1; \
+		[ $GOARCH = "arm" ] && BIN_DIR_SUFFIX=${BIN_DIR_SUFFIX}_$(go env GOARM | cut -d , -f 1); \
+		cp .dist/gop_$BIN_DIR_SUFFIX/bin/gop $GOPROOT/bin/; \
 	else \
-		git ls-tree --full-tree --name-only -r HEAD | grep -vE "^\." | xargs -I {} cp --parents {} $GOPROOT/; \
 		./all.bash; \
-		mv bin $GOPROOT/; \
+		cp bin/gop $GOPROOT/bin/; \
 	fi
 
 FROM $BASE_IMAGE
diff --git a/doc/spec-mini.md b/doc/spec-mini.md
index 5af2c331..d1ee949b 100644
--- a/doc/spec-mini.md
+++ b/doc/spec-mini.md
@@ -749,7 +749,115 @@ func(n int) func(p *T)
 
 ### Interface types
 
-TODO
+An interface type specifies a [method set]() called its _interface_. A variable of interface type can store a value of any type with a method set that is any superset of the interface. Such a type is said to _implement the interface_. The value of an uninitialized variable of interface type is `nil`.
+
+```go
+InterfaceType      = "interface" "{" { ( MethodSpec | InterfaceTypeName ) ";" } "}" .
+MethodSpec         = MethodName Signature .
+MethodName         = identifier .
+InterfaceTypeName  = TypeName .
+```
+
+An interface type may specify methods _explicitly_ through method specifications, or it may _embed_ methods of other interfaces through interface type names.
+
+```go
+// A simple File interface.
+interface {
+	Read([]byte) (int, error)
+	Write([]byte) (int, error)
+	Close() error
+}
+```
+
+The name of each explicitly specified method must be [unique]() and not [blank]().
+
+```go
+interface {
+	String() string
+	String() string  // illegal: String not unique
+	_(x int)         // illegal: method must have non-blank name
+}
+```
+
+More than one type may implement an interface. For instance, if two types `S1` and `S2` have the method set
+
+```go
+func (p T) Read(p []byte) (n int, err error)
+func (p T) Write(p []byte) (n int, err error)
+func (p T) Close() error
+```
+
+(where `T` stands for either `S1` or `S2`) then the `File` interface is implemented by both `S1` and `S2`, regardless of what other methods `S1` and `S2` may have or share.
+
+A type implements any interface comprising any subset of its methods and may therefore implement several distinct interfaces. For instance, all types implement the _empty interface_:
+
+```go
+interface{}
+```
+
+Similarly, consider this interface specification, which appears within a [type declaration](#type-declarations) to define an interface called `Locker`:
+
+```go
+type Locker interface {
+	Lock()
+	Unlock()
+}
+```
+
+If `S1` and `S2` also implement
+
+```go
+func Lock() { … }
+func Unlock() { … }
+```
+
+they implement the `Locker` interface as well as the `File` interface.
+
+An interface `T` may use a (possibly qualified) interface type name `E` in place of a method specification. This is called _embedding_ interface `E` in `T`. The method set of `T` is the union of the method sets of T’s explicitly declared methods and of T’s embedded interfaces.
+
+```go
+type Reader interface {
+	Read(p []byte) (n int, err error)
+	Close() error
+}
+
+type Writer interface {
+	Write(p []byte) (n int, err error)
+	Close() error
+}
+
+// ReadWriter's methods are Read, Write, and Close.
+type ReadWriter interface {
+	Reader  // includes methods of Reader in ReadWriter's method set
+	Writer  // includes methods of Writer in ReadWriter's method set
+}
+```
+
+A union of method sets contains the (exported and non-exported) methods of each method set exactly once, and methods with the [same]() names must have [identical]() signatures.
+
+```go
+type ReadCloser interface {
+	Reader   // includes methods of Reader in ReadCloser's method set
+	Close()  // illegal: signatures of Reader.Close and Close are different
+}
+```
+
+An interface type `T` may not embed itself or any interface type that embeds `T`, recursively.
+
+```go
+// illegal: Bad cannot embed itself
+type Bad interface {
+	Bad
+}
+
+// illegal: Bad1 cannot embed itself using Bad2
+type Bad1 interface {
+	Bad2
+}
+type Bad2 interface {
+	Bad1
+}
+```
 
 #### Built-in interfaces
 
diff --git a/go.mod b/go.mod
index 10b3a11e..cbe3b4a8 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.18
 
 require (
 	github.com/fsnotify/fsnotify v1.8.0
-	github.com/goplus/gogen v1.16.4-0.20241205134824-ac870e207d8f
+	github.com/goplus/gogen v1.16.3
 	github.com/goplus/llgo v0.9.8
 	github.com/goplus/mod v0.13.12
 	github.com/qiniu/x v1.13.10
diff --git a/go.sum b/go.sum
index cead13c2..e1e847ac 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,7 @@
 github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
 github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
-github.com/goplus/gogen v1.16.4-0.20241205134824-ac870e207d8f h1:+CwzStluc1MGjEQbR5CQOXWOqlBLYnaeECKcSXrHYKg=
-github.com/goplus/gogen v1.16.4-0.20241205134824-ac870e207d8f/go.mod h1:6TQYbabXDF9LCdDkOOzHmfg1R4ENfXQ3XpHa9RhTSD8=
+github.com/goplus/gogen v1.16.3 h1:nNkV1b6zd89d/UhMb4bZHcEfdAHtPaadrJFXNcoUITI=
+github.com/goplus/gogen v1.16.3/go.mod h1:6TQYbabXDF9LCdDkOOzHmfg1R4ENfXQ3XpHa9RhTSD8=
 github.com/goplus/llgo v0.9.8 h1:9qFO5sEYzTXYixNL9m9qDNfI2kjtnU3bPMf5hOwQlME=
 github.com/goplus/llgo v0.9.8/go.mod h1:1phqPJEgr/uw59PRz/NB7s54OoP+NGjC6pz0HovT5JY=
 github.com/goplus/mod v0.13.12 h1:Trwk6j3i9VvBuW6/9ZxmkoFlEL2v3HKQu0Na1c6DAdw=


Test patch:
diff --git a/cl/compile_gop_test.go b/cl/compile_gop_test.go
index 90bbdd66..04742bf2 100644
--- a/cl/compile_gop_test.go
+++ b/cl/compile_gop_test.go
@@ -1630,37 +1630,3 @@ func main() {
 }
 `)
 }
-
-func TestOverloadUntyped(t *testing.T) {
-	gopMixedClTest(t, "main", `
-package main
-
-type specialObj int
-type SpriteName string
-
-type SpriteImpl struct {
-}
-
-func (p *SpriteImpl) turn(v any) {
-}
-func (p *SpriteImpl) TurnTo__0(sprite *SpriteImpl) {
-}
-func (p *SpriteImpl) TurnTo__1(sprite SpriteName) {
-}
-func (p *SpriteImpl) TurnTo__2(obj specialObj) {
-}
-func (p *SpriteImpl) TurnTo__3(degree float64) {
-}
-`, `
-p := &SpriteImpl{}
-p.turnTo 180.0
-p.turnTo 180.1
-`, `package main
-
-func main() {
-	p := &SpriteImpl{}
-	p.TurnTo__2(180.0)
-	p.TurnTo__3(180.1)
-}
-`)
-}