blob: ec3bef2db7a6f6ca9f4336e620e667c84dbb1a9e [file] [log] [blame]
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package go2go
import (
"fmt"
"go/types"
"strings"
"unicode"
)
// We use Oriya digit zero as a separator.
// Do not use this character in your own identifiers.
const nameSep = '୦'
// We use Oriya digit eight to introduce a special character code.
// Do not use this character in your own identifiers.
const nameIntro = '୮'
var nameCodes = map[rune]int{
' ': 0,
'*': 1,
';': 2,
',': 3,
'{': 4,
'}': 5,
'[': 6,
']': 7,
'(': 8,
')': 9,
'.': 10,
'<': 11,
'-': 12,
'/': 13,
nameSep: 14,
nameIntro: 15,
}
// instantiatedName returns the name of a newly instantiated function.
func (t *translator) instantiatedName(qid qualifiedIdent, types []types.Type) (string, error) {
var sb strings.Builder
fmt.Fprintf(&sb, "instantiate%c", nameSep)
if qid.pkg != nil {
fmt.Fprintf(&sb, qid.pkg.Name())
}
fmt.Fprintf(&sb, "%c%s", nameSep, qid.ident.Name)
for _, typ := range types {
sb.WriteRune(nameSep)
s := t.withoutTags(typ).String()
// We have to uniquely translate s into a valid Go identifier.
// This is not possible in general but we assume that
// identifiers will not contain nameSep or nameIntro.
for _, r := range s {
if (unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_') && r != nameSep && r != nameIntro {
sb.WriteRune(r)
} else {
code, ok := nameCodes[r]
if !ok {
panic(fmt.Sprintf("%s: unexpected type string character %q in %q", t.fset.Position(qid.ident.Pos()), r, s))
}
fmt.Fprintf(&sb, "%c%x", nameIntro, code)
}
}
}
return sb.String(), nil
}
// importableName returns a name that we define in each package, so that
// we have something to import to avoid an unused package error.
func (t *translator) importableName() string {
return "Importable" + string(nameSep)
}