Loading tools/pdl/src/ast.rs +2 −14 Original line number Diff line number Diff line Loading @@ -50,19 +50,6 @@ pub struct Endianness { pub value: EndiannessValue, } #[derive(Debug, Serialize)] #[serde(tag = "kind")] pub enum Expr { #[serde(rename = "identifier")] Identifier { loc: SourceRange, name: String }, #[serde(rename = "integer")] Integer { loc: SourceRange, value: usize }, #[serde(rename = "unary_expr")] Unary { loc: SourceRange, op: String, operand: Box<Expr> }, #[serde(rename = "binary_expr")] Binary { loc: SourceRange, op: String, operands: Box<(Expr, Expr)> }, } #[derive(Debug, Serialize)] #[serde(tag = "kind", rename = "tag")] pub struct Tag { Loading @@ -76,7 +63,8 @@ pub struct Tag { pub struct Constraint { pub id: String, pub loc: SourceRange, pub value: Expr, pub value: Option<usize>, pub tag_id: Option<String>, } #[derive(Debug, Serialize)] Loading tools/pdl/src/lint.rs +28 −29 Original line number Diff line number Diff line Loading @@ -377,15 +377,12 @@ fn lint_constraint( result: &mut LintDiagnostics, ) { // Validate constraint value types. match (packet_scope.all_fields.get(&constraint.id), &constraint.value) { ( Some(Field::Scalar { loc: field_loc, width, .. }), Expr::Integer { value, loc: value_loc, .. }, ) => { match (packet_scope.all_fields.get(&constraint.id), &constraint.value, &constraint.tag_id) { (Some(Field::Scalar { loc: field_loc, width, .. }), Some(value), _) => { if bit_width(*value) > *width { result.push( Diagnostic::error().with_message("invalid integer literal").with_labels(vec![ value_loc.primary().with_message(format!( constraint.loc.primary().with_message(format!( "expected maximum value of `{}`", (1 << *width) - 1 )), Loading @@ -395,29 +392,27 @@ fn lint_constraint( } } (Some(Field::Typedef { type_id, loc: field_loc, .. }), _) => { match (scope.typedef.get(type_id), &constraint.value) { (Some(Decl::Enum { tags, .. }), Expr::Identifier { name, loc: name_loc, .. }) => { if !tags.iter().any(|t| &t.id == name) { (Some(Field::Scalar { loc: field_loc, .. }), None, _) => { result.push(Diagnostic::error().with_message("invalid literal type").with_labels(vec![ constraint.loc.primary().with_message("expected integer literal"), field_loc.secondary().with_message("the value is used here"), ])) } (Some(Field::Typedef { type_id, loc: field_loc, .. }), _, _) => { match (scope.typedef.get(type_id), &constraint.tag_id) { (Some(Decl::Enum { tags, .. }), Some(tag_id)) => { if !tags.iter().any(|t| &t.id == tag_id) { result.push( Diagnostic::error() .with_message(format!("undeclared enum tag `{}`", name)) .with_message(format!("undeclared enum tag `{}`", tag_id)) .with_labels(vec![ name_loc.primary(), constraint.loc.primary(), field_loc.secondary().with_message("the value is used here"), ]), ) } } (Some(Decl::Enum { .. }), _) => result.push( Diagnostic::error().with_message("invalid literal type").with_labels(vec![ constraint .loc .primary() .with_message(format!("expected `{}` tag identifier", type_id)), field_loc.secondary().with_message("the value is used here"), ]), ), (Some(decl), _) => result.push( Diagnostic::error().with_message("invalid constraint").with_labels(vec![ constraint.loc.primary(), Loading @@ -433,14 +428,18 @@ fn lint_constraint( } } (Some(Field::Scalar { loc: field_loc, .. }), _) => { result.push(Diagnostic::error().with_message("invalid literal type").with_labels(vec![ constraint.loc.primary().with_message("expected integer literal"), field_loc.secondary().with_message("the value is used here"), ])) } (Some(_), _) => unreachable!(), (None, _) => result.push( (Some(field), _, _) => result.push( Diagnostic::error() .with_message("invalid constraint field type") .with_labels(vec![constraint.loc.primary()]) .with_notes(vec![format!( "`{}` has type {}, expected enum field or scalar field", constraint.id, field.kind() )]), ), (None, _, _) => result.push( Diagnostic::error() .with_message(format!("undeclared identifier `{}`", constraint.id)) .with_labels(vec![constraint.loc.primary()]), Loading tools/pdl/src/parser.rs +2 −22 Original line number Diff line number Diff line Loading @@ -237,26 +237,6 @@ fn parse_string(iter: &mut NodeIterator<'_>) -> Result<String, String> { expect(iter, Rule::string).map(|n| n.as_string()) } fn parse_atomic_expr(iter: &mut NodeIterator<'_>, context: &Context) -> Result<ast::Expr, String> { match iter.next() { Some(n) if n.as_rule() == Rule::identifier => { Ok(ast::Expr::Identifier { loc: n.as_loc(context), name: n.as_string() }) } Some(n) if n.as_rule() == Rule::integer => { Ok(ast::Expr::Integer { loc: n.as_loc(context), value: n.as_usize()? }) } Some(n) => Err(format!( "expected rule {:?} or {:?}, got {:?}", Rule::identifier, Rule::integer, n.as_rule() )), None => { Err(format!("expected rule {:?} or {:?}, got nothing", Rule::identifier, Rule::integer)) } } } fn parse_size_modifier_opt(iter: &mut NodeIterator<'_>) -> Option<String> { maybe(iter, Rule::size_modifier).map(|n| n.as_string()) } Loading @@ -283,8 +263,8 @@ fn parse_constraint(node: Node<'_>, context: &Context) -> Result<ast::Constraint let loc = node.as_loc(context); let mut children = node.children(); let id = parse_identifier(&mut children)?; let value = parse_atomic_expr(&mut children, context)?; Ok(ast::Constraint { id, loc, value }) let (tag_id, value) = parse_identifier_or_integer(&mut children)?; Ok(ast::Constraint { id, loc, value, tag_id }) } } Loading tools/pdl/test/group-constraint.pdl +1 −1 Original line number Diff line number Diff line little_endian_packets custom_field custom: 1 "custom" custom_field custom_field: 1 "custom" checksum checksum: 1 "checksum" enum Enum : 1 { Loading Loading
tools/pdl/src/ast.rs +2 −14 Original line number Diff line number Diff line Loading @@ -50,19 +50,6 @@ pub struct Endianness { pub value: EndiannessValue, } #[derive(Debug, Serialize)] #[serde(tag = "kind")] pub enum Expr { #[serde(rename = "identifier")] Identifier { loc: SourceRange, name: String }, #[serde(rename = "integer")] Integer { loc: SourceRange, value: usize }, #[serde(rename = "unary_expr")] Unary { loc: SourceRange, op: String, operand: Box<Expr> }, #[serde(rename = "binary_expr")] Binary { loc: SourceRange, op: String, operands: Box<(Expr, Expr)> }, } #[derive(Debug, Serialize)] #[serde(tag = "kind", rename = "tag")] pub struct Tag { Loading @@ -76,7 +63,8 @@ pub struct Tag { pub struct Constraint { pub id: String, pub loc: SourceRange, pub value: Expr, pub value: Option<usize>, pub tag_id: Option<String>, } #[derive(Debug, Serialize)] Loading
tools/pdl/src/lint.rs +28 −29 Original line number Diff line number Diff line Loading @@ -377,15 +377,12 @@ fn lint_constraint( result: &mut LintDiagnostics, ) { // Validate constraint value types. match (packet_scope.all_fields.get(&constraint.id), &constraint.value) { ( Some(Field::Scalar { loc: field_loc, width, .. }), Expr::Integer { value, loc: value_loc, .. }, ) => { match (packet_scope.all_fields.get(&constraint.id), &constraint.value, &constraint.tag_id) { (Some(Field::Scalar { loc: field_loc, width, .. }), Some(value), _) => { if bit_width(*value) > *width { result.push( Diagnostic::error().with_message("invalid integer literal").with_labels(vec![ value_loc.primary().with_message(format!( constraint.loc.primary().with_message(format!( "expected maximum value of `{}`", (1 << *width) - 1 )), Loading @@ -395,29 +392,27 @@ fn lint_constraint( } } (Some(Field::Typedef { type_id, loc: field_loc, .. }), _) => { match (scope.typedef.get(type_id), &constraint.value) { (Some(Decl::Enum { tags, .. }), Expr::Identifier { name, loc: name_loc, .. }) => { if !tags.iter().any(|t| &t.id == name) { (Some(Field::Scalar { loc: field_loc, .. }), None, _) => { result.push(Diagnostic::error().with_message("invalid literal type").with_labels(vec![ constraint.loc.primary().with_message("expected integer literal"), field_loc.secondary().with_message("the value is used here"), ])) } (Some(Field::Typedef { type_id, loc: field_loc, .. }), _, _) => { match (scope.typedef.get(type_id), &constraint.tag_id) { (Some(Decl::Enum { tags, .. }), Some(tag_id)) => { if !tags.iter().any(|t| &t.id == tag_id) { result.push( Diagnostic::error() .with_message(format!("undeclared enum tag `{}`", name)) .with_message(format!("undeclared enum tag `{}`", tag_id)) .with_labels(vec![ name_loc.primary(), constraint.loc.primary(), field_loc.secondary().with_message("the value is used here"), ]), ) } } (Some(Decl::Enum { .. }), _) => result.push( Diagnostic::error().with_message("invalid literal type").with_labels(vec![ constraint .loc .primary() .with_message(format!("expected `{}` tag identifier", type_id)), field_loc.secondary().with_message("the value is used here"), ]), ), (Some(decl), _) => result.push( Diagnostic::error().with_message("invalid constraint").with_labels(vec![ constraint.loc.primary(), Loading @@ -433,14 +428,18 @@ fn lint_constraint( } } (Some(Field::Scalar { loc: field_loc, .. }), _) => { result.push(Diagnostic::error().with_message("invalid literal type").with_labels(vec![ constraint.loc.primary().with_message("expected integer literal"), field_loc.secondary().with_message("the value is used here"), ])) } (Some(_), _) => unreachable!(), (None, _) => result.push( (Some(field), _, _) => result.push( Diagnostic::error() .with_message("invalid constraint field type") .with_labels(vec![constraint.loc.primary()]) .with_notes(vec![format!( "`{}` has type {}, expected enum field or scalar field", constraint.id, field.kind() )]), ), (None, _, _) => result.push( Diagnostic::error() .with_message(format!("undeclared identifier `{}`", constraint.id)) .with_labels(vec![constraint.loc.primary()]), Loading
tools/pdl/src/parser.rs +2 −22 Original line number Diff line number Diff line Loading @@ -237,26 +237,6 @@ fn parse_string(iter: &mut NodeIterator<'_>) -> Result<String, String> { expect(iter, Rule::string).map(|n| n.as_string()) } fn parse_atomic_expr(iter: &mut NodeIterator<'_>, context: &Context) -> Result<ast::Expr, String> { match iter.next() { Some(n) if n.as_rule() == Rule::identifier => { Ok(ast::Expr::Identifier { loc: n.as_loc(context), name: n.as_string() }) } Some(n) if n.as_rule() == Rule::integer => { Ok(ast::Expr::Integer { loc: n.as_loc(context), value: n.as_usize()? }) } Some(n) => Err(format!( "expected rule {:?} or {:?}, got {:?}", Rule::identifier, Rule::integer, n.as_rule() )), None => { Err(format!("expected rule {:?} or {:?}, got nothing", Rule::identifier, Rule::integer)) } } } fn parse_size_modifier_opt(iter: &mut NodeIterator<'_>) -> Option<String> { maybe(iter, Rule::size_modifier).map(|n| n.as_string()) } Loading @@ -283,8 +263,8 @@ fn parse_constraint(node: Node<'_>, context: &Context) -> Result<ast::Constraint let loc = node.as_loc(context); let mut children = node.children(); let id = parse_identifier(&mut children)?; let value = parse_atomic_expr(&mut children, context)?; Ok(ast::Constraint { id, loc, value }) let (tag_id, value) = parse_identifier_or_integer(&mut children)?; Ok(ast::Constraint { id, loc, value, tag_id }) } } Loading
tools/pdl/test/group-constraint.pdl +1 −1 Original line number Diff line number Diff line little_endian_packets custom_field custom: 1 "custom" custom_field custom_field: 1 "custom" checksum checksum: 1 "checksum" enum Enum : 1 { Loading