[glsl-in] add support for .length() (#2017)

Adds parsing support for methods on the glsl frontend, while `.length` is the only method in the base extensions, there might be more in extensions.

Adds support for the `.length` method and tests for it.
This commit is contained in:
SpaceCat~Chan
2022-08-08 19:09:22 +02:00
committed by GitHub
parent cfbc91d6cf
commit f2624ea378
5 changed files with 138 additions and 13 deletions

View File

@@ -159,6 +159,15 @@ pub enum HirExprKind {
/// The target expression
expr: Handle<HirExpr>,
},
/// A method call like `what.something(a, b, c)`
Method {
/// expression the method call applies to (`what` in the example)
expr: Handle<HirExpr>,
/// the method name (`something` in the example)
name: String,
/// the arguments to the method (`a`, `b`, and `c` in the example)
args: Vec<Handle<HirExpr>>,
},
}
#[derive(Debug, Hash, PartialEq, Eq)]

View File

@@ -1366,6 +1366,67 @@ impl Context {
value
}
}
HirExprKind::Method {
expr: object,
ref name,
ref args,
} if ExprPos::Lhs != pos => {
let args = args
.iter()
.map(|e| self.lower_expect_inner(stmt, parser, *e, ExprPos::Rhs, body))
.collect::<Result<Vec<_>>>()?;
match name.as_ref() {
"length" => {
if !args.is_empty() {
parser.errors.push(Error {
kind: ErrorKind::SemanticError(
".length() doesn't take any arguments".into(),
),
meta,
});
}
let lowered_array =
self.lower_expect_inner(stmt, parser, object, pos, body)?.0;
let array_type = parser.resolve_type(self, lowered_array, meta)?;
match *array_type {
TypeInner::Array {
size: crate::ArraySize::Constant(size),
..
} => {
let mut array_length =
self.add_expression(Expression::Constant(size), meta, body);
self.forced_conversion(
parser,
&mut array_length,
meta,
ScalarKind::Sint,
4,
)?;
array_length
}
// let the error be handled in type checking if it's not a dynamic array
_ => {
let mut array_length = self.add_expression(
Expression::ArrayLength(lowered_array),
meta,
body,
);
self.conversion(&mut array_length, meta, ScalarKind::Sint, 4)?;
array_length
}
}
}
_ => {
return Err(Error {
kind: ErrorKind::SemanticError(
format!("unknown method '{}'", name).into(),
),
meta,
});
}
}
}
_ => {
return Err(Error {
kind: ErrorKind::SemanticError(

View File

@@ -231,6 +231,24 @@ impl<'source> ParsingContext<'source> {
TokenValue::Dot => {
let (field, end_meta) = self.expect_ident(parser)?;
if self.bump_if(parser, TokenValue::LeftParen).is_some() {
let args =
self.parse_function_call_args(parser, ctx, stmt, body, &mut meta)?;
base = stmt.hir_exprs.append(
HirExpr {
kind: HirExprKind::Method {
expr: base,
name: field,
args,
},
meta,
},
Default::default(),
);
continue;
}
meta.subsume(end_meta);
base = stmt.hir_exprs.append(
HirExpr {

View File

@@ -132,6 +132,18 @@ void testMatrixMultiplication(mat4x3 a, mat4x4 b) {
mat4x3 c = a * b;
}
layout(std430, binding = 0) buffer a_buf {
float a[];
};
void testLength() {
int len = a.length();
}
void testConstantLength(float a[4u]) {
int len = a.length();
}
out vec4 o_color;
void main() {
privatePointer(global);

View File

@@ -2,11 +2,17 @@ struct BST {
data: i32,
}
struct a_buf {
a: array<f32>,
}
struct FragmentOutput {
@location(0) o_color: vec4<f32>,
}
var<private> global: f32;
@group(0) @binding(0)
var<storage, read_write> global_1: a_buf;
var<private> o_color: vec4<f32>;
fn testBinOpVecFloat(a: vec4<f32>, b: f32) {
@@ -369,28 +375,47 @@ fn testMatrixMultiplication(a_22: mat4x3<f32>, b_18: mat4x4<f32>) {
return;
}
fn testLength() {
var len: i32;
len = i32(arrayLength((&global_1.a)));
return;
}
fn testConstantLength(a_24: array<f32,4u>) {
var a_25: array<f32,4u>;
var len_1: i32 = 4;
_ = (&global_1.a);
a_25 = a_24;
_ = a_25;
_ = i32(4u);
}
fn main_1() {
var local_5: f32;
_ = (&global_1.a);
_ = global;
let _e3 = global;
local_5 = _e3;
let _e5 = global;
local_5 = _e5;
privatePointer((&local_5));
let _e5 = local_5;
global = _e5;
let _e6 = o_color;
_ = _e6.xyzw;
let _e9 = vec4<f32>(1.0);
o_color.x = _e9.x;
o_color.y = _e9.y;
o_color.z = _e9.z;
o_color.w = _e9.w;
let _e7 = local_5;
global = _e7;
let _e8 = o_color;
_ = _e8.xyzw;
let _e11 = vec4<f32>(1.0);
o_color.x = _e11.x;
o_color.y = _e11.y;
o_color.z = _e11.z;
o_color.w = _e11.w;
return;
}
@fragment
fn main() -> FragmentOutput {
_ = (&global_1.a);
main_1();
let _e5 = o_color;
return FragmentOutput(_e5);
let _e7 = o_color;
return FragmentOutput(_e7);
}