Permalink
Browse files

improved cloning

  • Loading branch information...
1 parent f347191 commit 08d4c6cdac22b2f4a2eeaaa32e69691e2d343e4c @neelance neelance committed Jan 22, 2017
Showing with 37 additions and 48 deletions.
  1. +7 −10 compiler/expressions.go
  2. +10 −24 compiler/package.go
  3. +2 −6 compiler/statements.go
  4. +2 −8 compiler/utils.go
  5. +16 −0 tests/misc_test.go
@@ -756,12 +756,6 @@ func (c *funcContext) translateExpr(expr ast.Expr) *expression {
panic(fmt.Sprintf("Unhandled object: %T\n", o))
}
- case *this:
- if isWrapped(c.p.TypeOf(e)) {
- return c.formatExpr("this.$val")
- }
- return c.formatExpr("this")
-
case nil:
return c.formatExpr("")
@@ -772,7 +766,7 @@ func (c *funcContext) translateExpr(expr ast.Expr) *expression {
}
func (c *funcContext) translateCall(e *ast.CallExpr, sig *types.Signature, fun *expression) *expression {
- args := c.translateArgs(sig, e.Args, e.Ellipsis.IsValid(), false)
+ args := c.translateArgs(sig, e.Args, e.Ellipsis.IsValid())
if c.Blocking[e] {
resumeCase := c.caseCounter
c.caseCounter++
@@ -823,8 +817,11 @@ func (c *funcContext) makeReceiver(e *ast.SelectorExpr) *expression {
recvType = types.NewPointer(recvType)
x = c.setType(&ast.UnaryExpr{Op: token.AND, X: x}, recvType)
}
+ if isPointer && !pointerExpected {
+ x = c.setType(x, methodsRecvType)
+ }
- recv := c.translateExpr(x)
+ recv := c.translateImplicitConversionWithCloning(x, methodsRecvType)
if isWrapped(recvType) {
recv = c.formatExpr("new %s(%s)", c.typeName(methodsRecvType), recv)
}
@@ -896,7 +893,7 @@ func (c *funcContext) translateBuiltin(name string, sig *types.Signature, args [
return c.formatExpr("$panic(%s)", c.translateImplicitConversion(args[0], types.NewInterface(nil, nil)))
case "append":
if ellipsis || len(args) == 1 {
- argStr := c.translateArgs(sig, args, ellipsis, false)
+ argStr := c.translateArgs(sig, args, ellipsis)
return c.formatExpr("$appendSlice(%s, %s)", argStr[0], argStr[1])
}
sliceType := sig.Results().At(0).Type().Underlying().(*types.Slice)
@@ -912,7 +909,7 @@ func (c *funcContext) translateBuiltin(name string, sig *types.Signature, args [
case "print", "println":
return c.formatExpr("console.log(%s)", strings.Join(c.translateExprSlice(args, nil), ", "))
case "complex":
- argStr := c.translateArgs(sig, args, ellipsis, false)
+ argStr := c.translateArgs(sig, args, ellipsis)
return c.formatExpr("new %s(%s, %s)", c.typeName(sig.Results().At(0).Type()), argStr[0], argStr[1])
case "real":
return c.formatExpr("%e.$real", args[0])
View
@@ -606,17 +606,7 @@ func (c *funcContext) translateToplevelFunction(fun *ast.FuncDecl, info *analysi
return []byte(fmt.Sprintf("\t%s = function() {\n\t\t$throwRuntimeError(\"native function not implemented: %s\");\n\t};\n", funcRef, o.FullName()))
}
- var initStmts []ast.Stmt
- if recv != nil && !isBlank(recv) {
- initStmts = append([]ast.Stmt{
- &ast.AssignStmt{
- Lhs: []ast.Expr{recv},
- Tok: token.DEFINE,
- Rhs: []ast.Expr{c.setType(&this{}, sig.Recv().Type())},
- },
- }, initStmts...)
- }
- params, fun := translateFunction(fun.Type, initStmts, fun.Body, c, sig, info, funcRef)
+ params, fun := translateFunction(fun.Type, recv, fun.Body, c, sig, info, funcRef)
joinedParams = strings.Join(params, ", ")
return []byte(fmt.Sprintf("\t%s = %s;\n", funcRef, fun))
}
@@ -668,7 +658,7 @@ func (c *funcContext) translateToplevelFunction(fun *ast.FuncDecl, info *analysi
return code.Bytes()
}
-func translateFunction(typ *ast.FuncType, initStmts []ast.Stmt, body *ast.BlockStmt, outerContext *funcContext, sig *types.Signature, info *analysis.FuncInfo, funcRef string) ([]string, string) {
+func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt, outerContext *funcContext, sig *types.Signature, info *analysis.FuncInfo, funcRef string) ([]string, string) {
if info == nil {
panic("nil info")
}
@@ -701,17 +691,6 @@ func translateFunction(typ *ast.FuncType, initStmts []ast.Stmt, body *ast.BlockS
continue
}
params = append(params, c.objectName(c.p.Defs[ident]))
-
- switch c.p.Defs[ident].Type().Underlying().(type) {
- case *types.Array, *types.Struct:
- initStmts = append([]ast.Stmt{
- &ast.AssignStmt{
- Lhs: []ast.Expr{ident},
- Tok: token.DEFINE,
- Rhs: []ast.Expr{ident},
- },
- }, initStmts...)
- }
}
}
@@ -732,7 +711,14 @@ func translateFunction(typ *ast.FuncType, initStmts []ast.Stmt, body *ast.BlockS
}
}
- c.translateStmtList(initStmts)
+ if recv != nil && !isBlank(recv) {
+ this := "this"
+ if isWrapped(c.p.TypeOf(recv)) {
+ this = "this.$val"
+ }
+ c.Printf("%s = %s;", c.translateExpr(recv), this)
+ }
+
c.translateStmtList(body.List)
if len(c.Flattened) != 0 && !endsWithReturn(body.List) {
c.translateStmt(&ast.ReturnStmt{}, nil)
@@ -14,10 +14,6 @@ import (
"github.com/gopherjs/gopherjs/compiler/typesutil"
)
-type this struct {
- ast.Ident
-}
-
func (c *funcContext) translateStmtList(stmts []ast.Stmt) {
for _, stmt := range stmts {
c.translateStmt(stmt, nil)
@@ -330,7 +326,7 @@ func (c *funcContext) translateStmt(stmt ast.Stmt, label *types.Label) {
isJs = typesutil.IsJsPackage(c.p.Uses[fun.Sel].Pkg())
}
sig := c.p.TypeOf(s.Call.Fun).Underlying().(*types.Signature)
- args := c.translateArgs(sig, s.Call.Args, s.Call.Ellipsis.IsValid(), true)
+ args := c.translateArgs(sig, s.Call.Args, s.Call.Ellipsis.IsValid())
if isBuiltin || isJs {
vars := make([]string, len(s.Call.Args))
callArgs := make([]ast.Expr, len(s.Call.Args))
@@ -443,7 +439,7 @@ func (c *funcContext) translateStmt(stmt ast.Stmt, label *types.Label) {
c.translateStmt(s.Stmt, label)
case *ast.GoStmt:
- 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), ", "))
+ 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()), ", "))
case *ast.SendStmt:
chanType := c.p.TypeOf(s.Chan).Underlying().(*types.Chan)
View
@@ -74,7 +74,7 @@ func (c *funcContext) Delayed(f func()) {
c.delayedOutput = c.CatchOutput(0, f)
}
-func (c *funcContext) translateArgs(sig *types.Signature, argExprs []ast.Expr, ellipsis, clone bool) []string {
+func (c *funcContext) translateArgs(sig *types.Signature, argExprs []ast.Expr, ellipsis bool) []string {
if len(argExprs) == 1 {
if tuple, isTuple := c.p.TypeOf(argExprs[0]).(*types.Tuple); isTuple {
tupleVar := c.newVariable("_tuple")
@@ -108,13 +108,7 @@ func (c *funcContext) translateArgs(sig *types.Signature, argExprs []ast.Expr, e
argType = sig.Params().At(i).Type()
}
- var arg string
- switch {
- case clone:
- arg = c.translateImplicitConversionWithCloning(argExpr, argType).String()
- default:
- arg = c.translateImplicitConversion(argExpr, argType).String()
- }
+ arg := c.translateImplicitConversionWithCloning(argExpr, argType).String()
if preserveOrder && c.p.Types[argExpr].Value == nil {
argVar := c.newVariable("_arg")
View
@@ -596,3 +596,19 @@ func TestSliceOfString(t *testing.T) {
str := "foo"
print(str[0:10])
}
+
+type R struct{ v int }
+
+func (r R) Val() int {
+ return r.v
+}
+
+func TestReceiverCapture(t *testing.T) {
+ r := R{1}
+ f1 := r.Val
+ r = R{2}
+ f2 := r.Val
+ if f1() != 1 || f2() != 2 {
+ t.Fail()
+ }
+}

0 comments on commit 08d4c6c

Please sign in to comment.