예제 #1
0
파일: scope.go 프로젝트: mewmew/uc
// Insert inserts the given declaration into the current scope.
func (s *Scope) Insert(decl ast.Decl) error {
	// Early return for first-time declarations.
	ident := decl.Name()
	if ident == nil {
		// Anonymous function parameter declaration.
		return nil
	}
	name := ident.String()
	prev, ok := s.Decls[name]
	if !ok {
		s.Decls[name] = decl
		return nil
	}
	prevIdent := prev.Name()

	if prevIdent.NamePos == ident.NamePos {
		// Identifier already added to scope.
		return nil
	}

	// Previously declared.
	if !types.Equal(prev.Type(), decl.Type()) {
		return errors.Newf(ident.Start(), "redefinition of %q with type %q instead of %q", name, decl.Type(), prev.Type())
	}

	// The last tentative definition becomes the definition, unless defined
	// explicitly (e.g. having an initializer or function body).
	if !s.IsDef(prev) {
		s.Decls[name] = decl
		return nil
	}

	// Definition already present in scope.
	if s.IsDef(decl) {
		// TODO: Consider adding support for multiple errors (and potentially
		// warnings and notifications).
		//
		// If support for notifications are added, add a note of the previous declaration.
		//    errors.Notef(prevIdent.Start(), "previous definition of %q", name)
		return errors.Newf(ident.Start(), "redefinition of %q", name)
	}

	// Declaration of previously declared identifier.
	return nil
}
예제 #2
0
파일: util.go 프로젝트: mewmew/uc
// isTentativeDef reports whether the given global variable or function
// declaration is a tentative definition.
func isTentativeDef(n ast.Decl) bool {
	ident := n.Name()
	def := ident.Decl.Name()
	return ident.Start() != def.Start()
}