Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 435f630f authored by Henri Chataing's avatar Henri Chataing
Browse files

PDL: Remove Expr ast nodes

Expr ast nodes were initially introduced with the mind they
would be used to describe generic values and size modifiers,
they are only used for constraint values at the moment.

Remove the Expr in favor of optional value, tag_id fields in
constraints. This makes the ast more uniform.

Test: parse and lint test/*.pdl files
Change-Id: I0528d2567e0bda18e7d9fa1282015ebaff053577
parent fe1986fc
Loading
Loading
Loading
Loading
+2 −14
Original line number Diff line number Diff line
@@ -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 {
@@ -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)]
+28 −29
Original line number Diff line number Diff line
@@ -384,15 +384,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
                        )),
@@ -402,29 +399,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(),
@@ -440,14 +435,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()]),
+2 −22
Original line number Diff line number Diff line
@@ -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())
}
@@ -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 })
    }
}

+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 {