-
Notifications
You must be signed in to change notification settings - Fork 356
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
interp: add support of Go generics in interpreter
Status: * [x] parsing code with generics * [x] instantiate generics from concrete types * [x] automatic type inference * [x] support of generic recursive types * [x] support of generic methods * [x] support of generic receivers in methods * [x] support of multiple type parameters * [x] support of generic constraints * [x] tests (see _test/gen*.go) Fixes #1363.
- Loading branch information
Showing
19 changed files
with
986 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package main | ||
|
||
import "fmt" | ||
|
||
// SumInts adds together the values of m. | ||
func SumInts(m map[string]int64) int64 { | ||
var s int64 | ||
for _, v := range m { | ||
s += v | ||
} | ||
return s | ||
} | ||
|
||
// SumFloats adds together the values of m. | ||
func SumFloats(m map[string]float64) float64 { | ||
var s float64 | ||
for _, v := range m { | ||
s += v | ||
} | ||
return s | ||
} | ||
|
||
func main() { | ||
// Initialize a map for the integer values | ||
ints := map[string]int64{ | ||
"first": 34, | ||
"second": 12, | ||
} | ||
|
||
// Initialize a map for the float values | ||
floats := map[string]float64{ | ||
"first": 35.98, | ||
"second": 26.99, | ||
} | ||
|
||
fmt.Printf("Non-Generic Sums: %v and %v\n", | ||
SumInts(ints), | ||
SumFloats(floats)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package main | ||
|
||
import "fmt" | ||
|
||
// SumIntsOrFloats sums the values of map m. It supports both int64 and float64 | ||
// as types for map values. | ||
func SumIntsOrFloats[K comparable, V int64 | float64](m map[K]V) V { | ||
var s V | ||
for _, v := range m { | ||
s += v | ||
} | ||
return s | ||
} | ||
|
||
func main() { | ||
// Initialize a map for the integer values | ||
ints := map[string]int64{ | ||
"first": 34, | ||
"second": 12, | ||
} | ||
|
||
// Initialize a map for the float values | ||
floats := map[string]float64{ | ||
"first": 35.98, | ||
"second": 26.99, | ||
} | ||
|
||
fmt.Printf("Generic Sums: %v and %v\n", | ||
SumIntsOrFloats[string, int64](ints), | ||
SumIntsOrFloats[string, float64](floats)) | ||
} | ||
|
||
// Output: | ||
// Generic Sums: 46 and 62.97 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package main | ||
|
||
type Number interface { | ||
int | int64 | ~float64 | ||
} | ||
|
||
func Sum[T Number](numbers []T) T { | ||
var total T | ||
for _, x := range numbers { | ||
total += x | ||
} | ||
return total | ||
} | ||
|
||
func main() { | ||
xs := []int{3, 5, 10} | ||
total := Sum(xs) | ||
println(total) | ||
} | ||
|
||
// Output: | ||
// 18 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package main | ||
|
||
import "fmt" | ||
|
||
type List[T any] struct { | ||
head, tail *element[T] | ||
} | ||
|
||
// A recursive generic type. | ||
type element[T any] struct { | ||
next *element[T] | ||
val T | ||
} | ||
|
||
func (lst *List[T]) Push(v T) { | ||
if lst.tail == nil { | ||
lst.head = &element[T]{val: v} | ||
lst.tail = lst.head | ||
} else { | ||
lst.tail.next = &element[T]{val: v} | ||
lst.tail = lst.tail.next | ||
} | ||
} | ||
|
||
func (lst *List[T]) GetAll() []T { | ||
var elems []T | ||
for e := lst.head; e != nil; e = e.next { | ||
elems = append(elems, e.val) | ||
} | ||
return elems | ||
} | ||
|
||
func main() { | ||
lst := List[int]{} | ||
lst.Push(10) | ||
lst.Push(13) | ||
lst.Push(23) | ||
fmt.Println("list:", lst.GetAll()) | ||
} | ||
|
||
// Output: | ||
// list: [10 13 23] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package main | ||
|
||
import "fmt" | ||
|
||
type Set[Elem comparable] struct { | ||
m map[Elem]struct{} | ||
} | ||
|
||
func Make[Elem comparable]() Set[Elem] { | ||
return Set[Elem]{m: make(map[Elem]struct{})} | ||
} | ||
|
||
func (s Set[Elem]) Add(v Elem) { | ||
s.m[v] = struct{}{} | ||
} | ||
|
||
func main() { | ||
s := Make[int]() | ||
s.Add(1) | ||
fmt.Println(s) | ||
} | ||
|
||
// Output: | ||
// {map[1:{}]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
func MapKeys[K comparable, V any](m map[K]V) []K { | ||
r := make([]K, 0, len(m)) | ||
for k := range m { | ||
r = append(r, k) | ||
} | ||
return r | ||
} | ||
|
||
func main() { | ||
var m = map[int]string{1: "2", 2: "4", 4: "8"} | ||
|
||
// Test type inference | ||
println(len(MapKeys(m))) | ||
} | ||
|
||
// Output: | ||
// 3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
func MapKeys[K comparable, V any](m map[K]V) []K { | ||
r := make([]K, 0, len(m)) | ||
for k := range m { | ||
r = append(r, k) | ||
} | ||
return r | ||
} | ||
|
||
func main() { | ||
var m = map[int]string{1: "2", 2: "4", 4: "8"} | ||
|
||
// Test type inference | ||
println(len(MapKeys)) | ||
} | ||
|
||
// Error: | ||
// invalid argument for len |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package main | ||
|
||
type Float interface { | ||
~float32 | ~float64 | ||
} | ||
|
||
func add[T Float](a, b T) float64 { return float64(a) + float64(b) } | ||
|
||
func main() { | ||
var x, y int = 1, 2 | ||
println(add(x, y)) | ||
} | ||
|
||
// Error: | ||
// int does not implement main.Float |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package main | ||
|
||
type Float interface { | ||
~float32 | ~float64 | ||
} | ||
|
||
func add[T Float](a, b T) float64 { return float64(a) + float64(b) } | ||
|
||
func main() { | ||
println(add(1, 2)) | ||
} | ||
|
||
// Error: | ||
// untyped int does not implement main.Float |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.