|
4 | 4 | //
|
5 | 5 | // Copyright (c) 2022, Olof Kraigher [email protected]
|
6 | 6 |
|
| 7 | +use fnv::FnvHashSet; |
| 8 | + |
7 | 9 | use super::analyze::*;
|
8 | 10 | use super::expression::ExpressionType;
|
9 | 11 | use super::named_entity::*;
|
@@ -855,9 +857,18 @@ impl<'a> AnalyzeContext<'a> {
|
855 | 857 |
|
856 | 858 | if let Some(disambiguated) = disambiguated {
|
857 | 859 | match disambiguated {
|
858 |
| - Disambiguated::Ambiguous(_) => { |
| 860 | + Disambiguated::Ambiguous(ents) => { |
859 | 861 | // @TODO ambiguous error
|
860 |
| - return Err(EvalError::Unknown); |
| 862 | + if let Some(types) = ambiguous_functions_to_types(ents) { |
| 863 | + resolved = |
| 864 | + ResolvedName::Expression(DisambiguatedType::Ambiguous(types)); |
| 865 | + } else { |
| 866 | + diagnostics.error( |
| 867 | + &prefix.pos, |
| 868 | + "Procedure calls are not valid in names and expressions", |
| 869 | + ); |
| 870 | + return Err(EvalError::Unknown); |
| 871 | + } |
861 | 872 | }
|
862 | 873 | Disambiguated::Unambiguous(ent) => {
|
863 | 874 | if let Some(typ) = ent.return_type() {
|
@@ -996,9 +1007,18 @@ impl<'a> AnalyzeContext<'a> {
|
996 | 1007 | overloaded.entities().collect(),
|
997 | 1008 | diagnostics,
|
998 | 1009 | ))? {
|
999 |
| - Some(Disambiguated::Ambiguous(_)) => { |
| 1010 | + Some(Disambiguated::Ambiguous(ents)) => { |
1000 | 1011 | // @TODO ambiguous error
|
1001 |
| - return Err(EvalError::Unknown); |
| 1012 | + if let Some(types) = ambiguous_functions_to_types(ents) { |
| 1013 | + resolved = |
| 1014 | + ResolvedName::Expression(DisambiguatedType::Ambiguous(types)); |
| 1015 | + } else { |
| 1016 | + diagnostics.error( |
| 1017 | + &prefix.pos, |
| 1018 | + "Procedure calls are not valid in names and expressions", |
| 1019 | + ); |
| 1020 | + return Err(EvalError::Unknown); |
| 1021 | + } |
1002 | 1022 | }
|
1003 | 1023 | Some(Disambiguated::Unambiguous(ent)) => {
|
1004 | 1024 | prefix.set_unique_reference(&ent);
|
@@ -1652,6 +1672,20 @@ fn check_single_argument<'a>(
|
1652 | 1672 | }
|
1653 | 1673 | }
|
1654 | 1674 |
|
| 1675 | +fn ambiguous_functions_to_types(overloaded: Vec<OverloadedEnt>) -> Option<FnvHashSet<BaseType>> { |
| 1676 | + let types: FnvHashSet<_> = overloaded |
| 1677 | + .iter() |
| 1678 | + .filter_map(|ent| ent.return_type()) |
| 1679 | + .map(|typ| typ.base()) |
| 1680 | + .collect(); |
| 1681 | + |
| 1682 | + if !types.is_empty() { |
| 1683 | + Some(types) |
| 1684 | + } else { |
| 1685 | + None |
| 1686 | + } |
| 1687 | +} |
| 1688 | + |
1655 | 1689 | #[cfg(test)]
|
1656 | 1690 | mod test {
|
1657 | 1691 | use super::*;
|
@@ -2714,4 +2748,24 @@ type enum_t is (alpha, beta);
|
2714 | 2748 | )))
|
2715 | 2749 | );
|
2716 | 2750 | }
|
| 2751 | + |
| 2752 | + #[test] |
| 2753 | + fn ambiguous_function() { |
| 2754 | + let test = TestSetup::new(); |
| 2755 | + test.declarative_part( |
| 2756 | + " |
| 2757 | + function myfun(arg: integer) return integer; |
| 2758 | + function myfun(arg: integer) return real; |
| 2759 | + ", |
| 2760 | + ); |
| 2761 | + let code = test.snippet("myfun(0)"); |
| 2762 | + assert_eq!( |
| 2763 | + test.name_resolve(&code, None, &mut NoDiagnostics), |
| 2764 | + Ok(ResolvedName::Expression(DisambiguatedType::Ambiguous( |
| 2765 | + vec![test.ctx().real().base(), test.ctx().integer().base()] |
| 2766 | + .into_iter() |
| 2767 | + .collect() |
| 2768 | + ))) |
| 2769 | + ); |
| 2770 | + } |
2717 | 2771 | }
|
0 commit comments