Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ func (p *Package) NewParam(pos token.Pos, name string, typ types.Type, optional
return param
}

// NewResult returns a new variable representing a function result.
func (p *Package) NewResult(pos token.Pos, name string, typ types.Type) *types.Var {
param := types.NewParam(pos, p.Types, name, typ)
if HasVarKind {
p.SetVarKind(param, ResultVar)
}
return param
}

// NewRecv returns a new variable representing a method receiver.
func (p *Package) NewRecv(pos token.Pos, name string, typ types.Type) *types.Var {
param := types.NewParam(pos, p.Types, name, typ)
if HasVarKind {
p.SetVarKind(param, RecvVar)
}
return param
}

// ----------------------------------------------------------------------------

// Func type
Expand Down
21 changes: 21 additions & 0 deletions package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4719,4 +4719,25 @@ func main() {
`)
}

func TestFuncVarKind(t *testing.T) {
pkg := newMainPackage()
x := pkg.NewParam(token.NoPos, "x", types.Typ[types.Int], false)
pkg.SetVarKind(x, gogen.ParamVar)
pkg.VarKind(x)
y := pkg.NewParam(token.NoPos, "y", types.Typ[types.Int], false)
r := pkg.NewResult(token.NoPos, "r", types.Typ[types.Int])
typ := pkg.NewType("T").InitType(pkg, types.Typ[types.Int])
recv := pkg.NewRecv(token.NoPos, "this", typ)
pkg.NewFunc(recv, "add", types.NewTuple(x, y), types.NewTuple(r), false).
BodyStart(pkg).Val(1).Return(1).End()
domTest(t, pkg, `package main

type T int

func (this T) add(x int, y int) (r int) {
return 1
}
`)
}

// ----------------------------------------------------------------------------
14 changes: 12 additions & 2 deletions param_go125.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,20 @@ type optionalVars struct{}

// setParamOptional marks a parameter as optional using types.Var.SetKind (Go 1.25+).
func (o *optionalVars) setParamOptional(param *types.Var) {
param.SetKind(0xff)
param.SetKind(types.VarKind(ParamOptionalVar))
}

// isParamOptional checks if a parameter is marked as optional using types.Var.Kind (Go 1.25+).
func (o *optionalVars) isParamOptional(param *types.Var) bool {
return param.Kind() == 0xff
return param.Kind() == types.VarKind(ParamOptionalVar)
}

func (o *optionalVars) SetVarKind(v *types.Var, kind VarKind) {
v.SetKind(types.VarKind(kind))
}

func (o *optionalVars) VarKind(v *types.Var) VarKind {
return VarKind(v.Kind())
}

const HasVarKind = true
13 changes: 12 additions & 1 deletion param_legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

package gogen

import "go/types"
import (
"go/types"
)

// optionalVars manages optional parameter metadata for Go < 1.25.
type optionalVars struct {
Expand All @@ -32,3 +34,12 @@ func (o *optionalVars) setParamOptional(param *types.Var) {
func (o *optionalVars) isParamOptional(param *types.Var) bool {
return o.paramsMeta[param]
}

func (o *optionalVars) SetVarKind(v *types.Var, kind VarKind) {
}

func (o *optionalVars) VarKind(v *types.Var) VarKind {
Comment thread
visualfc marked this conversation as resolved.
return 0
}

const HasVarKind = false
6 changes: 5 additions & 1 deletion stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,11 @@ func (p *forRangeStmt) RangeAssignThen(cb *CodeBuilder, pos token.Pos) {
if name == "_" {
continue
}
if scope.Insert(types.NewVar(token.NoPos, pkg.Types, name, typs[i])) != nil {
newVar := types.NewVar(token.NoPos, pkg.Types, name, typs[i])
if HasVarKind {
pkg.SetVarKind(newVar, LocalVar)
}
if scope.Insert(newVar) != nil {
log.Panicln("TODO: variable already defined -", name)
}
}
Expand Down
12 changes: 10 additions & 2 deletions type_var_and_const.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,11 @@ func (p *ValueDecl) endInit(cb *CodeBuilder, arity int) *ValueDecl {
values[i] = parg.Val
}
p.setType(i, name, retType)
if old := p.scope.Insert(types.NewVar(p.pos, pkg.Types, name, retType)); old != nil {
newVar := types.NewVar(p.pos, pkg.Types, name, retType)
if HasVarKind && pkg.Types.Scope() != p.scope {
pkg.SetVarKind(newVar, LocalVar)
}
Comment thread
visualfc marked this conversation as resolved.
if old := p.scope.Insert(newVar); old != nil {
if p.tok != token.DEFINE {
oldpos := cb.fset.Position(old.Pos())
cb.panicCodeErrorf(
Expand Down Expand Up @@ -461,7 +465,11 @@ func (p *Package) newValueDecl(
continue
}
if typ != nil && tok == token.VAR {
if old := scope.Insert(types.NewVar(pos, p.Types, name, typ)); old != nil {
newVar := types.NewVar(pos, p.Types, name, typ)
if HasVarKind && p.Types.Scope() != scope {
p.SetVarKind(newVar, LocalVar)
Comment thread
visualfc marked this conversation as resolved.
}
if old := scope.Insert(newVar); old != nil {
allowRedecl := p.allowRedecl && scope == p.Types.Scope()
if !(allowRedecl && types.Identical(old.Type(), typ)) { // for c2go
oldpos := p.cb.fset.Position(old.Pos())
Expand Down
47 changes: 47 additions & 0 deletions varkind.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2021 The XGo Authors (xgo.dev)
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gogen

import "fmt"

// A VarKind discriminates the various kinds of variables.
type VarKind uint8

const (
_ VarKind = iota // (not meaningful)
PackageVar // a package-level variable
LocalVar // a local variable
RecvVar // a method receiver variable
ParamVar // a function parameter variable
ResultVar // a function result variable
FieldVar // a struct field

ParamOptionalVar VarKind = 0xff
)

var varKindNames = map[VarKind]string{
0: "VarKind(0)",
PackageVar: "PackageVar",
LocalVar: "LocalVar",
RecvVar: "RecvVar",
ParamVar: "ParamVar",
ResultVar: "ResultVar",
FieldVar: "FieldVar",
ParamOptionalVar: "ParamOptional",
}

func (kind VarKind) String() string {
if s, ok := varKindNames[kind]; ok {
return s
}
return fmt.Sprintf("VarKind(%d)", kind)
}
64 changes: 64 additions & 0 deletions varkind_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2021 The XGo Authors (xgo.dev)
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build go1.25

package gogen_test

import (
"go/types"
"testing"

"github.com/goplus/gogen"
)

func TestVarKind(t *testing.T) {
pkg := newPackage("foo")
kinds := []gogen.VarKind{
gogen.PackageVar,
gogen.LocalVar,
gogen.RecvVar,
gogen.ParamVar,
gogen.FieldVar,
gogen.ParamOptionalVar,
}
v := pkg.NewParam(0, "v", types.Typ[types.Int], false)
for _, kind := range kinds {
pkg.SetVarKind(v, kind)
if pkg.VarKind(v).String() != kind.String() {
t.Fatal("bad kind string")
}
if types.VarKind(pkg.VarKind(v)) != v.Kind() {
t.Fatal("bad kind")
}
}
if gogen.VarKind(gogen.FieldVar+1).String() != types.VarKind(gogen.FieldVar+1).String() {
t.Fatal("bad string")
}
}

func TestRecvVarKind(t *testing.T) {
pkg := newPackage("foo")
typ := pkg.NewType("T").InitType(pkg, types.Typ[types.Int])
recv := pkg.NewRecv(0, "this", typ)
if recv.Kind() != types.RecvVar {
t.Fatal("error", recv.Kind())
}
}

func TestResultVarKind(t *testing.T) {
pkg := newPackage("foo")
typ := pkg.NewType("T").InitType(pkg, types.Typ[types.Int])
recv := pkg.NewResult(0, "this", typ)
if recv.Kind() != types.ResultVar {
t.Fatal("error", recv.Kind())
}
}
Loading