Repository: goplus/gop
Pull request #1705 (2024-02-03 13:08:42)

FuncAlias


Patch:
diff --git a/cl/compile.go b/cl/compile.go
index 00b515fe..e7754acb 100644
--- a/cl/compile.go
+++ b/cl/compile.go
@@ -253,20 +253,21 @@ type baseLoader struct {
 	start token.Pos
 }
 
-func initLoader(ctx *pkgCtx, syms map[string]loader, start token.Pos, name string, fn func(), genBody bool) {
+func initLoader(ctx *pkgCtx, syms map[string]loader, start token.Pos, name string, fn func(), genBody bool) bool {
 	if name == "_" {
 		if genBody {
 			ctx.inits = append(ctx.inits, fn)
 		}
-		return
+		return false
 	}
 	if old, ok := syms[name]; ok {
 		oldpos := ctx.Position(old.pos())
 		ctx.handleErrorf(
 			start, "%s redeclared in this block\n\tprevious declaration at %v", name, oldpos)
-		return
+		return false
 	}
 	syms[name] = &baseLoader{start: start, fn: fn}
+	return true
 }
 
 func (p *baseLoader) load() {
@@ -920,7 +921,8 @@ func preloadFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, goFile
 				defer p.RestoreCurFile(old)
 				loadFunc(ctx, nil, d, genFnBody)
 			}
-			if name.Name == "init" {
+			fname := name.Name
+			if fname == "init" {
 				if genFnBody {
 					if debugLoad {
 						log.Println("==> Preload func init")
@@ -929,9 +931,13 @@ func preloadFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, goFile
 				}
 			} else {
 				if debugLoad {
-					log.Println("==> Preload func", name.Name)
+					log.Println("==> Preload func", fname)
 				}
-				initLoader(parent, syms, name.Pos(), name.Name, fn, genFnBody)
+				initLoader(parent, syms, name.Pos(), fname, fn, genFnBody) /* {
+					if strings.HasSuffix(fname, "Gopx_") { // Gopx_xxx func
+						ctx.lbinames = append(ctx.lbinames, fname)
+					}
+				} */
 			}
 		} else {
 			if name, ok := getRecvTypeName(parent, d.Recv, true); ok {
diff --git a/cl/expr.go b/cl/expr.go
index 9fc45f38..c970fb70 100644
--- a/cl/expr.go
+++ b/cl/expr.go
@@ -57,7 +57,7 @@ Name lookup:
 // ---------------------------------------------------------------------------*/
 
 const (
-	clIdentCanAutoCall = 1 << iota
+	clIdentCanAutoCall = 1 << iota // allow auto property
 	clIdentAllowBuiltin
 	clIdentLHS
 	clIdentSelectorExpr // this ident is X of ast.SelectorExpr
@@ -120,6 +120,11 @@ func compileIdent(ctx *blockCtx, ident *ast.Ident, flags int) (pkg gox.PkgRef, k
 		goto find
 	}
 
+	// function alias
+	if compileFuncAlias(ctx, scope, ident, flags) {
+		return
+	}
+
 	// pkgRef object
 	if (flags & clIdentSelectorExpr) != 0 {
 		if name == "C" && len(ctx.clookups) > 0 {
@@ -391,6 +396,21 @@ func compileSelectorExpr(ctx *blockCtx, v *ast.SelectorExpr, flags int) {
 	}
 }
 
+func compileFuncAlias(ctx *blockCtx, scope *types.Scope, x *ast.Ident, flags int) bool {
+	name := x.Name
+	if c := name[0]; c >= 'a' && c <= 'z' {
+		name = string(rune(c)+('A'-'a')) + name[1:]
+		o := scope.Lookup(name)
+		if o == nil && ctx.loadSymbol(name) {
+			o = scope.Lookup(name)
+		}
+		if o != nil {
+			return identVal(ctx, x, flags, o, true)
+		}
+	}
+	return false
+}
+
 func pkgRef(at gox.PkgRef, name string) (o types.Object, alias bool) {
 	if c := name[0]; c >= 'a' && c <= 'z' {
 		name = string(rune(c)+('A'-'a')) + name[1:]
@@ -437,28 +457,37 @@ func lookupPkgRef(ctx *blockCtx, pkg gox.PkgRef, x *ast.Ident, pkgKind int) (o t
 // allow at.Types to be nil
 func compilePkgRef(ctx *blockCtx, at gox.PkgRef, x *ast.Ident, flags, pkgKind int) bool {
 	if v, alias := lookupPkgRef(ctx, at, x, pkgKind); v != nil {
-		cb := ctx.cb
 		if (flags & clIdentLHS) != 0 {
 			if rec := ctx.recorder(); rec != nil {
 				rec.Use(x, v)
 			}
-			cb.VarRef(v, x)
-		} else {
-			autoprop := alias && (flags&clIdentCanAutoCall) != 0
-			if autoprop && !gox.HasAutoProperty(v.Type()) {
+			ctx.cb.VarRef(v, x)
+			return true
+		}
+		return identVal(ctx, x, flags, v, alias)
+	}
+	return false
+}
+
+func identVal(ctx *blockCtx, x *ast.Ident, flags int, v types.Object, alias bool) bool {
+	autocall := false
+	if alias {
+		if (flags & clCommandWithoutArgs) != 0 {
+			autocall = true
+		} else if autocall = (flags & clIdentCanAutoCall) != 0; autocall {
+			if !gox.HasAutoProperty(v.Type()) {
 				return false
 			}
-			if rec := ctx.recorder(); rec != nil {
-				rec.Use(x, v)
-			}
-			cb.Val(v, x)
-			if autoprop {
-				cb.CallWith(0, 0, x)
-			}
 		}
-		return true
 	}
-	return false
+	if rec := ctx.recorder(); rec != nil {
+		rec.Use(x, v)
+	}
+	cb := ctx.cb.Val(v, x)
+	if autocall {
+		cb.CallWith(0, 0, x)
+	}
+	return true
 }
 
 type fnType struct {


Test patch:
diff --git a/cl/builtin_test.go b/cl/builtin_test.go
index 3d03c7ad..c44fa00e 100644
--- a/cl/builtin_test.go
+++ b/cl/builtin_test.go
@@ -39,6 +39,21 @@ func getGoxConf() *gox.Config {
 	return &gox.Config{Fset: fset, Importer: imp}
 }
 
+func TestCompileFuncAlias(t *testing.T) {
+	ctx := &blockCtx{
+		pkgCtx: &pkgCtx{
+			syms: map[string]loader{"Foo": &baseLoader{
+				fn: func() {},
+			}},
+		},
+	}
+	scope := types.NewScope(nil, 0, 0, "")
+	x := ast.NewIdent("foo")
+	if compileFuncAlias(ctx, scope, x, 0) {
+		t.Fatal("compileFuncAlias: ok?")
+	}
+}
+
 func TestErrStringLit(t *testing.T) {
 	defer func() {
 		if e := recover(); e == nil {
diff --git a/cl/compile_gop_test.go b/cl/compile_gop_test.go
index b09eaf65..04dde8d4 100644
--- a/cl/compile_gop_test.go
+++ b/cl/compile_gop_test.go
@@ -20,6 +20,23 @@ import (
 	"testing"
 )
 
+func TestFuncAlias(t *testing.T) {
+	gopClTest(t, `
+func Foo(a ...int) {}
+
+foo 100
+foo
+`, `package main
+
+func Foo(a ...int) {
+}
+func main() {
+	Foo(100)
+	Foo()
+}
+`)
+}
+
 func TestOverloadOp(t *testing.T) {
 	gopClTest(t, `
 type foo struct {