func (sc *PackageScoping) MangleExpr(e ast.Expr) ast.Expr { switch e := e.(type) { case *ast.CallExpr: for i := range e.Args { e.Args[i] = sc.MangleExpr(e.Args[i]) } sc.MangleExpr(e.Fun) if fn, ok := e.Fun.(*ast.Ident); ok { switch fn.Name { case "print", "println": sc.Do("runtime.print") sc.Do("runtime.print_int") case "new": sc.Do("runtime.malloc") } } case *ast.Ident: if pkg, ok := sc.Globals[e.Name]; ok { // It's a global identifier, so we need to mangle it... sc.Do(pkg + "." + e.Name) oldname := e.Name e.Name = ManglePackageAndName(pkg, e.Name) fmt.Println("Name is", e.Name, "from", pkg, oldname) } else { // Nothing to do here, it is a local identifier or builtin. } case *ast.BasicLit: // Nothing to do here, a literal is never imported. case *ast.BinaryExpr: e.X = sc.MangleExpr(e.X) e.Y = sc.MangleExpr(e.Y) // FIXME: We could do better here if we had type information... switch e.Op { case token.EQL: sc.Do("runtime.strings_equal") case token.NEQ: sc.Do("runtime.strings_unequal") } case *ast.UnaryExpr: sc.MangleExpr(e.X) case *ast.ParenExpr: sc.MangleExpr(e.X) case *ast.IndexExpr: e.X = sc.MangleExpr(e.X) e.Index = sc.MangleExpr(e.Index) case *ast.SliceExpr: e.X = sc.MangleExpr(e.X) e.Low = sc.MangleExpr(e.Low) e.High = sc.MangleExpr(e.High) sc.Do("runtime.slice_string") case *ast.StarExpr: sc.MangleExpr(e.X) case *ast.SelectorExpr: if b, ok := e.X.(*ast.Ident); ok { if theimp, ok := sc.Imports[b.Name]; ok { sc.Do(theimp + "." + e.Sel.Name) e.Sel.Name = ManglePackageAndName(theimp, e.Sel.Name) return e.Sel } else { fmt.Println("not a package: ", b.Name) fmt.Println("Imports are", sc.Imports) sc.MangleExpr(e.X) } } else { sc.MangleExpr(e.X) } case *ast.StructType: for _, f := range e.Fields.List { sc.MangleExpr(f.Type) } case *ast.CompositeLit: e.Type = sc.MangleExpr(e.Type) for i := range e.Elts { e.Elts[i] = sc.MangleExpr(e.Elts[i]) } case *ast.MapType: e.Key = sc.MangleExpr(e.Key) e.Value = sc.MangleExpr(e.Value) case *ast.Ellipsis: e.Elt = sc.MangleExpr(e.Elt) case *ast.InterfaceType: for _, field := range e.Methods.List { field.Type = sc.MangleExpr(field.Type) } case *ast.ArrayType: e.Len = sc.MangleExpr(e.Len) e.Elt = sc.MangleExpr(e.Elt) case *ast.TypeAssertExpr: e.X = sc.MangleExpr(e.X) e.Type = sc.MangleExpr(e.Type) case *ast.FuncType: for _, field := range e.Params.List { field.Type = sc.MangleExpr(field.Type) } for _, field := range e.Results.List { field.Type = sc.MangleExpr(field.Type) } case *ast.FuncLit: for _, field := range e.Type.Params.List { field.Type = sc.MangleExpr(field.Type) } for _, field := range e.Type.Results.List { field.Type = sc.MangleExpr(field.Type) } sc.MangleStatement(e.Body) case *ast.KeyValueExpr: e.Key = sc.MangleExpr(e.Key) e.Value = sc.MangleExpr(e.Value) case nil: // Nothing to do with nil expression default: panic(fmt.Sprintf("Tracked weird expression of type %T", e)) } return e }