Skip to content

Commit 08d4c6c

Browse files
committed
improved cloning
1 parent f347191 commit 08d4c6c

File tree

5 files changed

+37
-48
lines changed

5 files changed

+37
-48
lines changed

compiler/expressions.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -756,12 +756,6 @@ func (c *funcContext) translateExpr(expr ast.Expr) *expression {
756756
panic(fmt.Sprintf("Unhandled object: %T\n", o))
757757
}
758758

759-
case *this:
760-
if isWrapped(c.p.TypeOf(e)) {
761-
return c.formatExpr("this.$val")
762-
}
763-
return c.formatExpr("this")
764-
765759
case nil:
766760
return c.formatExpr("")
767761

@@ -772,7 +766,7 @@ func (c *funcContext) translateExpr(expr ast.Expr) *expression {
772766
}
773767

774768
func (c *funcContext) translateCall(e *ast.CallExpr, sig *types.Signature, fun *expression) *expression {
775-
args := c.translateArgs(sig, e.Args, e.Ellipsis.IsValid(), false)
769+
args := c.translateArgs(sig, e.Args, e.Ellipsis.IsValid())
776770
if c.Blocking[e] {
777771
resumeCase := c.caseCounter
778772
c.caseCounter++
@@ -823,8 +817,11 @@ func (c *funcContext) makeReceiver(e *ast.SelectorExpr) *expression {
823817
recvType = types.NewPointer(recvType)
824818
x = c.setType(&ast.UnaryExpr{Op: token.AND, X: x}, recvType)
825819
}
820+
if isPointer && !pointerExpected {
821+
x = c.setType(x, methodsRecvType)
822+
}
826823

827-
recv := c.translateExpr(x)
824+
recv := c.translateImplicitConversionWithCloning(x, methodsRecvType)
828825
if isWrapped(recvType) {
829826
recv = c.formatExpr("new %s(%s)", c.typeName(methodsRecvType), recv)
830827
}
@@ -896,7 +893,7 @@ func (c *funcContext) translateBuiltin(name string, sig *types.Signature, args [
896893
return c.formatExpr("$panic(%s)", c.translateImplicitConversion(args[0], types.NewInterface(nil, nil)))
897894
case "append":
898895
if ellipsis || len(args) == 1 {
899-
argStr := c.translateArgs(sig, args, ellipsis, false)
896+
argStr := c.translateArgs(sig, args, ellipsis)
900897
return c.formatExpr("$appendSlice(%s, %s)", argStr[0], argStr[1])
901898
}
902899
sliceType := sig.Results().At(0).Type().Underlying().(*types.Slice)
@@ -912,7 +909,7 @@ func (c *funcContext) translateBuiltin(name string, sig *types.Signature, args [
912909
case "print", "println":
913910
return c.formatExpr("console.log(%s)", strings.Join(c.translateExprSlice(args, nil), ", "))
914911
case "complex":
915-
argStr := c.translateArgs(sig, args, ellipsis, false)
912+
argStr := c.translateArgs(sig, args, ellipsis)
916913
return c.formatExpr("new %s(%s, %s)", c.typeName(sig.Results().At(0).Type()), argStr[0], argStr[1])
917914
case "real":
918915
return c.formatExpr("%e.$real", args[0])

compiler/package.go

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -606,17 +606,7 @@ func (c *funcContext) translateToplevelFunction(fun *ast.FuncDecl, info *analysi
606606
return []byte(fmt.Sprintf("\t%s = function() {\n\t\t$throwRuntimeError(\"native function not implemented: %s\");\n\t};\n", funcRef, o.FullName()))
607607
}
608608

609-
var initStmts []ast.Stmt
610-
if recv != nil && !isBlank(recv) {
611-
initStmts = append([]ast.Stmt{
612-
&ast.AssignStmt{
613-
Lhs: []ast.Expr{recv},
614-
Tok: token.DEFINE,
615-
Rhs: []ast.Expr{c.setType(&this{}, sig.Recv().Type())},
616-
},
617-
}, initStmts...)
618-
}
619-
params, fun := translateFunction(fun.Type, initStmts, fun.Body, c, sig, info, funcRef)
609+
params, fun := translateFunction(fun.Type, recv, fun.Body, c, sig, info, funcRef)
620610
joinedParams = strings.Join(params, ", ")
621611
return []byte(fmt.Sprintf("\t%s = %s;\n", funcRef, fun))
622612
}
@@ -668,7 +658,7 @@ func (c *funcContext) translateToplevelFunction(fun *ast.FuncDecl, info *analysi
668658
return code.Bytes()
669659
}
670660

671-
func translateFunction(typ *ast.FuncType, initStmts []ast.Stmt, body *ast.BlockStmt, outerContext *funcContext, sig *types.Signature, info *analysis.FuncInfo, funcRef string) ([]string, string) {
661+
func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt, outerContext *funcContext, sig *types.Signature, info *analysis.FuncInfo, funcRef string) ([]string, string) {
672662
if info == nil {
673663
panic("nil info")
674664
}
@@ -701,17 +691,6 @@ func translateFunction(typ *ast.FuncType, initStmts []ast.Stmt, body *ast.BlockS
701691
continue
702692
}
703693
params = append(params, c.objectName(c.p.Defs[ident]))
704-
705-
switch c.p.Defs[ident].Type().Underlying().(type) {
706-
case *types.Array, *types.Struct:
707-
initStmts = append([]ast.Stmt{
708-
&ast.AssignStmt{
709-
Lhs: []ast.Expr{ident},
710-
Tok: token.DEFINE,
711-
Rhs: []ast.Expr{ident},
712-
},
713-
}, initStmts...)
714-
}
715694
}
716695
}
717696

@@ -732,7 +711,14 @@ func translateFunction(typ *ast.FuncType, initStmts []ast.Stmt, body *ast.BlockS
732711
}
733712
}
734713

735-
c.translateStmtList(initStmts)
714+
if recv != nil && !isBlank(recv) {
715+
this := "this"
716+
if isWrapped(c.p.TypeOf(recv)) {
717+
this = "this.$val"
718+
}
719+
c.Printf("%s = %s;", c.translateExpr(recv), this)
720+
}
721+
736722
c.translateStmtList(body.List)
737723
if len(c.Flattened) != 0 && !endsWithReturn(body.List) {
738724
c.translateStmt(&ast.ReturnStmt{}, nil)

compiler/statements.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ import (
1414
"github.com/gopherjs/gopherjs/compiler/typesutil"
1515
)
1616

17-
type this struct {
18-
ast.Ident
19-
}
20-
2117
func (c *funcContext) translateStmtList(stmts []ast.Stmt) {
2218
for _, stmt := range stmts {
2319
c.translateStmt(stmt, nil)
@@ -330,7 +326,7 @@ func (c *funcContext) translateStmt(stmt ast.Stmt, label *types.Label) {
330326
isJs = typesutil.IsJsPackage(c.p.Uses[fun.Sel].Pkg())
331327
}
332328
sig := c.p.TypeOf(s.Call.Fun).Underlying().(*types.Signature)
333-
args := c.translateArgs(sig, s.Call.Args, s.Call.Ellipsis.IsValid(), true)
329+
args := c.translateArgs(sig, s.Call.Args, s.Call.Ellipsis.IsValid())
334330
if isBuiltin || isJs {
335331
vars := make([]string, len(s.Call.Args))
336332
callArgs := make([]ast.Expr, len(s.Call.Args))
@@ -443,7 +439,7 @@ func (c *funcContext) translateStmt(stmt ast.Stmt, label *types.Label) {
443439
c.translateStmt(s.Stmt, label)
444440

445441
case *ast.GoStmt:
446-
c.Printf("$go(%s, [%s]);", c.translateExpr(s.Call.Fun), strings.Join(c.translateArgs(c.p.TypeOf(s.Call.Fun).Underlying().(*types.Signature), s.Call.Args, s.Call.Ellipsis.IsValid(), true), ", "))
442+
c.Printf("$go(%s, [%s]);", c.translateExpr(s.Call.Fun), strings.Join(c.translateArgs(c.p.TypeOf(s.Call.Fun).Underlying().(*types.Signature), s.Call.Args, s.Call.Ellipsis.IsValid()), ", "))
447443

448444
case *ast.SendStmt:
449445
chanType := c.p.TypeOf(s.Chan).Underlying().(*types.Chan)

compiler/utils.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func (c *funcContext) Delayed(f func()) {
7474
c.delayedOutput = c.CatchOutput(0, f)
7575
}
7676

77-
func (c *funcContext) translateArgs(sig *types.Signature, argExprs []ast.Expr, ellipsis, clone bool) []string {
77+
func (c *funcContext) translateArgs(sig *types.Signature, argExprs []ast.Expr, ellipsis bool) []string {
7878
if len(argExprs) == 1 {
7979
if tuple, isTuple := c.p.TypeOf(argExprs[0]).(*types.Tuple); isTuple {
8080
tupleVar := c.newVariable("_tuple")
@@ -108,13 +108,7 @@ func (c *funcContext) translateArgs(sig *types.Signature, argExprs []ast.Expr, e
108108
argType = sig.Params().At(i).Type()
109109
}
110110

111-
var arg string
112-
switch {
113-
case clone:
114-
arg = c.translateImplicitConversionWithCloning(argExpr, argType).String()
115-
default:
116-
arg = c.translateImplicitConversion(argExpr, argType).String()
117-
}
111+
arg := c.translateImplicitConversionWithCloning(argExpr, argType).String()
118112

119113
if preserveOrder && c.p.Types[argExpr].Value == nil {
120114
argVar := c.newVariable("_arg")

tests/misc_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,3 +596,19 @@ func TestSliceOfString(t *testing.T) {
596596
str := "foo"
597597
print(str[0:10])
598598
}
599+
600+
type R struct{ v int }
601+
602+
func (r R) Val() int {
603+
return r.v
604+
}
605+
606+
func TestReceiverCapture(t *testing.T) {
607+
r := R{1}
608+
f1 := r.Val
609+
r = R{2}
610+
f2 := r.Val
611+
if f1() != 1 || f2() != 2 {
612+
t.Fail()
613+
}
614+
}

0 commit comments

Comments
 (0)