作者:hackrol
项目:daily-progra
func (p *exporter) value(x exact.Value) {
if trace {
p.tracef("value { ")
defer p.tracef("} ")
}
switch kind := x.Kind(); kind {
case exact.Bool:
tag := falseTag
if exact.BoolVal(x) {
tag = trueTag
}
p.int(tag)
case exact.Int:
if i, ok := exact.Int64Val(x); ok {
p.int(int64Tag)
p.int64(i)
return
}
p.int(floatTag)
p.float(x)
case exact.Float:
p.int(fractionTag)
p.fraction(x)
case exact.Complex:
p.int(complexTag)
p.fraction(exact.Real(x))
p.fraction(exact.Imag(x))
case exact.String:
p.int(stringTag)
p.string(exact.StringVal(x))
default:
panic(fmt.Sprintf("unexpected value kind %d", kind))
}
}
作者:4hono
项目:obd
// checkPrintf checks a call to a formatted print routine such as Printf.
// call.Args[formatIndex] is (well, should be) the format argument.
func (f *File) checkPrintf(call *ast.CallExpr, name string, formatIndex int) {
if formatIndex >= len(call.Args) {
f.Bad(call.Pos(), "too few arguments in call to", name)
return
}
lit := f.pkg.types[call.Args[formatIndex]].Value
if lit == nil {
if *verbose {
f.Warn(call.Pos(), "can't check non-constant format in call to", name)
}
return
}
if lit.Kind() != exact.String {
f.Badf(call.Pos(), "constant %v not a string in call to %s", lit, name)
return
}
format := exact.StringVal(lit)
firstArg := formatIndex + 1 // Arguments are immediately after format string.
if !strings.Contains(format, "%") {
if len(call.Args) > firstArg {
f.Badf(call.Pos(), "no formatting directive in %s call", name)
}
return
}
// Hard part: check formats against args.
argNum := firstArg
indexed := false
for i, w := 0, 0; i < len(format); i += w {
w = 1
if format[i] == '%' {
state := f.parsePrintfVerb(call, name, format[i:], firstArg, argNum)
if state == nil {
return
}
w = len(state.format)
if state.indexed {
indexed = true
}
if !f.okPrintfArg(call, state) { // One error per format is enough.
return
}
if len(state.argNums) > 0 {
// Continue with the next sequential argument.
argNum = state.argNums[len(state.argNums)-1] + 1
}
}
}
// Dotdotdot is hard.
if call.Ellipsis.IsValid() && argNum >= len(call.Args)-1 {
return
}
// If the arguments were direct indexed, we assume the programmer knows what's up.
// Otherwise, there should be no leftover arguments.
if !indexed && argNum != len(call.Args) {
expect := argNum - firstArg
numArgs := len(call.Args) - firstArg
f.Badf(call.Pos(), "wrong number of args for format in %s call: %d needed but %d args", name, expect, numArgs)
}
}
作者:BrianI
项目:metric
//ranges through config file and checks all expressions.
// prints result messages to stdout
func (c *checker) CheckAll() ([]CheckResult, error) {
result := []CheckResult{}
cnf, err := conf.ReadConfigFile(c.configFile)
if err != nil {
return nil, err
}
for _, section := range cnf.GetSections() {
if section == "default" {
continue
}
expr, _ := cnf.GetString(section, "expr")
_, r, err := types.Eval(expr, c.pkg, c.sc)
if err != nil {
fmt.Fprintln(os.Stderr, err)
continue
}
cr := &CheckResult{
Name: section,
}
var m string
if exact.BoolVal(r) {
m, err = cnf.GetString(section, "true")
if err != nil {
continue
}
} else {
m, err = cnf.GetString(section, "false")
if err != nil {
continue
}
}
val, err := cnf.GetString(section, "val")
if err == nil {
t, v, err := types.Eval(val, c.pkg, c.sc)
if err == nil {
if types.Identical(t, types.Typ[types.UntypedFloat]) || types.Identical(t, types.Typ[types.Float64]) {
x, _ := exact.Float64Val(v)
cr.Value = x
}
}
}
owner, err := cnf.GetString(section, "owner")
if err == nil {
cr.Owner = owner
} else {
cr.Owner = "unknown"
}
_, msg, err := types.Eval(m, c.pkg, c.sc)
if err != nil {
cr.Message = m
} else {
cr.Message = exact.StringVal(msg)
}
result = append(result, *cr)
}
return result, nil
}
作者:4hono
项目:obd
// constValue returns the value of the constant with the
// dynamic type tag appropriate for c.Type().
func constValue(c *ssa.Const) value {
if c.IsNil() {
return zero(c.Type()) // typed nil
}
if t, ok := c.Type().Underlying().(*types.Basic); ok {
// TODO(adonovan): eliminate untyped constants from SSA form.
switch t.Kind() {
case types.Bool, types.UntypedBool:
return exact.BoolVal(c.Value)
case types.Int, types.UntypedInt:
// Assume sizeof(int) is same on host and target.
return int(c.Int64())
case types.Int8:
return int8(c.Int64())
case types.Int16:
return int16(c.Int64())
case types.Int32, types.UntypedRune:
return int32(c.Int64())
case types.Int64:
return c.Int64()
case types.Uint:
// Assume sizeof(uint) is same on host and target.
return uint(c.Uint64())
case types.Uint8:
return uint8(c.Uint64())
case types.Uint16:
return uint16(c.Uint64())
case types.Uint32:
return uint32(c.Uint64())
case types.Uint64:
return c.Uint64()
case types.Uintptr:
// Assume sizeof(uintptr) is same on host and target.
return uintptr(c.Uint64())
case types.Float32:
return float32(c.Float64())
case types.Float64, types.UntypedFloat:
return c.Float64()
case types.Complex64:
return complex64(c.Complex128())
case types.Complex128, types.UntypedComplex:
return c.Complex128()
case types.String, types.UntypedString:
if c.Value.Kind() == exact.String {
return exact.StringVal(c.Value)
}
return string(rune(c.Int64()))
}
}
panic(fmt.Sprintf("constValue: %s", c))
}
作者:nagyistg
项目:hm-workspac
func (c *Const) Name() string {
var s string
if c.Value.Kind() == exact.String {
s = exact.StringVal(c.Value)
const max = 20
if len(s) > max {
s = s[:max-3] + "..." // abbreviate
}
s = strconv.Quote(s)
} else {
s = c.Value.String()
}
return s + ":" + c.typ.String()
}
作者:pombredann
项目:go.tool
func (l *Literal) Name() string {
var s string
if l.Value.Kind() == exact.String {
s = exact.StringVal(l.Value)
const maxLit = 20
if len(s) > maxLit {
s = s[:maxLit-3] + "..." // abbreviate
}
s = strconv.Quote(s)
} else {
s = l.Value.String()
}
return s + ":" + l.Type_.String()
}
作者:ufo2294026
项目:two-server-other
func (c *Const) valstring() string {
if c.Value == nil {
return "nil"
} else if c.Value.Kind() == exact.String {
s := exact.StringVal(c.Value)
const max = 20
if len(s) > max {
s = s[:max-3] + "..." // abbreviate
}
return strconv.Quote(s)
} else {
return c.Value.String()
}
}
作者:nvdnkp
项目:gopherj
func (c *funcContext) identifierConstant(expr ast.Expr) (string, bool) {
val := c.p.info.Types[expr].Value
if val == nil {
return "", false
}
s := exact.StringVal(val)
if len(s) == 0 {
return "", false
}
for i, c := range s {
if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (i > 0 && c >= '0' && c <= '9') || c == '_' || c == '$') {
return "", false
}
}
return s, true
}
作者:4hono
项目:obd
func (c *Const) RelString(from *types.Package) string {
var s string
if c.Value == nil {
s = "nil"
} else if c.Value.Kind() == exact.String {
s = exact.StringVal(c.Value)
const max = 20
// TODO(adonovan): don't cut a rune in half.
if len(s) > max {
s = s[:max-3] + "..." // abbreviate
}
s = strconv.Quote(s)
} else {
s = c.Value.String()
}
return s + ":" + relType(c.Type(), from)
}
作者:ufo2294026
项目:two-server-other
func ext۰reflect۰rtype۰MethodByName(a *analysis, cgn *cgnode) {
// If we have access to the callsite,
// and the argument is a string constant,
// return only that method.
var name string
if site := cgn.callersite; site != nil {
if c, ok := site.instr.Common().Args[0].(*ssa.Const); ok {
name = exact.StringVal(c.Value)
}
}
a.addConstraint(&rtypeMethodByNameConstraint{
cgn: cgn,
name: name,
t: a.funcParams(cgn.obj),
result: a.funcResults(cgn.obj),
})
}
作者:Logirapto
项目:na
func analyzeNapParam(pkg *types.Package, info *types.Info, c *ast.CallExpr) (string, bool) {
sel, ok := c.Fun.(*ast.SelectorExpr)
if !ok {
return "", false
}
xType := info.Types[sel.X]
if xType.Type == nil {
return "", false
}
if xType.Type.String() != "github.com/Logiraptor/nap.Request" {
return "", false
}
// printNode(c)
nameTV := info.Types[c.Args[0]]
return exact.StringVal(nameTV.Value), true
}
作者:4hono
项目:obd
func Test(t *testing.T) {
switch runtime.GOOS {
case "windows":
t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
}
conf := loader.Config{
Fset: token.NewFileSet(),
ParserMode: parser.ParseComments,
SourceImports: true,
}
// Each entry is a single-file package.
// (Multi-file packages aren't interesting for this test.)
// Order matters: each non-template package is processed using
// the preceding template package.
for _, filename := range []string{
"testdata/A.template",
"testdata/A1.go",
"testdata/A2.go",
"testdata/B.template",
"testdata/B1.go",
"testdata/C.template",
"testdata/C1.go",
"testdata/D.template",
"testdata/D1.go",
"testdata/E.template",
"testdata/E1.go",
"testdata/bad_type.template",
"testdata/no_before.template",
"testdata/no_after_return.template",
"testdata/type_mismatch.template",
"testdata/expr_type_mismatch.template",
} {
pkgname := strings.TrimSuffix(filepath.Base(filename), ".go")
if err := conf.CreateFromFilenames(pkgname, filename); err != nil {
t.Fatal(err)
}
}
iprog, err := conf.Load()
if err != nil {
t.Fatal(err)
}
var xform *eg.Transformer
for _, info := range iprog.Created {
file := info.Files[0]
filename := iprog.Fset.File(file.Pos()).Name() // foo.go
if strings.HasSuffix(filename, "template") {
// a new template
shouldFail, _ := info.Pkg.Scope().Lookup("shouldFail").(*types.Const)
xform, err = eg.NewTransformer(iprog.Fset, info, *verboseFlag)
if err != nil {
if shouldFail == nil {
t.Errorf("NewTransformer(%s): %s", filename, err)
} else if want := exact.StringVal(shouldFail.Val()); !strings.Contains(err.Error(), want) {
t.Errorf("NewTransformer(%s): got error %q, want error %q", filename, err, want)
}
} else if shouldFail != nil {
t.Errorf("NewTransformer(%s) succeeded unexpectedly; want error %q",
filename, shouldFail.Val())
}
continue
}
if xform == nil {
t.Errorf("%s: no previous template", filename)
continue
}
// apply previous template to this package
n := xform.Transform(&info.Info, info.Pkg, file)
if n == 0 {
t.Errorf("%s: no matches", filename)
continue
}
got := filename + "t" // foo.got
golden := filename + "lden" // foo.golden
// Write actual output to foo.got.
if err := eg.WriteAST(iprog.Fset, got, file); err != nil {
t.Error(err)
}
defer os.Remove(got)
// Compare foo.got with foo.golden.
var cmd *exec.Cmd
switch runtime.GOOS {
case "plan9":
cmd = exec.Command("/bin/diff", "-c", golden, got)
default:
cmd = exec.Command("/usr/bin/diff", "-u", golden, got)
}
//.........这里部分代码省略.........
作者:umisam
项目:gopherj
func (c *PkgContext) translateExpr(expr ast.Expr) string {
exprType := c.info.Types[expr]
if value, valueFound := c.info.Values[expr]; valueFound {
basic := types.Typ[types.String]
if value.Kind() != exact.String { // workaround for bug in go/types
basic = exprType.Underlying().(*types.Basic)
}
switch {
case basic.Info()&types.IsBoolean != 0:
return strconv.FormatBool(exact.BoolVal(value))
case basic.Info()&types.IsInteger != 0:
if is64Bit(basic) {
d, _ := exact.Uint64Val(value)
return fmt.Sprintf("new %s(%d, %d)", c.typeName(exprType), d>>32, d&(1<<32-1))
}
d, _ := exact.Int64Val(value)
return strconv.FormatInt(d, 10)
case basic.Info()&types.IsFloat != 0:
f, _ := exact.Float64Val(value)
return strconv.FormatFloat(f, 'g', -1, 64)
case basic.Info()&types.IsComplex != 0:
r, _ := exact.Float64Val(exact.Real(value))
i, _ := exact.Float64Val(exact.Imag(value))
if basic.Kind() == types.UntypedComplex {
exprType = types.Typ[types.Complex128]
}
return fmt.Sprintf("new %s(%s, %s)", c.typeName(exprType), strconv.FormatFloat(r, 'g', -1, 64), strconv.FormatFloat(i, 'g', -1, 64))
case basic.Info()&types.IsString != 0:
buffer := bytes.NewBuffer(nil)
for _, r := range []byte(exact.StringVal(value)) {
switch r {
case '\b':
buffer.WriteString(`\b`)
case '\f':
buffer.WriteString(`\f`)
case '\n':
buffer.WriteString(`\n`)
case '\r':
buffer.WriteString(`\r`)
case '\t':
buffer.WriteString(`\t`)
case '\v':
buffer.WriteString(`\v`)
case '"':
buffer.WriteString(`\"`)
case '\\':
buffer.WriteString(`\\`)
default:
if r < 0x20 || r > 0x7E {
fmt.Fprintf(buffer, `\x%02X`, r)
continue
}
buffer.WriteByte(r)
}
}
return `"` + buffer.String() + `"`
default:
panic("Unhandled constant type: " + basic.String())
}
}
switch e := expr.(type) {
case *ast.CompositeLit:
if ptrType, isPointer := exprType.(*types.Pointer); isPointer {
exprType = ptrType.Elem()
}
collectIndexedElements := func(elementType types.Type) []string {
elements := make([]string, 0)
i := 0
zero := c.zeroValue(elementType)
for _, element := range e.Elts {
if kve, isKve := element.(*ast.KeyValueExpr); isKve {
key, _ := exact.Int64Val(c.info.Values[kve.Key])
i = int(key)
element = kve.Value
}
for len(elements) <= i {
elements = append(elements, zero)
}
elements[i] = c.translateExprToType(element, elementType)
i++
}
return elements
}
switch t := exprType.Underlying().(type) {
case *types.Array:
elements := collectIndexedElements(t.Elem())
if len(elements) != 0 {
zero := c.zeroValue(t.Elem())
for len(elements) < int(t.Len()) {
elements = append(elements, zero)
}
return createListComposite(t.Elem(), elements)
}
return fmt.Sprintf("Go$makeArray(%s, %d, function() { return %s; })", toArrayType(t.Elem()), t.Len(), c.zeroValue(t.Elem()))
case *types.Slice:
return fmt.Sprintf("new %s(%s)", c.typeName(exprType), createListComposite(t.Elem(), collectIndexedElements(t.Elem())))
case *types.Map:
//.........这里部分代码省略.........
作者:kpsmit
项目:gopherj
func Write(pkg *types.Package, out io.Writer, sizes types.Sizes) {
fmt.Fprintf(out, "package %s\n", pkg.Name())
e := &exporter{pkg: pkg, imports: make(map[*types.Package]bool), out: out}
for _, imp := range pkg.Imports() {
e.addImport(imp)
}
for _, name := range pkg.Scope().Names() {
obj := pkg.Scope().Lookup(name)
_, isTypeName := obj.(*types.TypeName)
if obj.Exported() || isTypeName {
e.toExport = append(e.toExport, obj)
}
}
for i := 0; i < len(e.toExport); i++ {
switch o := e.toExport[i].(type) {
case *types.TypeName:
fmt.Fprintf(out, "type %s %s\n", e.makeName(o), e.makeType(o.Type().Underlying()))
if _, isInterface := o.Type().Underlying().(*types.Interface); !isInterface {
writeMethods := func(t types.Type) {
methods := types.NewMethodSet(t)
for i := 0; i < methods.Len(); i++ {
m := methods.At(i)
if len(m.Index()) > 1 {
continue // method of embedded field
}
out.Write([]byte("func (? " + e.makeType(m.Recv()) + ") " + e.makeName(m.Obj()) + e.makeSignature(m.Type()) + "\n"))
}
}
writeMethods(o.Type())
writeMethods(types.NewPointer(o.Type()))
}
case *types.Func:
out.Write([]byte("func " + e.makeName(o) + e.makeSignature(o.Type()) + "\n"))
case *types.Const:
optType := ""
basic, isBasic := o.Type().(*types.Basic)
if !isBasic || basic.Info()&types.IsUntyped == 0 {
optType = " " + e.makeType(o.Type())
}
basic = o.Type().Underlying().(*types.Basic)
var val string
switch {
case basic.Info()&types.IsBoolean != 0:
val = strconv.FormatBool(exact.BoolVal(o.Val()))
case basic.Info()&types.IsInteger != 0:
if basic.Kind() == types.Uint64 {
d, _ := exact.Uint64Val(o.Val())
val = fmt.Sprintf("%#x", d)
break
}
d, _ := exact.Int64Val(o.Val())
if basic.Kind() == types.UntypedRune {
switch {
case d < 0 || d > unicode.MaxRune:
val = fmt.Sprintf("('\\x00' + %d)", d)
case d > 0xffff:
val = fmt.Sprintf("'\\U%08x'", d)
default:
val = fmt.Sprintf("'\\u%04x'", d)
}
break
}
val = fmt.Sprintf("%#x", d)
case basic.Info()&types.IsFloat != 0:
f, _ := exact.Float64Val(o.Val())
val = strconv.FormatFloat(f, 'b', -1, 64)
case basic.Info()&types.IsComplex != 0:
r, _ := exact.Float64Val(exact.Real(o.Val()))
i, _ := exact.Float64Val(exact.Imag(o.Val()))
val = fmt.Sprintf("(%s+%si)", strconv.FormatFloat(r, 'b', -1, 64), strconv.FormatFloat(i, 'b', -1, 64))
case basic.Info()&types.IsString != 0:
val = fmt.Sprintf("%#v", exact.StringVal(o.Val()))
default:
panic("Unhandled constant type: " + basic.String())
}
out.Write([]byte("const " + e.makeName(o) + optType + " = " + val + "\n"))
case *types.Var:
out.Write([]byte("var " + e.makeName(o) + " " + e.makeType(o.Type()) + "\n"))
default:
panic(fmt.Sprintf("Unhandled object: %T\n", o))
}
}
fmt.Fprintf(out, "$$\n")
}
作者:hajimehosh
项目:gopherj
func (c *funcContext) translateExpr(expr ast.Expr) *expression {
exprType := c.p.info.Types[expr].Type
if value := c.p.info.Types[expr].Value; value != nil {
basic := types.Typ[types.String]
if value.Kind() != exact.String { // workaround for bug in go/types
basic = exprType.Underlying().(*types.Basic)
}
switch {
case basic.Info()&types.IsBoolean != 0:
return c.formatExpr("%s", strconv.FormatBool(exact.BoolVal(value)))
case basic.Info()&types.IsInteger != 0:
if is64Bit(basic) {
d, _ := exact.Uint64Val(value)
if basic.Kind() == types.Int64 {
return c.formatExpr("new %s(%s, %s)", c.typeName(exprType), strconv.FormatInt(int64(d)>>32, 10), strconv.FormatUint(d&(1<<32-1), 10))
}
return c.formatExpr("new %s(%s, %s)", c.typeName(exprType), strconv.FormatUint(d>>32, 10), strconv.FormatUint(d&(1<<32-1), 10))
}
d, _ := exact.Int64Val(value)
return c.formatExpr("%s", strconv.FormatInt(d, 10))
case basic.Info()&types.IsFloat != 0:
f, _ := exact.Float64Val(value)
return c.formatExpr("%s", strconv.FormatFloat(f, 'g', -1, 64))
case basic.Info()&types.IsComplex != 0:
r, _ := exact.Float64Val(exact.Real(value))
i, _ := exact.Float64Val(exact.Imag(value))
if basic.Kind() == types.UntypedComplex {
exprType = types.Typ[types.Complex128]
}
return c.formatExpr("new %s(%s, %s)", c.typeName(exprType), strconv.FormatFloat(r, 'g', -1, 64), strconv.FormatFloat(i, 'g', -1, 64))
case basic.Info()&types.IsString != 0:
return c.formatExpr("%s", encodeString(exact.StringVal(value)))
default:
panic("Unhandled constant type: " + basic.String())
}
}
switch e := expr.(type) {
case *ast.CompositeLit:
if ptrType, isPointer := exprType.(*types.Pointer); isPointer {
exprType = ptrType.Elem()
}
collectIndexedElements := func(elementType types.Type) []string {
elements := make([]string, 0)
i := 0
zero := c.zeroValue(elementType)
for _, element := range e.Elts {
if kve, isKve := element.(*ast.KeyValueExpr); isKve {
key, _ := exact.Int64Val(c.p.info.Types[kve.Key].Value)
i = int(key)
element = kve.Value
}
for len(elements) <= i {
elements = append(elements, zero)
}
elements[i] = c.translateImplicitConversion(element, elementType).String()
i++
}
return elements
}
switch t := exprType.Underlying().(type) {
case *types.Array:
elements := collectIndexedElements(t.Elem())
if len(elements) != 0 {
zero := c.zeroValue(t.Elem())
for len(elements) < int(t.Len()) {
elements = append(elements, zero)
}
return c.formatExpr(`go$toNativeArray("%s", [%s])`, typeKind(t.Elem()), strings.Join(elements, ", "))
}
return c.formatExpr(`go$makeNativeArray("%s", %d, function() { return %s; })`, typeKind(t.Elem()), int(t.Len()), c.zeroValue(t.Elem()))
case *types.Slice:
return c.formatExpr("new %s([%s])", c.typeName(exprType), strings.Join(collectIndexedElements(t.Elem()), ", "))
case *types.Map:
mapVar := c.newVariable("_map")
keyVar := c.newVariable("_key")
assignments := ""
for _, element := range e.Elts {
kve := element.(*ast.KeyValueExpr)
assignments += c.formatExpr(`%s = %s, %s[%s] = { k: %s, v: %s }, `, keyVar, c.translateImplicitConversion(kve.Key, t.Key()), mapVar, c.makeKey(c.newIdent(keyVar, t.Key()), t.Key()), keyVar, c.translateImplicitConversion(kve.Value, t.Elem())).String()
}
return c.formatExpr("(%s = new Go$Map(), %s%s)", mapVar, assignments, mapVar)
case *types.Struct:
elements := make([]string, t.NumFields())
isKeyValue := true
if len(e.Elts) != 0 {
_, isKeyValue = e.Elts[0].(*ast.KeyValueExpr)
}
if !isKeyValue {
for i, element := range e.Elts {
elements[i] = c.translateImplicitConversion(element, t.Field(i).Type()).String()
}
}
if isKeyValue {
for i := range elements {
elements[i] = c.zeroValue(t.Field(i).Type())
}
for _, element := range e.Elts {
//.........这里部分代码省略.........
作者:nagyistg
项目:hm-workspac
// builtin typechecks a call to a built-in and returns the result via x.
// If the call has type errors, the returned x is marked as invalid.
//
func (check *checker) builtin(x *operand, call *ast.CallExpr, id builtinId) {
args := call.Args
// declare before goto's
var arg0 ast.Expr // first argument, if present
// check argument count
n := len(args)
msg := ""
bin := predeclaredFuncs[id]
if n < bin.nargs {
msg = "not enough"
} else if !bin.variadic && n > bin.nargs {
msg = "too many"
}
if msg != "" {
check.invalidOp(call.Pos(), msg+" arguments for %s (expected %d, found %d)", call, bin.nargs, n)
goto Error
}
// common case: evaluate first argument if present;
// if it is an expression, x has the expression value
if n > 0 {
arg0 = args[0]
switch id {
case _Make, _New, _Print, _Println, _Offsetof, _Trace:
// respective cases below do the work
default:
// argument must be an expression
check.expr(x, arg0)
if x.mode == invalid {
goto Error
}
}
}
switch id {
case _Append:
if _, ok := x.typ.Underlying().(*Slice); !ok {
check.invalidArg(x.pos(), "%s is not a typed slice", x)
goto Error
}
resultTyp := x.typ
for _, arg := range args[1:] {
check.expr(x, arg)
if x.mode == invalid {
goto Error
}
// TODO(gri) check assignability
}
x.mode = value
x.typ = resultTyp
case _Cap, _Len:
mode := invalid
var val exact.Value
switch typ := implicitArrayDeref(x.typ.Underlying()).(type) {
case *Basic:
if isString(typ) && id == _Len {
if x.mode == constant {
mode = constant
val = exact.MakeInt64(int64(len(exact.StringVal(x.val))))
} else {
mode = value
}
}
case *Array:
mode = value
// spec: "The expressions len(s) and cap(s) are constants
// if the type of s is an array or pointer to an array and
// the expression s does not contain channel receives or
// function calls; in this case s is not evaluated."
if !check.containsCallsOrReceives(arg0) {
mode = constant
val = exact.MakeInt64(typ.len)
}
case *Slice, *Chan:
mode = value
case *Map:
if id == _Len {
mode = value
}
}
if mode == invalid {
check.invalidArg(x.pos(), "%s for %s", x, bin.name)
goto Error
}
x.mode = mode
x.typ = Typ[Int]
x.val = val
case _Close:
ch, ok := x.typ.Underlying().(*Chan)
//.........这里部分代码省略.........
作者:nvdnkp
项目:gopherj
func (c *funcContext) translateExpr(expr ast.Expr) *expression {
exprType := c.p.info.Types[expr].Type
if value := c.p.info.Types[expr].Value; value != nil {
basic := types.Typ[types.String]
if value.Kind() != exact.String { // workaround for bug in go/types
basic = exprType.Underlying().(*types.Basic)
}
switch {
case basic.Info()&types.IsBoolean != 0:
return c.formatExpr("%s", strconv.FormatBool(exact.BoolVal(value)))
case basic.Info()&types.IsInteger != 0:
if is64Bit(basic) {
d, _ := exact.Uint64Val(value)
if basic.Kind() == types.Int64 {
return c.formatExpr("new %s(%s, %s)", c.typeName(exprType), strconv.FormatInt(int64(d)>>32, 10), strconv.FormatUint(d&(1<<32-1), 10))
}
return c.formatExpr("new %s(%s, %s)", c.typeName(exprType), strconv.FormatUint(d>>32, 10), strconv.FormatUint(d&(1<<32-1), 10))
}
d, _ := exact.Int64Val(value)
return c.formatExpr("%s", strconv.FormatInt(d, 10))
case basic.Info()&types.IsFloat != 0:
f, _ := exact.Float64Val(value)
return c.formatExpr("%s", strconv.FormatFloat(f, 'g', -1, 64))
case basic.Info()&types.IsComplex != 0:
r, _ := exact.Float64Val(exact.Real(value))
i, _ := exact.Float64Val(exact.Imag(value))
if basic.Kind() == types.UntypedComplex {
exprType = types.Typ[types.Complex128]
}
return c.formatExpr("new %s(%s, %s)", c.typeName(exprType), strconv.FormatFloat(r, 'g', -1, 64), strconv.FormatFloat(i, 'g', -1, 64))
case basic.Info()&types.IsString != 0:
return c.formatExpr("%s", encodeString(exact.StringVal(value)))
default:
panic("Unhandled constant type: " + basic.String())
}
}
switch e := expr.(type) {
case *ast.CompositeLit:
if ptrType, isPointer := exprType.(*types.Pointer); isPointer {
exprType = ptrType.Elem()
}
collectIndexedElements := func(elementType types.Type) []string {
elements := make([]string, 0)
i := 0
zero := c.zeroValue(elementType)
for _, element := range e.Elts {
if kve, isKve := element.(*ast.KeyValueExpr); isKve {
key, _ := exact.Int64Val(c.p.info.Types[kve.Key].Value)
i = int(key)
element = kve.Value
}
for len(elements) <= i {
elements = append(elements, zero)
}
elements[i] = c.translateImplicitConversionWithCloning(element, elementType).String()
i++
}
return elements
}
switch t := exprType.Underlying().(type) {
case *types.Array:
elements := collectIndexedElements(t.Elem())
if len(elements) == 0 {
return c.formatExpr("%s", c.zeroValue(t))
}
zero := c.zeroValue(t.Elem())
for len(elements) < int(t.Len()) {
elements = append(elements, zero)
}
return c.formatExpr(`$toNativeArray("%s", [%s])`, typeKind(t.Elem()), strings.Join(elements, ", "))
case *types.Slice:
return c.formatExpr("new %s([%s])", c.typeName(exprType), strings.Join(collectIndexedElements(t.Elem()), ", "))
case *types.Map:
mapVar := c.newVariable("_map")
keyVar := c.newVariable("_key")
assignments := ""
for _, element := range e.Elts {
kve := element.(*ast.KeyValueExpr)
assignments += c.formatExpr(`%s = %s, %s[%s] = { k: %s, v: %s }, `, keyVar, c.translateImplicitConversion(kve.Key, t.Key()), mapVar, c.makeKey(c.newIdent(keyVar, t.Key()), t.Key()), keyVar, c.translateImplicitConversion(kve.Value, t.Elem())).String()
}
return c.formatExpr("(%s = new $Map(), %s%s)", mapVar, assignments, mapVar)
case *types.Struct:
elements := make([]string, t.NumFields())
isKeyValue := true
if len(e.Elts) != 0 {
_, isKeyValue = e.Elts[0].(*ast.KeyValueExpr)
}
if !isKeyValue {
for i, element := range e.Elts {
elements[i] = c.translateImplicitConversion(element, t.Field(i).Type()).String()
}
}
if isKeyValue {
for i := range elements {
elements[i] = c.zeroValue(t.Field(i).Type())
}
for _, element := range e.Elts {
//.........这里部分代码省略.........
作者:umisam
项目:gopherj
func (c *PkgContext) translateMethod(typeName string, isStruct bool, fun *ast.FuncDecl) {
c.newScope(func() {
sig := c.info.Objects[fun.Name].(*types.Func).Type().(*types.Signature)
recvType := sig.Recv().Type()
ptr, isPointer := recvType.(*types.Pointer)
params := c.translateParams(fun.Type)
joinedParams := strings.Join(params, ", ")
printPrimaryFunction := func(lhs string) {
c.Printf("%s = function(%s) {", lhs, joinedParams)
c.Indent(func() {
if jsCode, ok := c.pkg.Scope().Lookup("js_" + typeName + "_" + fun.Name.Name).(*types.Const); ok {
c.Write([]byte(exact.StringVal(jsCode.Val())))
c.Write([]byte{'\n'})
return
}
if fun.Body == nil {
c.Printf(`throw new Go$Panic("Native function not implemented: %s.%s");`, typeName, fun.Name.Name)
return
}
body := fun.Body.List
if fun.Recv.List[0].Names != nil {
recv := fun.Recv.List[0].Names[0]
c.info.Types[recv] = recvType
this := c.newIdent("this", recvType)
if isWrapped(recvType) {
this = c.newIdent("this.Go$val", recvType)
}
body = append([]ast.Stmt{
&ast.AssignStmt{
Lhs: []ast.Expr{recv},
Tok: token.DEFINE,
Rhs: []ast.Expr{this},
},
}, body...)
}
c.translateFunctionBody(body, sig)
})
c.Printf("};")
}
switch {
case isStruct:
printPrimaryFunction(typeName + ".prototype." + fun.Name.Name)
c.Printf("%s.Go$NonPointer.prototype.%s = function(%s) { return this.Go$val.%s(%s); };", typeName, fun.Name.Name, joinedParams, fun.Name.Name, joinedParams)
case !isStruct && !isPointer:
value := "this.Go$get()"
if isWrapped(recvType) {
value = fmt.Sprintf("new %s(%s)", typeName, value)
}
printPrimaryFunction(typeName + ".prototype." + fun.Name.Name)
c.Printf("%s.Go$Pointer.prototype.%s = function(%s) { return %s.%s(%s); };", typeName, fun.Name.Name, joinedParams, value, fun.Name.Name, joinedParams)
case !isStruct && isPointer:
if _, isArray := ptr.Elem().Underlying().(*types.Array); isArray {
printPrimaryFunction(typeName + ".prototype." + fun.Name.Name)
break
}
value := "this"
if isWrapped(ptr.Elem()) {
value = "this.Go$val"
}
c.Printf("%s.prototype.%s = function(%s) { var obj = %s; return (new %s.Go$Pointer(function() { return obj; }, null)).%s(%s); };", typeName, fun.Name.Name, joinedParams, value, typeName, fun.Name.Name, joinedParams)
printPrimaryFunction(typeName + ".Go$Pointer.prototype." + fun.Name.Name)
}
})
}
作者:postfi
项目:GoProxyHun
//.........这里部分代码省略.........
// fallthrough
}
// check general case by creating custom signature
sig := makeSig(S, S, NewSlice(T)) // []T required for variadic signature
sig.variadic = true
check.arguments(x, call, sig, func(x *operand, i int) {
// only evaluate arguments that have not been evaluated before
if i < len(alist) {
*x = alist[i]
return
}
arg(x, i)
}, nargs)
// ok to continue even if check.arguments reported errors
x.mode = value
x.typ = S
if check.Types != nil {
check.recordBuiltinType(call.Fun, sig)
}
case _Cap, _Len:
// cap(x)
// len(x)
mode := invalid
var typ Type
var val exact.Value
switch typ = implicitArrayDeref(x.typ.Underlying()); t := typ.(type) {
case *Basic:
if isString(t) && id == _Len {
if x.mode == constant {
mode = constant
val = exact.MakeInt64(int64(len(exact.StringVal(x.val))))
} else {
mode = value
}
}
case *Array:
mode = value
// spec: "The expressions len(s) and cap(s) are constants
// if the type of s is an array or pointer to an array and
// the expression s does not contain channel receives or
// function calls; in this case s is not evaluated."
if !check.hasCallOrRecv {
mode = constant
val = exact.MakeInt64(t.len)
}
case *Slice, *Chan:
mode = value
case *Map:
if id == _Len {
mode = value
}
}
if mode == invalid {
check.invalidArg(x.pos(), "%s for %s", x, bin.name)
return
}
x.mode = mode
x.typ = Typ[Int]
作者:umisam
项目:gopherj
//.........这里部分代码省略.........
Lhs: lhs,
Tok: token.DEFINE,
Rhs: spec.Values,
})
unorderedSingleVarSpecs[i] = nil
}
}
c.Indent(func() {
for _, importedPkg := range typesPkg.Imports() {
varName := c.newVariable(importedPkg.Name())
c.Printf(`var %s = Go$packages["%s"];`, varName, importedPkg.Path())
c.pkgVars[importedPkg.Path()] = varName
}
// types and their functions
for _, spec := range typeSpecs {
obj := c.info.Objects[spec.Name]
typeName := c.objectName(obj)
c.Printf("var %s;", typeName)
c.translateTypeSpec(spec)
for _, fun := range functionsByType[obj.Type()] {
_, isStruct := obj.Type().Underlying().(*types.Struct)
c.translateMethod(typeName, isStruct, fun)
}
c.Printf("Go$pkg.%s = %s;", typeName, typeName)
}
// package functions
for _, fun := range functionsByType[nil] {
if isBlank(fun.Name) {
continue
}
c.newScope(func() {
name := c.objectName(c.info.Objects[fun.Name])
params := c.translateParams(fun.Type)
c.Printf("var %s = function(%s) {", name, strings.Join(params, ", "))
c.Indent(func() {
jsCode, _ := typesPkg.Scope().Lookup("js_" + name).(*types.Const)
if jsCode != nil {
c.Write([]byte(exact.StringVal(jsCode.Val())))
c.Write([]byte{'\n'})
return
}
if fun.Body == nil {
c.Printf(`throw new Go$Panic("Native function not implemented: %s");`, name)
return
}
c.translateFunctionBody(fun.Body.List, c.info.Objects[fun.Name].Type().(*types.Signature))
})
c.Printf("};")
})
}
// constants
for _, spec := range constSpecs {
for _, name := range spec.Names {
if isBlank(name) || strings.HasPrefix(name.Name, "js_") {
continue
}
o := c.info.Objects[name].(*types.Const)
c.info.Types[name] = o.Type()
c.info.Values[name] = o.Val()
c.Printf("%s = %s;", c.objectName(o), c.translateExpr(name))
}
}
// variables
for _, spec := range varSpecs {
for _, name := range spec.Names {
o := c.info.Objects[name].(*types.Var)
c.Printf("%s = %s;", c.objectName(o), c.zeroValue(o.Type()))
}
}
// native implementations
if native, hasNative := natives[importPath]; hasNative {
c.Write([]byte(strings.TrimSpace(native)))
c.Write([]byte{'\n'})
}
// exports for package functions
for _, fun := range functionsByType[nil] {
name := fun.Name.Name
if fun.Name.IsExported() || name == "main" {
c.Printf("Go$pkg.%s = %s;", name, name)
}
}
// init function
c.Printf("Go$pkg.init = function() {")
c.Indent(func() {
c.translateFunctionBody(append(intVarStmts, initStmts...), nil)
})
c.Printf("};")
})
return c.output, nil
}