Example #1
0
File: dscan.go Project: rwl/gorf
func (this DepthWalker) Visit(node ast.Node) ast.Visitor {
	if node == nil {
		return this + 1
	}

	buffer := ""
	for i := 0; i < int(this); i++ {
		buffer += " "
	}

	fmt.Printf("%sPos: %d %s\n", buffer, node.Pos(), AllSources.Position(node.Pos()))
	fmt.Printf("%sEnd: %d %s\n", buffer, node.End(), AllSources.Position(node.End()))
	fmt.Printf("%s%T\n", buffer, node)
	fmt.Printf("%s%v\n", buffer, node)
	if e, ok := node.(ast.Expr); ok {
		obj, typ := types.ExprType(e, LocalImporter)
		fmt.Printf("%s%v\n", buffer, obj)
		fmt.Printf("%s%v\n", buffer, typ)
	}
	fmt.Println()

	switch n := node.(type) {

	}

	return this + 1
}
Example #2
0
func exprType(n ast.Node, expectTuple bool, pkg string, importer Importer) (xobj *ast.Object, typ Type) {
	debugp("exprType tuple:%v pkg:%s %T %v [", expectTuple, pkg, n, pretty{n})
	defer func() {
		debugp("] -> %p, %v", xobj, typ)
	}()
	switch n := n.(type) {
	case nil:
	case *ast.Ident:
		obj := n.Obj
		if obj == nil || obj.Kind == ast.Bad {
			break
		}
		// A type object represents itself.
		if obj.Kind == ast.Typ {
			// Objects in the universal scope don't live
			// in any package.
			if parser.Universe.Lookup(obj.Name) == obj {
				pkg = ""
			}
			return obj, Type{n, obj.Kind, pkg}
		}
		expr, typ := splitDecl(obj, n)
		switch {
		case typ != nil:
			_, t := exprType(typ, false, pkg, importer)
			if t.Kind != ast.Bad {
				t.Kind = obj.Kind
			}
			return obj, t

		case expr != nil:
			_, t := exprType(expr, false, pkg, importer)
			if t.Kind == ast.Typ {
				debugp("expected value, got type %v", t)
				t = badType
			}
			return obj, t

		default:
			switch n.Obj {
			case falseIdent.Obj, trueIdent.Obj:
				return obj, Type{boolIdent, ast.Con, ""}
			case iotaIdent.Obj:
				return obj, Type{intIdent, ast.Con, ""}
			default:
				return obj, Type{}
			}
		}
	case *ast.LabeledStmt:
		return n.Label.Obj, Type{n, ast.Lbl, pkg}

	case *ast.ImportSpec:
		return nil, Type{n, ast.Pkg, ""}

	case *ast.ParenExpr:
		return exprType(n.X, expectTuple, pkg, importer)

	case *ast.CompositeLit:
		return nil, certify(n.Type, ast.Var, pkg, importer)

	case *ast.FuncLit:
		return nil, certify(n.Type, ast.Var, pkg, importer)

	case *ast.SelectorExpr:
		_, t := exprType(n.X, false, pkg, importer)
		// TODO: method expressions. when t.Kind == ast.Typ,
		// 	mutate a method declaration into a function with
		//	the receiver as first argument
		if t.Kind == ast.Bad {
			break
		}
		obj := t.Member(n.Sel.Name, importer)
		if obj == nil {
			return nil, badType
		}
		if t.Kind == ast.Pkg {
			eobj, et := exprType(&ast.Ident{Name: obj.Name, Obj: obj}, false, t.Pkg, importer)
			et.Pkg = litToString(t.Node.(*ast.ImportSpec).Path)
			return eobj, et
		}
		// a method turns into a function type;
		// the number of formal arguments depends
		// on the class of the receiver expression.
		if fd, ismethod := obj.Decl.(*ast.FuncDecl); ismethod {
			if t.Kind == ast.Typ {
				return obj, certify(methodExpr(fd), ast.Fun, t.Pkg, importer)
			}
			return obj, certify(fd.Type, ast.Fun, t.Pkg, importer)
		} else if obj.Kind == ast.Typ {
			return obj, certify(&ast.Ident{Name: obj.Name, Obj: obj}, ast.Typ, t.Pkg, importer)
		}
		_, typ := splitDecl(obj, nil)
		return obj, certify(typ, obj.Kind, t.Pkg, importer)

	case *ast.FuncDecl:
		return nil, certify(methodExpr(n), ast.Fun, pkg, importer)

	case *ast.IndexExpr:
		_, t0 := exprType(n.X, false, pkg, importer)
		t := t0.Underlying(true, importer)
		switch n := t.Node.(type) {
		case *ast.ArrayType:
			return nil, certify(n.Elt, ast.Var, t.Pkg, importer)
		case *ast.MapType:
			t := certify(n.Value, ast.Var, t.Pkg, importer)
			if expectTuple {
				return nil, Type{MultiValue{[]ast.Expr{t.Node.(ast.Expr), predecl("bool")}}, ast.Var, t.Pkg}
			}
			return nil, t
		}

	case *ast.SliceExpr:
		_, typ := exprType(n.X, false, pkg, importer)
		return nil, typ

	case *ast.CallExpr:
		switch exprName(n.Fun) {
		case makeIdent.Obj:
			if len(n.Args) > 0 {
				return nil, certify(n.Args[0], ast.Var, pkg, importer)
			}
		case newIdent.Obj:
			if len(n.Args) > 0 {
				t := certify(n.Args[0], ast.Var, pkg, importer)
				if t.Kind != ast.Bad {
					return nil, Type{&ast.StarExpr{n.Pos(), t.Node.(ast.Expr)}, ast.Var, t.Pkg}
				}
			}
		default:
			if _, fntype := exprType(n.Fun, false, pkg, importer); fntype.Kind != ast.Bad {
				// A type cast transforms a type expression
				// into a value expression.
				if fntype.Kind == ast.Typ {
					fntype.Kind = ast.Var
					// Preserve constness if underlying expr is constant.
					if len(n.Args) == 1 {
						_, argtype := exprType(n.Args[0], false, pkg, importer)
						if argtype.Kind == ast.Con {
							fntype.Kind = ast.Con
						}
					}
					return nil, fntype
				}
				// A function call operates on the underlying type,
				t := fntype.Underlying(true, importer)
				if fn, ok := t.Node.(*ast.FuncType); ok {
					return nil, certify(fields2type(fn.Results), ast.Var, t.Pkg, importer)
				}
			}
		}

	case *ast.StarExpr:
		if _, t := exprType(n.X, false, pkg, importer); t.Kind != ast.Bad {
			if t.Kind == ast.Typ {
				return nil, Type{&ast.StarExpr{n.Pos(), t.Node.(ast.Expr)}, ast.Typ, t.Pkg}
			}
			if n, ok := t.Node.(*ast.StarExpr); ok {
				return nil, certify(n.X, ast.Var, t.Pkg, importer)
			}
		}

	case *ast.TypeAssertExpr:
		t := certify(n.Type, ast.Var, pkg, importer)
		if expectTuple && t.Kind != ast.Bad {
			return nil, Type{MultiValue{[]ast.Expr{t.Node.(ast.Expr), predecl("bool")}}, ast.Var, t.Pkg}
		}
		return nil, t

	case *ast.UnaryExpr:
		if _, t := exprType(n.X, false, pkg, importer); t.Kind != ast.Bad {
			u := t.Underlying(true, importer)
			switch n.Op {
			case token.ARROW:
				if ct, ok := u.Node.(*ast.ChanType); ok {
					t := certify(ct.Value, ast.Var, u.Pkg, importer)
					if expectTuple && t.Kind != ast.Bad {
						return nil, Type{MultiValue{[]ast.Expr{t.Node.(ast.Expr), predecl("bool")}}, ast.Var, t.Pkg}
					}
					return nil, certify(ct.Value, ast.Var, u.Pkg, importer)
				}
			case token.RANGE:
				switch n := u.Node.(type) {
				case *ast.ArrayType:
					if expectTuple {
						return nil, Type{MultiValue{[]ast.Expr{predecl("int"), n.Elt}}, ast.Var, u.Pkg}
					}

					return nil, Type{predecl("bool"), ast.Var, ""}

				case *ast.MapType:
					if expectTuple {
						return nil, Type{MultiValue{[]ast.Expr{n.Key, n.Value}}, ast.Var, u.Pkg}
					}
					return nil, certify(n.Key, ast.Var, u.Pkg, importer)

				case *ast.ChanType:
					return nil, certify(n.Value, ast.Var, u.Pkg, importer)
				}

			case token.AND:
				if t.Kind == ast.Var {
					return nil, Type{&ast.StarExpr{n.Pos(), t.Node.(ast.Expr)}, ast.Var, t.Pkg}
				}

			case token.NOT:
				return nil, Type{predecl("bool"), t.Kind, ""}

			default:
				return nil, t
			}
		}

	case *ast.BinaryExpr:
		switch n.Op {
		case token.LSS, token.EQL, token.GTR, token.NEQ, token.LEQ, token.GEQ, token.ARROW, token.LOR, token.LAND:
			_, t := exprType(n.X, false, pkg, importer)
			if t.Kind == ast.Con {
				_, t = exprType(n.Y, false, pkg, importer)
			}
			return nil, Type{predecl("bool"), t.Kind, ""}

		case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.AND_NOT, token.XOR:
			_, tx := exprType(n.X, false, pkg, importer)
			_, ty := exprType(n.Y, false, pkg, importer)
			switch {
			case tx.Kind == ast.Bad || ty.Kind == ast.Bad:

			case !isNamedType(tx, importer):
				return nil, ty
			case !isNamedType(ty, importer):
				return nil, tx
			}
			// could check type equality
			return nil, tx

		case token.SHL, token.SHR:
			_, typ := exprType(n.X, false, pkg, importer)
			return nil, typ
		}

	case *ast.BasicLit:
		var id *ast.Ident
		switch n.Kind {
		case token.STRING:
			id = stringIdent

		case token.INT, token.CHAR:
			id = intIdent

		case token.FLOAT:
			id = floatIdent

		default:
			debugp("unknown constant type %v", n.Kind)
		}
		if id != nil {
			return nil, Type{id, ast.Con, ""}
		}

	case *ast.StructType, *ast.ChanType, *ast.MapType, *ast.ArrayType, *ast.InterfaceType, *ast.FuncType:
		return nil, Type{n.(ast.Node), ast.Typ, pkg}

	case MultiValue:
		return nil, Type{n, ast.Typ, pkg}

	case *exprIndex:
		_, t := exprType(n.x, true, pkg, importer)
		if t.Kind != ast.Bad {
			if ts, ok := t.Node.(MultiValue); ok {
				if n.i < len(ts.Types) {
					return nil, certify(ts.Types[n.i], ast.Var, t.Pkg, importer)
				}
			}
		}
	case *ast.Ellipsis:
		t := certify(n.Elt, ast.Var, pkg, importer)
		if t.Kind != ast.Bad {
			return nil, Type{&ast.ArrayType{n.Pos(), nil, t.Node.(ast.Expr)}, ast.Var, t.Pkg}
		}

	default:
		panic(fmt.Sprintf("unknown type %T", n))
	}
	return nil, badType
}