func findPackageSym( b *builder, sub *lex8.Token, pkg *types.Pkg, ) *sym8.Symbol { sym := pkg.Syms.Query(sub.Lit) if sym == nil { b.Errorf(sub.Pos, "%s has no symbol named %s", pkg, sub.Lit, ) return nil } name := sym.Name() if !sym8.IsPublic(name) && sym.Pkg() != b.path { b.Errorf(sub.Pos, "symbol %s is not public", name) return nil } return sym }
func linkSymbol(b *builder, s *funcStmt, f *link8.Func) { t := s.symTok if b.curPkg == nil { b.Errorf(t.Pos, "no context for resolving %q", t.Lit) return // this may happen for bare function } typ, pkg, name := resolveSymbol(b, s) if typ == SymNone { return } if s.fill == fillLink && typ != SymFunc { b.Errorf(t.Pos, "%s %q is not a function", SymStr(typ), t.Lit) return } else if pkg != b.curPkg.Path() && !sym8.IsPublic(s.sym) { // for imported package, check if it is public b.Errorf(t.Pos, "%q is not public", t.Lit) return } // save the link f.AddLink(s.fill, &link8.PkgSym{pkg, name}) }
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 }
func buildType(b *builder, expr ast.Expr) types.T { if expr == nil { panic("bug") } switch expr := expr.(type) { case *ast.Operand: ret := buildOperand(b, expr) if ret == nil { return nil } ref := ret.R() t, ok := ref.T.(*types.Type) if !ok { b.Errorf(ast.ExprPos(expr), "expect a type, got %s", ref.T) return nil } return t.T case *ast.StarExpr: t := buildType(b, expr.Expr) if t == nil { return nil } return &types.Pointer{t} case *ast.ArrayTypeExpr: return buildArrayType(b, expr) case *ast.ParenExpr: return buildType(b, expr.Expr) case *ast.FuncTypeExpr: return buildFuncType(b, nil, expr.FuncSig) case *ast.MemberExpr: op, ok := expr.Expr.(*ast.Operand) if !ok { b.Errorf(ast.ExprPos(expr.Expr), "expect a package") return nil } pkg := buildPkgRef(b, op.Token) if pkg == nil { return nil } name := expr.Sub.Lit s := pkg.Syms.Query(name) if s == nil { b.Errorf(expr.Sub.Pos, "symbol %s not found", name) return nil } if !sym8.IsPublic(name) && s.Pkg() != b.path { b.Errorf(expr.Sub.Pos, "symbol %s is not public", name) return nil } if s.Type != tast.SymStruct { b.Errorf(expr.Sub.Pos, "symbol %s is a %s, not a struct", name, tast.SymStr(s.Type), ) return nil } return s.ObjType.(*types.Type).T } b.Errorf(ast.ExprPos(expr), "expect a type") return nil }