func buildMember(b *builder, m *tast.MemberExpr) *ref { obj := b.buildExpr(m.Expr) if !obj.IsSingle() { panic("not single") } t := obj.Type() if pkg, ok := t.(*types.Pkg); ok { return buildPkgSym(b, m, pkg) } pt := types.PointerOf(t) var tstruct *types.Struct if pt != nil { tstruct = pt.(*types.Struct) } else { tstruct = t.(*types.Struct) } addr := b.newPtr() if pt != nil { b.b.Assign(addr, obj.IR()) if obj != b.this { nilPointerPanic(b, addr) } } else { b.b.Arith(addr, nil, "&", obj.IR()) } sym := m.Symbol if sym.Type == tast.SymField { return buildField(b, addr, sym.Obj.(*types.Field)) } else if sym.Type == tast.SymFunc { recv := newRef(types.NewPointer(tstruct), addr) method := sym.Obj.(*objFunc) ft := method.Type().(*types.Func) return newRecvRef(ft, recv, method.IR()) } panic("bug") }
func buildCallMake(b *builder, expr *ast.CallExpr, f tast.Expr) tast.Expr { args := buildExprList(b, expr.Args) if args == nil { return nil } n := args.R().Len() if n == 0 { b.Errorf(expr.Lparen.Pos, "make() takes at least one argument") return nil } argsList, ok := tast.MakeExprList(args) if !ok { b.Errorf(expr.Lparen.Pos, "make() only takes a literal list") return nil } arg0 := argsList.Exprs[0] t, ok := arg0.R().T.(*types.Type) if !ok { b.Errorf(expr.Lparen.Pos, "make() takes a type as the 1st argument") return nil } switch st := t.T.(type) { case *types.Slice: if n != 3 { b.Errorf(expr.Lparen.Pos, "make() slice takes 3 arguments") return nil } size := argsList.Exprs[1] pos := ast.ExprPos(expr.Args.Exprs[1]) size = checkArrayIndex(b, size, pos) if size == nil { return nil } start := argsList.Exprs[2] startType := start.R().T startPos := ast.ExprPos(expr.Args.Exprs[2]) if v, ok := types.NumConst(startType); ok { start = constCastUint(b, startPos, v, start) if start == nil { return nil } } else if !types.IsBasic(startType, types.Uint) { pt := types.PointerOf(startType) if pt == nil || !types.SameType(pt, st.T) { b.Errorf(startPos, "make() takes an uint or a typed pointer as the 3rd arg", ) return nil } } callArgs := tast.NewExprList() callArgs.Append(arg0) callArgs.Append(size) callArgs.Append(start) r := tast.NewRef(st) return &tast.CallExpr{f, callArgs, r} } b.Errorf(expr.Lparen.Pos, "cannot make() type %s", t.T) return nil }
func buildMember(b *builder, m *ast.MemberExpr) tast.Expr { obj := b.buildExpr(m.Expr) if obj == nil { return nil } ref := obj.R() if !ref.IsSingle() { b.Errorf(m.Dot.Pos, "%s does not have any member", ref) return nil } t := ref.T if pkg, ok := t.(*types.Pkg); ok { r, sym := buildPkgSym(b, m, pkg) if r == nil { return nil } // TODO: this can be further optimized return &tast.MemberExpr{obj, m.Sub, r, sym} } pt := types.PointerOf(t) var tstruct *types.Struct var ok bool if pt != nil { if tstruct, ok = pt.(*types.Struct); !ok { b.Errorf(m.Dot.Pos, "*%s is not a pointer of struct", t) return nil } } else { if tstruct, ok = t.(*types.Struct); !ok { b.Errorf(m.Dot.Pos, "%s is not a struct", t) return nil } } symTable := tstruct.Syms name := m.Sub.Lit sym := symTable.Query(name) if sym == nil { b.Errorf(m.Sub.Pos, "struct %s has no member named %s", tstruct, name, ) return nil } else if !sym8.IsPublic(name) && sym.Pkg() != b.path { b.Errorf(m.Sub.Pos, "symbol %s is not public", name) return nil } b.refSym(sym, m.Sub.Pos) if sym.Type == tast.SymField { t := sym.ObjType.(types.T) r := tast.NewAddressableRef(t) return &tast.MemberExpr{obj, m.Sub, r, sym} } else if sym.Type == tast.SymFunc { ft := sym.ObjType.(*types.Func) r := tast.NewRef(ft.MethodFunc) r.Recv = ref return &tast.MemberExpr{obj, m.Sub, r, sym} } b.Errorf(m.Sub.Pos, "invalid sym type: %s", tast.SymStr(sym.Type)) return nil }