Merge combines an existing function declaration with another. If a function is extended, by say adding new overloads to an existing function, then it is merged with the prior definition of the function at which point its overloads must not collide with pre-existing overloads and its bindings (singl
(other *FunctionDecl)
| 144 | // prior definition of the function at which point its overloads must not collide with pre-existing overloads |
| 145 | // and its bindings (singleton, or per-overload) must not conflict with previous definitions either. |
| 146 | func (f *FunctionDecl) Merge(other *FunctionDecl) (*FunctionDecl, error) { |
| 147 | if f == other { |
| 148 | return f, nil |
| 149 | } |
| 150 | if f == nil || other == nil || f.Name() != other.Name() { |
| 151 | return nil, fmt.Errorf("cannot merge unrelated functions. %q and %q", f.Name(), other.Name()) |
| 152 | } |
| 153 | merged := &FunctionDecl{ |
| 154 | name: f.Name(), |
| 155 | overloads: make(map[string]*OverloadDecl, len(f.overloads)), |
| 156 | singleton: f.singleton, |
| 157 | overloadOrdinals: make([]string, len(f.overloadOrdinals)), |
| 158 | overloadDecls: make([]*OverloadDecl, len(f.overloadDecls)), |
| 159 | // if one function is expecting type-guards and the other is not, then they |
| 160 | // must not be disabled. |
| 161 | disableTypeGuards: f.disableTypeGuards && other.disableTypeGuards, |
| 162 | // default to the current functions declaration state. |
| 163 | state: f.state, |
| 164 | doc: f.doc, |
| 165 | } |
| 166 | // If the other state indicates that the declaration should be explicitly enabled or |
| 167 | // disabled, then update the merged state with the most recent value. |
| 168 | if other.state != declarationStateUnset { |
| 169 | merged.state = other.state |
| 170 | } |
| 171 | // Allow for non-empty overrides of documentation |
| 172 | if len(other.doc) != 0 && f.doc != other.doc { |
| 173 | merged.doc = other.doc |
| 174 | } |
| 175 | // baseline copy of the overloads and their ordinals |
| 176 | copy(merged.overloadOrdinals, f.overloadOrdinals) |
| 177 | copy(merged.overloadDecls, f.overloadDecls) |
| 178 | for oID, o := range f.overloads { |
| 179 | merged.overloads[oID] = o |
| 180 | } |
| 181 | // overloads and their ordinals are added from the left |
| 182 | for _, oID := range other.overloadOrdinals { |
| 183 | o := other.overloads[oID] |
| 184 | err := merged.AddOverload(o) |
| 185 | if err != nil { |
| 186 | return nil, fmt.Errorf("function declaration merge failed: %v", err) |
| 187 | } |
| 188 | } |
| 189 | if other.singleton != nil { |
| 190 | if merged.singleton != nil && merged.singleton != other.singleton { |
| 191 | return nil, fmt.Errorf("function already has a singleton binding: %s", f.Name()) |
| 192 | } |
| 193 | merged.singleton = other.singleton |
| 194 | } |
| 195 | return merged, nil |
| 196 | } |
| 197 | |
| 198 | // FunctionSubsetter subsets a function declaration or returns nil and false if the function |
| 199 | // subset was empty. |