-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #351 from visualfc/instance
build: instantiate generics
- Loading branch information
Showing
13 changed files
with
672 additions
and
9 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,18 @@ | ||
package main | ||
|
||
// The index function returns the index of the first occurrence of v in s, | ||
// or -1 if not present. | ||
func index[E comparable](s []E, v E) int { | ||
for i, vs := range s { | ||
if v == vs { | ||
return i | ||
} | ||
} | ||
return -1 | ||
} | ||
|
||
func main() { | ||
s := []int{1, 3, 5, 2, 4} | ||
println(index(s, 3)) | ||
println(index(s, 6)) | ||
} |
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,95 @@ | ||
; ModuleID = 'main' | ||
source_filename = "main" | ||
|
||
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } | ||
|
||
@"main.init$guard" = global i1 false, align 1 | ||
@__llgo_argc = global i32 0, align 4 | ||
@__llgo_argv = global ptr null, align 8 | ||
|
||
define void @main.init() { | ||
_llgo_0: | ||
%0 = load i1, ptr @"main.init$guard", align 1 | ||
br i1 %0, label %_llgo_2, label %_llgo_1 | ||
|
||
_llgo_1: ; preds = %_llgo_0 | ||
store i1 true, ptr @"main.init$guard", align 1 | ||
br label %_llgo_2 | ||
|
||
_llgo_2: ; preds = %_llgo_1, %_llgo_0 | ||
ret void | ||
} | ||
|
||
define i32 @main(i32 %0, ptr %1) { | ||
_llgo_0: | ||
store i32 %0, ptr @__llgo_argc, align 4 | ||
store ptr %1, ptr @__llgo_argv, align 8 | ||
call void @"github.com/goplus/llgo/internal/runtime.init"() | ||
call void @main.init() | ||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 40) | ||
%3 = getelementptr inbounds i64, ptr %2, i64 0 | ||
store i64 1, ptr %3, align 4 | ||
%4 = getelementptr inbounds i64, ptr %2, i64 1 | ||
store i64 3, ptr %4, align 4 | ||
%5 = getelementptr inbounds i64, ptr %2, i64 2 | ||
store i64 5, ptr %5, align 4 | ||
%6 = getelementptr inbounds i64, ptr %2, i64 3 | ||
store i64 2, ptr %6, align 4 | ||
%7 = getelementptr inbounds i64, ptr %2, i64 4 | ||
store i64 4, ptr %7, align 4 | ||
%8 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 | ||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, i32 0, i32 0 | ||
store ptr %2, ptr %9, align 8 | ||
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, i32 0, i32 1 | ||
store i64 5, ptr %10, align 4 | ||
%11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, i32 0, i32 2 | ||
store i64 5, ptr %11, align 4 | ||
%12 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %8, align 8 | ||
%13 = call i64 @"main.index[int]"(%"github.com/goplus/llgo/internal/runtime.Slice" %12, i64 3) | ||
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %13) | ||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) | ||
%14 = call i64 @"main.index[int]"(%"github.com/goplus/llgo/internal/runtime.Slice" %12, i64 6) | ||
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %14) | ||
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) | ||
ret i32 0 | ||
} | ||
|
||
declare void @"github.com/goplus/llgo/internal/runtime.init"() | ||
|
||
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) | ||
|
||
define i64 @"main.index[int]"(%"github.com/goplus/llgo/internal/runtime.Slice" %0, i64 %1) { | ||
_llgo_0: | ||
%2 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 | ||
br label %_llgo_1 | ||
|
||
_llgo_1: ; preds = %_llgo_2, %_llgo_0 | ||
%3 = phi i64 [ -1, %_llgo_0 ], [ %4, %_llgo_2 ] | ||
%4 = add i64 %3, 1 | ||
%5 = icmp slt i64 %4, %2 | ||
br i1 %5, label %_llgo_2, label %_llgo_3 | ||
|
||
_llgo_2: ; preds = %_llgo_1 | ||
%6 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 | ||
%7 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 1 | ||
%8 = icmp slt i64 %4, 0 | ||
%9 = icmp sge i64 %4, %7 | ||
%10 = or i1 %9, %8 | ||
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %10) | ||
%11 = getelementptr inbounds i64, ptr %6, i64 %4 | ||
%12 = load i64, ptr %11, align 4 | ||
%13 = icmp eq i64 %1, %12 | ||
br i1 %13, label %_llgo_4, label %_llgo_1 | ||
|
||
_llgo_3: ; preds = %_llgo_1 | ||
ret i64 -1 | ||
|
||
_llgo_4: ; preds = %_llgo_2 | ||
ret i64 %4 | ||
} | ||
|
||
declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64) | ||
|
||
declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) | ||
|
||
declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) |
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,36 @@ | ||
package main | ||
|
||
func main() { | ||
recursive() | ||
} | ||
|
||
func recursive() { | ||
type T int | ||
if got, want := recur1[T](5), T(110); got != want { | ||
panic("error") | ||
} | ||
} | ||
|
||
type Integer interface { | ||
~int | ~int32 | ~int64 | ||
} | ||
|
||
func recur1[T Integer](n T) T { | ||
if n == 0 || n == 1 { | ||
return T(1) | ||
} else { | ||
return n * recur2(n-1) | ||
} | ||
} | ||
|
||
func recur2[T Integer](n T) T { | ||
list := make([]T, n) | ||
for i, _ := range list { | ||
list[i] = T(i + 1) | ||
} | ||
var sum T | ||
for _, elt := range list { | ||
sum += elt | ||
} | ||
return sum + recur1(n-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,174 @@ | ||
; ModuleID = 'main' | ||
source_filename = "main" | ||
|
||
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } | ||
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr } | ||
%"github.com/goplus/llgo/internal/runtime.Slice" = type { ptr, i64, i64 } | ||
|
||
@"main.init$guard" = global i1 false, align 1 | ||
@__llgo_argc = global i32 0, align 4 | ||
@__llgo_argv = global ptr null, align 8 | ||
@0 = private unnamed_addr constant [5 x i8] c"error", align 1 | ||
@_llgo_string = linkonce global ptr null, align 8 | ||
|
||
define void @main.init() { | ||
_llgo_0: | ||
%0 = load i1, ptr @"main.init$guard", align 1 | ||
br i1 %0, label %_llgo_2, label %_llgo_1 | ||
|
||
_llgo_1: ; preds = %_llgo_0 | ||
store i1 true, ptr @"main.init$guard", align 1 | ||
call void @"main.init$after"() | ||
br label %_llgo_2 | ||
|
||
_llgo_2: ; preds = %_llgo_1, %_llgo_0 | ||
ret void | ||
} | ||
|
||
define i32 @main(i32 %0, ptr %1) { | ||
_llgo_0: | ||
store i32 %0, ptr @__llgo_argc, align 4 | ||
store ptr %1, ptr @__llgo_argv, align 8 | ||
call void @"github.com/goplus/llgo/internal/runtime.init"() | ||
call void @main.init() | ||
call void @main.recursive() | ||
ret i32 0 | ||
} | ||
|
||
define void @main.recursive() { | ||
_llgo_0: | ||
%0 = call i64 @"main.recur1[main.T]"(i64 5) | ||
%1 = icmp ne i64 %0, 110 | ||
br i1 %1, label %_llgo_1, label %_llgo_2 | ||
|
||
_llgo_1: ; preds = %_llgo_0 | ||
%2 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 | ||
%3 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 0 | ||
store ptr @0, ptr %3, align 8 | ||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %2, i32 0, i32 1 | ||
store i64 5, ptr %4, align 4 | ||
%5 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %2, align 8 | ||
%6 = load ptr, ptr @_llgo_string, align 8 | ||
%7 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 16) | ||
store %"github.com/goplus/llgo/internal/runtime.String" %5, ptr %7, align 8 | ||
%8 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8 | ||
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, i32 0, i32 0 | ||
store ptr %6, ptr %9, align 8 | ||
%10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, i32 0, i32 1 | ||
store ptr %7, ptr %10, align 8 | ||
%11 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %8, align 8 | ||
call void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface" %11) | ||
unreachable | ||
|
||
_llgo_2: ; preds = %_llgo_0 | ||
ret void | ||
} | ||
|
||
declare void @"github.com/goplus/llgo/internal/runtime.init"() | ||
|
||
define i64 @"main.recur1[main.T]"(i64 %0) { | ||
_llgo_0: | ||
%1 = icmp eq i64 %0, 0 | ||
br i1 %1, label %_llgo_1, label %_llgo_3 | ||
|
||
_llgo_1: ; preds = %_llgo_3, %_llgo_0 | ||
ret i64 1 | ||
|
||
_llgo_2: ; preds = %_llgo_3 | ||
%2 = sub i64 %0, 1 | ||
%3 = call i64 @"main.recur2[main.T]"(i64 %2) | ||
%4 = mul i64 %0, %3 | ||
ret i64 %4 | ||
|
||
_llgo_3: ; preds = %_llgo_0 | ||
%5 = icmp eq i64 %0, 1 | ||
br i1 %5, label %_llgo_1, label %_llgo_2 | ||
} | ||
|
||
define void @"main.init$after"() { | ||
_llgo_0: | ||
%0 = load ptr, ptr @_llgo_string, align 8 | ||
%1 = icmp eq ptr %0, null | ||
br i1 %1, label %_llgo_1, label %_llgo_2 | ||
|
||
_llgo_1: ; preds = %_llgo_0 | ||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 24) | ||
store ptr %2, ptr @_llgo_string, align 8 | ||
br label %_llgo_2 | ||
|
||
_llgo_2: ; preds = %_llgo_1, %_llgo_0 | ||
ret void | ||
} | ||
|
||
declare ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64) | ||
|
||
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64) | ||
|
||
declare void @"github.com/goplus/llgo/internal/runtime.Panic"(%"github.com/goplus/llgo/internal/runtime.eface") | ||
|
||
define i64 @"main.recur2[main.T]"(i64 %0) { | ||
_llgo_0: | ||
%1 = mul i64 %0, 8 | ||
%2 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 %1) | ||
%3 = alloca %"github.com/goplus/llgo/internal/runtime.Slice", align 8 | ||
%4 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %3, i32 0, i32 0 | ||
store ptr %2, ptr %4, align 8 | ||
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %3, i32 0, i32 1 | ||
store i64 %0, ptr %5, align 4 | ||
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Slice", ptr %3, i32 0, i32 2 | ||
store i64 %0, ptr %6, align 4 | ||
%7 = load %"github.com/goplus/llgo/internal/runtime.Slice", ptr %3, align 8 | ||
%8 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 | ||
br label %_llgo_1 | ||
|
||
_llgo_1: ; preds = %_llgo_2, %_llgo_0 | ||
%9 = phi i64 [ -1, %_llgo_0 ], [ %10, %_llgo_2 ] | ||
%10 = add i64 %9, 1 | ||
%11 = icmp slt i64 %10, %8 | ||
br i1 %11, label %_llgo_2, label %_llgo_3 | ||
|
||
_llgo_2: ; preds = %_llgo_1 | ||
%12 = add i64 %10, 1 | ||
%13 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 | ||
%14 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 | ||
%15 = icmp slt i64 %10, 0 | ||
%16 = icmp sge i64 %10, %14 | ||
%17 = or i1 %16, %15 | ||
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %17) | ||
%18 = getelementptr inbounds i64, ptr %13, i64 %10 | ||
store i64 %12, ptr %18, align 4 | ||
br label %_llgo_1 | ||
|
||
_llgo_3: ; preds = %_llgo_1 | ||
%19 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 | ||
br label %_llgo_4 | ||
|
||
_llgo_4: ; preds = %_llgo_5, %_llgo_3 | ||
%20 = phi i64 [ 0, %_llgo_3 ], [ %31, %_llgo_5 ] | ||
%21 = phi i64 [ -1, %_llgo_3 ], [ %22, %_llgo_5 ] | ||
%22 = add i64 %21, 1 | ||
%23 = icmp slt i64 %22, %19 | ||
br i1 %23, label %_llgo_5, label %_llgo_6 | ||
|
||
_llgo_5: ; preds = %_llgo_4 | ||
%24 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 0 | ||
%25 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %7, 1 | ||
%26 = icmp slt i64 %22, 0 | ||
%27 = icmp sge i64 %22, %25 | ||
%28 = or i1 %27, %26 | ||
call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %28) | ||
%29 = getelementptr inbounds i64, ptr %24, i64 %22 | ||
%30 = load i64, ptr %29, align 4 | ||
%31 = add i64 %20, %30 | ||
br label %_llgo_4 | ||
|
||
_llgo_6: ; preds = %_llgo_4 | ||
%32 = sub i64 %0, 1 | ||
%33 = call i64 @"main.recur1[main.T]"(i64 %32) | ||
%34 = add i64 %20, %33 | ||
ret i64 %34 | ||
} | ||
|
||
declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) | ||
|
||
declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) |
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,63 @@ | ||
package main | ||
|
||
type Data[T any] struct { | ||
v T | ||
} | ||
|
||
func (p *Data[T]) Set(v T) { | ||
p.v = v | ||
} | ||
|
||
func (p *(Data[T1])) Set2(v T1) { | ||
p.v = v | ||
} | ||
|
||
type sliceOf[E any] interface { | ||
~[]E | ||
} | ||
|
||
type Slice[S sliceOf[T], T any] struct { | ||
Data S | ||
} | ||
|
||
func (p *Slice[S, T]) Append(t ...T) S { | ||
p.Data = append(p.Data, t...) | ||
return p.Data | ||
} | ||
|
||
func (p *Slice[S1, T1]) Append2(t ...T1) S1 { | ||
p.Data = append(p.Data, t...) | ||
return p.Data | ||
} | ||
|
||
type ( | ||
DataInt = Data[int] | ||
SliceInt = Slice[[]int, int] | ||
DataString = Data[string] | ||
SliceString = Slice[[]string, string] | ||
) | ||
|
||
func main() { | ||
println(DataInt{1}.v) | ||
println(DataString{"hello"}.v) | ||
println(Data[int]{100}.v) | ||
println(Data[string]{"hello"}.v) | ||
|
||
// TODO | ||
println(Data[struct { | ||
X int | ||
Y int | ||
}]{}.v.X) | ||
|
||
v1 := SliceInt{} | ||
v1.Append(100) | ||
v2 := SliceString{} | ||
v2.Append("hello") | ||
v3 := Slice[[]int, int]{} | ||
v3.Append([]int{1, 2, 3, 4}...) | ||
v3.Append2([]int{1, 2, 3, 4}...) | ||
|
||
println(v1.Data, v1.Data[0]) | ||
println(v2.Data, v2.Data[0]) | ||
println(v3.Data, v3.Data[0]) | ||
} |
Oops, something went wrong.