Skip to content

Commit 107b177

Browse files
committed
more stuff working
1 parent cb8219f commit 107b177

File tree

4 files changed

+129
-23
lines changed

4 files changed

+129
-23
lines changed

naga/src/front/wgsl/error.rs

+28
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,13 @@ pub(crate) enum Error<'a> {
260260
expected: Range<u32>,
261261
found: u32,
262262
},
263+
WrongArgumentCountForOverloads {
264+
function: String,
265+
call_span: Span,
266+
arg_span: Span,
267+
max_arguments: u32,
268+
overloads: Vec<String>,
269+
},
263270
WrongArgumentType {
264271
function: String,
265272
call_span: Span,
@@ -821,6 +828,27 @@ impl<'a> Error<'a> {
821828
labels: vec![(span, "wrong number of arguments".into())],
822829
notes: vec![],
823830
},
831+
Error::WrongArgumentCountForOverloads {
832+
ref function,
833+
call_span,
834+
arg_span,
835+
max_arguments,
836+
ref overloads,
837+
} => {
838+
let message = format!(
839+
"For the preceding argument types, `{function}` accepts only {max_arguments} arguments"
840+
);
841+
let labels = vec![
842+
(call_span, "This function call has too many arguments".into()),
843+
(arg_span, "This is the first excess argument".into())
844+
];
845+
let mut notes = vec![
846+
format!("These are the only overloads of `{function}` that could accept the preceding arguments:"),
847+
];
848+
notes.extend(overloads.iter().map(|o| format!("overload: {o}")));
849+
850+
ParseError { message, labels, notes }
851+
}
824852
Error::WrongArgumentType {
825853
ref function,
826854
call_span,

naga/src/front/wgsl/lower/mod.rs

+40-8
Original file line numberDiff line numberDiff line change
@@ -2298,20 +2298,52 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
22982298
use crate::proc::Rule as _;
22992299

23002300
let mut overloads = fun.overloads();
2301+
log::debug!("JIMB: {fun:?}");
2302+
let min_arguments = overloads.min_subexpressions();
2303+
let max_arguments = overloads.max_subexpressions();
2304+
if arguments.len() < min_arguments || max_arguments < arguments.len() {
2305+
return Err(Error::WrongArgumentCount {
2306+
span,
2307+
expected: min_arguments as u32 .. max_arguments as u32,
2308+
found: arguments.len() as u32
2309+
});
2310+
}
2311+
23012312
let mut unconverted_arguments = Vec::with_capacity(arguments.len());
23022313
for (i, &arg) in arguments.iter().enumerate() {
23032314
let lowered = self.expression_for_abstract(arg, ctx)?;
23042315
let ty = resolve_inner!(ctx, lowered);
23052316
let remaining_overloads = overloads.arg(i, ty, &ctx.module.types);
23062317
if remaining_overloads.is_empty() {
2307-
return Err(Error::WrongArgumentType {
2308-
function: fun.to_wgsl().to_string(),
2309-
call_span: span,
2310-
arg_span: ctx.ast_expressions.get_span(arg),
2311-
arg_index: i as u32,
2312-
found: crate::common::wgsl::Wgslish(ty).to_string(),
2313-
allowed: overloads.allowed_args(i),
2314-
});
2318+
// If there were other types permitted for the i'th arg, then
2319+
// this is a no-such-overload error.
2320+
//
2321+
// Otherwise, since we checked the argument count against the
2322+
// min and max earlier, it must be the case that the prior
2323+
// arguments narrowed the overloads to a subset none of which
2324+
// accept this many arguments.
2325+
let arg_span = ctx.ast_expressions.get_span(arg);
2326+
let allowed = overloads.allowed_args(i);
2327+
let function = fun.to_wgsl().to_string();
2328+
if allowed.is_empty() {
2329+
let overload_list = overloads.overload_list(&function);
2330+
return Err(Error::WrongArgumentCountForOverloads {
2331+
function,
2332+
call_span: span,
2333+
arg_span,
2334+
max_arguments: overloads.max_subexpressions() as u32,
2335+
overloads: overload_list,
2336+
});
2337+
} else {
2338+
return Err(Error::WrongArgumentType {
2339+
function,
2340+
call_span: span,
2341+
arg_span,
2342+
arg_index: i as u32,
2343+
found: crate::common::wgsl::Wgslish(ty).to_string(),
2344+
allowed,
2345+
});
2346+
}
23152347
}
23162348
overloads = remaining_overloads;
23172349
unconverted_arguments.push(lowered);

naga/src/proc/builtins/list.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,22 @@ impl super::OverloadSet for List {
8484
self.members == 0
8585
}
8686

87-
fn min_subexpressions(&self) -> Option<usize> {
88-
self.members().fold(None, |n, (_, rule)| {
89-
std::cmp::min(n, Some(rule.subexpressions.len()))
90-
})
87+
fn min_subexpressions(&self) -> usize {
88+
self.members().fold(None, |best, (_, rule)| {
89+
// This is different from `max_subexpressions` because
90+
// `<Option as PartialOrd>` doesn't work the way we'd like.
91+
let len = rule.subexpressions.len();
92+
Some(match best {
93+
Some(best) => std::cmp::max(best, len),
94+
None => len
95+
})
96+
}).unwrap()
9197
}
9298

93-
fn max_subexpressions(&self) -> Option<usize> {
99+
fn max_subexpressions(&self) -> usize {
94100
self.members().fold(None, |n, (_, rule)| {
95101
std::cmp::max(n, Some(rule.subexpressions.len()))
96-
})
102+
}).unwrap()
97103
}
98104

99105
fn arg(&self, i: usize, ty: &crate::TypeInner, types: &crate::UniqueArena<crate::Type>) -> Self {
@@ -122,7 +128,8 @@ impl super::OverloadSet for List {
122128
}
123129

124130
fn most_preferred(&self) -> Option<Rule> {
125-
self.members().next().map(|(_, rule)| rule.clone())
131+
let (_, rule) = self.members().next().unwrap();
132+
Some(rule.clone())
126133
}
127134

128135
fn overload_list(&self, name: &str) -> Vec<String> {

naga/src/proc/builtins/mod.rs

+47-8
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,20 @@ pub trait OverloadSet: Clone + std::fmt::Debug {
2525
fn is_empty(&self) -> bool;
2626

2727
/// Return the smallest number of subexpressions in any type rule
28-
/// in the set. Return `None` if `self` is empty.
29-
fn min_subexpressions(&self) -> Option<usize>;
28+
/// in the set.
29+
///
30+
/// # Panics
31+
///
32+
/// Panics if `self` is empty.
33+
fn min_subexpressions(&self) -> usize;
3034

3135
/// Return the largest number of subexpressions in any type rule
32-
/// in the set. Return `None` if `self` is empty.
33-
fn max_subexpressions(&self) -> Option<usize>;
36+
/// in the set.
37+
///
38+
/// # Panics
39+
///
40+
/// Panics if `self` is empty.
41+
fn max_subexpressions(&self) -> usize;
3442

3543
/// Limit `self` to the overloads that can accept a given
3644
/// subexpression.
@@ -78,12 +86,15 @@ pub trait OverloadSet: Clone + std::fmt::Debug {
7886
/// [concretize]: https://gpuweb.github.io/gpuweb/wgsl/#concretization
7987
fn concrete_only(self, types: &crate::UniqueArena<crate::Type>) -> Self;
8088

81-
/// Return the most preferred candidate, or `None` if `self` is empty.
89+
/// Return the most preferred candidate.
8290
///
8391
/// Rank the candidates in `self` as described in WGSL's [overload
8492
/// resolution algorithm][ora], and return a singleton set containing the
8593
/// most preferred candidate.
8694
///
95+
/// If there is no most preferred candidate, return `None`,
96+
/// indicating that the expression is ambiguous.
97+
///
8798
/// As it's described in the spec, choosing the most preferred candidate
8899
/// depends on the ranks of the conversions being applied to each argument,
89100
/// so it's impossible to determine the most preferred candidate from the
@@ -93,6 +104,10 @@ pub trait OverloadSet: Clone + std::fmt::Debug {
93104
/// leaf scalar type for all its subexpressions, then the most abstract
94105
/// overload must be the most preferred candidate.
95106
///
107+
/// # Panics
108+
///
109+
/// Panics if `self` is empty.
110+
///
96111
/// [ora]: https://gpuweb.github.io/gpuweb/wgsl/#overload-resolution-section
97112
fn most_preferred(&self) -> Option<Self::Rule>;
98113

@@ -139,13 +154,13 @@ impl OverloadSet for AnyOverloadSet {
139154
}
140155
}
141156

142-
fn min_subexpressions(&self) -> Option<usize> {
157+
fn min_subexpressions(&self) -> usize {
143158
match *self {
144159
AnyOverloadSet::List(ref list) => list.min_subexpressions(),
145160
}
146161
}
147162

148-
fn max_subexpressions(&self) -> Option<usize> {
163+
fn max_subexpressions(&self) -> usize {
149164
match *self {
150165
AnyOverloadSet::List(ref list) => list.max_subexpressions(),
151166
}
@@ -165,7 +180,7 @@ impl OverloadSet for AnyOverloadSet {
165180

166181
fn most_preferred(&self) -> Option<AnyRule> {
167182
match *self {
168-
AnyOverloadSet::List(ref list) => list.most_preferred().map(AnyRule::List),
183+
AnyOverloadSet::List(ref list) => list.most_preferred().map(AnyRule::List)
169184
}
170185
}
171186

@@ -216,6 +231,10 @@ impl crate::MathFunction {
216231
const VEC3F: Ti = Ti::Vector { size: Vs::Tri, scalar: Sc::F32 };
217232
const VEC4F: Ti = Ti::Vector { size: Vs::Quad, scalar: Sc::F32 };
218233

234+
const VEC2AF: Ti = Ti::Vector { size: Vs::Bi, scalar: Sc::ABSTRACT_FLOAT };
235+
const VEC3AF: Ti = Ti::Vector { size: Vs::Tri, scalar: Sc::ABSTRACT_FLOAT };
236+
const VEC4AF: Ti = Ti::Vector { size: Vs::Quad, scalar: Sc::ABSTRACT_FLOAT };
237+
219238
const VEC2I: Ti = Ti::Vector { size: Vs::Bi, scalar: Sc::I32 };
220239
const VEC3I: Ti = Ti::Vector { size: Vs::Tri, scalar: Sc::I32 };
221240
const VEC4I: Ti = Ti::Vector { size: Vs::Quad, scalar: Sc::I32 };
@@ -266,9 +285,29 @@ impl crate::MathFunction {
266285
},
267286
];
268287

288+
static POW: &[list::Rule] = &[
289+
list::Rule {
290+
subexpressions: &[Ti::Scalar(Sc::F32), Ti::Scalar(Sc::F32)],
291+
conclusion: Ti::Scalar(Sc::F32),
292+
},
293+
list::Rule {
294+
subexpressions: &[Ti::Scalar(Sc::ABSTRACT_FLOAT), Ti::Scalar(Sc::ABSTRACT_FLOAT)],
295+
conclusion: Ti::Scalar(Sc::ABSTRACT_FLOAT),
296+
},
297+
list::Rule {
298+
subexpressions: &[VEC2F, VEC2F],
299+
conclusion: VEC2F,
300+
},
301+
list::Rule {
302+
subexpressions: &[VEC2AF, VEC2AF],
303+
conclusion: VEC2AF,
304+
},
305+
];
306+
269307
match self {
270308
Mf::Sin => AnyOverloadSet::List(list::List::from_rules(COMPONENT_WISE_FLOAT)),
271309
Mf::Dot => AnyOverloadSet::List(list::List::from_rules(DOT_PRODUCT)),
310+
Mf::Pow => AnyOverloadSet::List(list::List::from_rules(POW)),
272311
_ => todo!(),
273312
}
274313
}

0 commit comments

Comments
 (0)