コード例 #1
0
ファイル: reader.go プロジェクト: gordonklaus/flux
func (r *reader) obj(x ast.Expr) types.Object {
	switch x := x.(type) {
	case *ast.Ident:
		if obj := r.scope.LookupParent(x.Name); obj != nil {
			if v, ok := obj.(*types.Var); ok && v.Pkg == nil { // ignore local vars
				return nil
			}
			return obj
		}
		return unknownObject{pkg: r.pkg, name: x.Name}
	case *ast.SelectorExpr:
		// TODO: Type.Method and pkg.Type.Method
		n1 := name(x.X)
		n2 := x.Sel.Name
		switch obj := r.scope.LookupParent(n1).(type) {
		case *types.PkgName:
			if obj := obj.Pkg.Scope().Lookup(n2); obj != nil {
				return obj
			}
			return unknownObject{pkg: obj.Pkg, name: n2}
		case *types.Var:
			t := obj.Type
			fm, _, addr := types.LookupFieldOrMethod(t, r.pkg, n2)
			switch fm := fm.(type) {
			case *types.Func:
				sig := fm.Type.(*types.Signature)
				return types.NewFunc(0, r.pkg, n2, types.NewSignature(nil, newVar("", t), sig.Params, sig.Results, sig.IsVariadic))
			case *types.Var:
				return field{fm, t, addr}
			}
			return unknownObject{pkg: obj.Pkg, recv: t, name: n2}
		}
	}
	panic("unreachable")
}
コード例 #2
0
ファイル: reader.go プロジェクト: gordonklaus/flux
func (r *reader) value(b *block, x, y ast.Expr, set bool, s ast.Stmt) {
	if x2, ok := x.(*ast.UnaryExpr); ok {
		x = x2.X
	}
	var obj types.Object
	if _, ok := x.(*ast.StarExpr); !ok { // StarExpr indicates an assignment (*x = y), for which obj must be nil
		obj = r.obj(x)
		if u, ok := obj.(unknownObject); ok {
			if _, ok := s.(*ast.DeclStmt); ok {
				obj = types.NewConst(0, u.pkg, u.name, nil, nil)
			} else {
				var t types.Type
				if set {
					t = r.scope.Lookup(name(y)).(*types.Var).Type
				}
				addr := false
				if s, ok := s.(*ast.AssignStmt); ok {
					if s.Tok == token.DEFINE {
						_, addr = s.Rhs[0].(*ast.UnaryExpr)
					}
				}
				if u.recv != nil {
					obj = field{types.NewVar(0, u.pkg, u.name, t), u.recv, addr} // it may be a method val, but a non-addressable field is close enough
				} else {
					if addr {
						obj = types.NewVar(0, u.pkg, u.name, t)
					} else {
						obj = types.NewFunc(0, u.pkg, u.name, types.NewSignature(nil, newVar("", u.recv), nil, nil, false))
					}
				}
			}
			//unknown(obj) == true
		}
	}
	n := newValueNode(obj, r.pkg, set)
	b.addNode(n)
	switch x := x.(type) {
	case *ast.SelectorExpr:
		r.in(x.X, n.x)
	case *ast.StarExpr:
		r.in(x.X, n.x)
	}
	if set {
		r.in(y, n.y)
	} else {
		r.out(y, n.y)
	}
	r.seq(n, s)
}
コード例 #3
0
ファイル: reader.go プロジェクト: gordonklaus/flux
func (r *reader) typ(x ast.Expr) types.Type {
	switch x := x.(type) {
	case *ast.Ident:
		if t, ok := r.scope.LookupParent(x.Name).(*types.TypeName); ok {
			return t.Type
		}
		return types.NewNamed(types.NewTypeName(0, r.pkg, x.Name, nil), types.Typ[types.Invalid], nil) //unknown(t.Obj) == true
	case *ast.SelectorExpr:
		pkg := r.scope.LookupParent(name(x.X)).(*types.PkgName).Pkg
		if t, ok := pkg.Scope().Lookup(x.Sel.Name).(*types.TypeName); ok {
			return t.Type
		}
		return types.NewNamed(types.NewTypeName(0, r.pkg, x.Sel.Name, nil), types.Typ[types.Invalid], nil) //unknown(t.Obj) == true
	case *ast.StarExpr:
		return types.NewPointer(r.typ(x.X))
	case *ast.ArrayType:
		elem := r.typ(x.Elt)
		if x.Len != nil {
			// TODO: x.Len
			return types.NewArray(elem, 0)
		}
		return types.NewSlice(elem)
	case *ast.Ellipsis:
		return types.NewSlice(r.typ(x.Elt))
	case *ast.MapType:
		return types.NewMap(r.typ(x.Key), r.typ(x.Value))
	case *ast.ChanType:
		dir := types.SendRecv
		if x.Dir&ast.SEND == 0 {
			dir = types.RecvOnly
		}
		if x.Dir&ast.RECV == 0 {
			dir = types.SendOnly
		}
		return types.NewChan(dir, r.typ(x.Value))
	case *ast.FuncType:
		var params, results []*types.Var
		for _, f := range x.Params.List {
			t := r.typ(f.Type)
			if f.Names == nil {
				params = append(params, types.NewParam(0, r.pkg, "", t))
			}
			for _, n := range f.Names {
				params = append(params, types.NewParam(0, r.pkg, n.Name, t))
			}
		}
		variadic := false
		if x.Results != nil {
			for _, f := range x.Results.List {
				t := r.typ(f.Type)
				if f.Names == nil {
					results = append(results, types.NewParam(0, r.pkg, "", t))
				}
				for _, n := range f.Names {
					results = append(results, types.NewParam(0, r.pkg, n.Name, t))
				}
				_, variadic = f.Type.(*ast.Ellipsis)
			}
		}
		return types.NewSignature(nil, nil, params, results, variadic)
	case *ast.StructType:
		var fields []*types.Var
		if x.Fields != nil {
			for _, f := range x.Fields.List {
				t := r.typ(f.Type)
				if f.Names == nil {
					fields = append(fields, types.NewField(0, r.pkg, "", t, true))
				}
				for _, n := range f.Names {
					fields = append(fields, types.NewField(0, r.pkg, n.Name, t, false))
				}
			}
		}
		return types.NewStruct(fields, nil)
	case *ast.InterfaceType:
		var methods []*types.Func
		var embeddeds []*types.Named
		if x.Methods != nil {
			for _, f := range x.Methods.List {
				switch t := r.typ(f.Type).(type) {
				case *types.Signature:
					methods = append(methods, types.NewFunc(0, r.pkg, f.Names[0].Name, t))
				case *types.Named:
					embeddeds = append(embeddeds, t)
				}
			}
		}
		return types.NewInterface(methods, embeddeds)
	}
	panic("unreachable")
}