Exemple #1
0
// isCompatible reports whether t and u are of compatible types.
func isCompatible(t, u types.Type) bool {
	if types.Equal(t, u) {
		return true
	}
	if t, ok := t.(types.Numerical); ok {
		if u, ok := u.(types.Numerical); ok {
			// TODO: Check for other compatible types (e.g. pointers, array names,
			// strings).
			return t.IsNumerical() && u.IsNumerical()
		}
	}
	return false
}
Exemple #2
0
// isCompatibleArg reports whether the given call argument and function
// parameter types are compatible.
func isCompatibleArg(arg, param types.Type) bool {
	if isCompatible(arg, param) {
		return true
	}
	if arg, ok := arg.(*types.Array); ok {
		if param, ok := param.(*types.Array); ok {
			// TODO: Check for other compatible types (e.g. pointers, array names,
			// strings).
			if param.Len != 0 {
				return false
			}
			return types.Equal(arg.Elem, param.Elem)
		}
	}
	return false
}
Exemple #3
0
// 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
}