001package gudusoft.gsqlparser.ir.bound;
002
003import gudusoft.gsqlparser.ir.common.Confidence;
004import gudusoft.gsqlparser.ir.common.Evidence;
005import gudusoft.gsqlparser.ir.common.IRNode;
006import gudusoft.gsqlparser.ir.common.IRNodeKind;
007import gudusoft.gsqlparser.ir.common.IRVisitor;
008
009import java.util.Collections;
010import java.util.List;
011
012/**
013 * Bound reference to a procedure or function call.
014 */
015public class BoundRoutineRef extends IRNode {
016
017    /** Original call text. */
018    private final String originalText;
019
020    /** Name parts (e.g., [package, procedure]). */
021    private final List<String> nameParts;
022
023    /** Binding status. */
024    private final EBindingStatus bindingStatus;
025
026    /** Resolved routine symbol. */
027    private final BoundRoutineSymbol resolvedRoutine;
028
029    /** Overload candidates (when multiple signatures match). */
030    private final List<BoundRoutineSymbol> overloadCandidates;
031
032    /** Actual arguments with formal parameter binding. */
033    private final List<BoundArgument> arguments;
034
035    /** Evidence and confidence. */
036    private final Evidence evidence;
037    private final Confidence confidence;
038
039    public BoundRoutineRef(String originalText, List<String> nameParts,
040                           EBindingStatus bindingStatus,
041                           BoundRoutineSymbol resolvedRoutine,
042                           List<BoundRoutineSymbol> overloadCandidates,
043                           List<BoundArgument> arguments,
044                           Evidence evidence, Confidence confidence) {
045        this.originalText = originalText;
046        this.nameParts = nameParts != null
047                ? Collections.unmodifiableList(nameParts)
048                : Collections.<String>emptyList();
049        this.bindingStatus = bindingStatus;
050        this.resolvedRoutine = resolvedRoutine;
051        this.overloadCandidates = overloadCandidates != null
052                ? Collections.unmodifiableList(overloadCandidates)
053                : Collections.<BoundRoutineSymbol>emptyList();
054        this.arguments = arguments != null
055                ? Collections.unmodifiableList(arguments)
056                : Collections.<BoundArgument>emptyList();
057        this.evidence = evidence;
058        this.confidence = confidence;
059    }
060
061    public String getOriginalText() { return originalText; }
062    public List<String> getNameParts() { return nameParts; }
063    public EBindingStatus getBindingStatus() { return bindingStatus; }
064    public BoundRoutineSymbol getResolvedRoutine() { return resolvedRoutine; }
065    public List<BoundRoutineSymbol> getOverloadCandidates() { return overloadCandidates; }
066    public List<BoundArgument> getArguments() { return arguments; }
067    public Evidence getEvidence() { return evidence; }
068    public Confidence getConfidence() { return confidence; }
069
070    /**
071     * Creates a copy of this ref with a resolved routine, updating binding status to EXACT.
072     * Preserves source anchor and properties from the original.
073     */
074    public BoundRoutineRef withResolvedRoutine(BoundRoutineSymbol resolved) {
075        return withResolvedRoutine(resolved, EBindingStatus.EXACT, null, null);
076    }
077
078    /**
079     * Creates a copy of this ref with the given binding status, resolved routine,
080     * optional overload candidates, and optional evidence.
081     */
082    public BoundRoutineRef withResolvedRoutine(BoundRoutineSymbol resolved,
083                                                EBindingStatus status,
084                                                List<BoundRoutineSymbol> candidates,
085                                                Evidence newEvidence) {
086        BoundRoutineRef copy = new BoundRoutineRef(
087                originalText, nameParts,
088                status, resolved,
089                candidates != null ? candidates : overloadCandidates,
090                arguments,
091                newEvidence != null ? newEvidence : evidence,
092                confidence);
093        copy.setSourceAnchor(this.getSourceAnchor());
094        if (this.getProperties() != null) {
095            for (java.util.Map.Entry<String, Object> e : this.getProperties().entrySet()) {
096                copy.setProperty(e.getKey(), e.getValue());
097            }
098        }
099        return copy;
100    }
101
102    @Override
103    public IRNodeKind getKind() {
104        return IRNodeKind.BOUND_ROUTINE_REF;
105    }
106
107    @Override
108    public <R, C> R accept(IRVisitor<R, C> visitor, C context) {
109        return visitor.visitBoundRoutineRef(this, context);
110    }
111
112    @Override
113    public String toString() {
114        return "BoundRoutineRef{" + originalText + ", " + bindingStatus + "}";
115    }
116}