Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions vhdl_lang/src/analysis/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ impl<'a> AnalyzeContext<'a, '_> {
AssignmentRightHand::Selected(selection) => {
let Selection {
expression,
is_matching: _,
alternatives,
} = selection;
let ctyp = as_fatal(self.expr_unambiguous_type(scope, expression, diagnostics))?;
Expand Down Expand Up @@ -95,6 +96,7 @@ impl<'a> AnalyzeContext<'a, '_> {
AssignmentRightHand::Selected(selection) => {
let Selection {
expression,
is_matching: _,
alternatives,
} = selection;
let ctyp = as_fatal(self.expr_unambiguous_type(scope, expression, diagnostics))?;
Expand Down
1 change: 1 addition & 0 deletions vhdl_lang/src/analysis/concurrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ impl<'a> AnalyzeContext<'a, '_> {
sels:
Selection {
ref mut expression,
is_matching: _,
ref mut alternatives,
},
end_label_pos: _,
Expand Down
1 change: 1 addition & 0 deletions vhdl_lang/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,7 @@ pub struct Alternative<T> {
#[derive(PartialEq, Debug, Clone)]
pub struct Selection<T> {
pub expression: WithTokenSpan<Expression>,
pub is_matching: bool,
pub alternatives: Vec<Alternative<T>>,
}

Expand Down
2 changes: 2 additions & 0 deletions vhdl_lang/src/ast/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ fn search_selection<T: Search>(
) -> SearchResult {
let Selection {
expression,
is_matching: _,
alternatives,
} = selection;
return_if_found!(expression.search(ctx, searcher));
Expand Down Expand Up @@ -246,6 +247,7 @@ fn search_assignment<T: Search>(
AssignmentRightHand::Selected(selection) => {
let Selection {
expression,
is_matching: _,
alternatives,
} = selection;
// expression comes before target
Expand Down
12 changes: 11 additions & 1 deletion vhdl_lang/src/syntax/concurrent_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,18 @@ fn parse_selected_signal_assignment(
ctx.stream.expect_kind(With)?;
let expression = parse_expression(ctx)?;
ctx.stream.expect_kind(Select)?;
let is_matching = ctx.stream.pop_if_kind(Que).is_some();
let target = parse_target(ctx)?;
ctx.stream.expect_kind(LTE)?;
// @TODO guarded
let guarded = false;
let delay_mechanism = parse_delay_mechanism(ctx)?;
let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_waveform)?);
let rhs = AssignmentRightHand::Selected(parse_selection(
ctx,
expression,
is_matching,
parse_waveform,
)?);
Ok(ConcurrentSignalAssignment {
postponed,
guarded,
Expand Down Expand Up @@ -591,6 +597,7 @@ fn parse_case_generate_statement(
Ok(CaseGenerateStatement {
sels: Selection {
expression,
is_matching: false,
alternatives,
},
end_label_pos: check_label_identifier_mismatch(ctx, label, end_ident),
Expand Down Expand Up @@ -1360,6 +1367,7 @@ with x(0) + 1 select

let selection = Selection {
expression: code.s1("x(0) + 1").expr(),
is_matching: false,
alternatives: vec![Alternative {
choices: code.s1("0|1").choices(),
item: code.s1("bar(1,2) after 2 ns").waveform(),
Expand Down Expand Up @@ -2126,6 +2134,7 @@ end generate;",
let gen = CaseGenerateStatement {
sels: Selection {
expression: code.s1("expr(0) + 2").expr(),
is_matching: false,
alternatives: vec![
Alternative {
choices: code.s1("1 | 2").choices(),
Expand Down Expand Up @@ -2180,6 +2189,7 @@ end generate gen1;",
let gen = CaseGenerateStatement {
sels: Selection {
expression: code.s1("expr(0) + 2").expr(),
is_matching: false,
alternatives: vec![
Alternative {
choices: code.s1("1 | 2").choices(),
Expand Down
57 changes: 54 additions & 3 deletions vhdl_lang/src/syntax/sequential_statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ where
pub fn parse_selection<T, F>(
ctx: &mut ParsingContext<'_>,
expression: WithTokenSpan<Expression>,
is_matching: bool,
parse_item: F,
) -> ParseResult<Selection<T>>
where
Expand Down Expand Up @@ -422,6 +423,7 @@ where

Ok(Selection {
expression,
is_matching,
alternatives,
})
}
Expand Down Expand Up @@ -520,12 +522,13 @@ pub fn parse_target(ctx: &mut ParsingContext<'_>) -> ParseResult<WithTokenSpan<T
fn parse_selected_assignment(ctx: &mut ParsingContext<'_>) -> ParseResult<SequentialStatement> {
let expression = parse_expression(ctx)?;
ctx.stream.expect_kind(Select)?;
let is_matching = ctx.stream.pop_if_kind(Que).is_some();
let target = parse_target(ctx)?;
expect_token!(
ctx.stream,
token,
ColonEq => {
let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_expression)?);
let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, is_matching, parse_expression)?);
Ok(SequentialStatement::VariableAssignment(VariableAssignment {
target,
rhs,
Expand All @@ -536,13 +539,13 @@ fn parse_selected_assignment(ctx: &mut ParsingContext<'_>) -> ParseResult<Sequen
Ok(SequentialStatement::SignalForceAssignment(SignalForceAssignment {
target,
force_mode: parse_optional_force_mode(ctx)?,
rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_expression)?)
rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, is_matching, parse_expression)?)
}))
} else {
Ok(SequentialStatement::SignalAssignment(SignalAssignment {
target,
delay_mechanism: parse_delay_mechanism(ctx)?,
rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_waveform)?)
rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, is_matching, parse_waveform)?)
}))
}
}
Expand Down Expand Up @@ -1097,6 +1100,7 @@ with x(0) + 1 select

let selection = Selection {
expression: code.s1("x(0) + 1").expr(),
is_matching: false,
alternatives: vec![
Alternative {
choices: code.s1("0|1").choices(),
Expand Down Expand Up @@ -1246,6 +1250,7 @@ with x(0) + 1 select

let selection = Selection {
expression: code.s1("x(0) + 1").expr(),
is_matching: false,
alternatives: vec![
Alternative {
choices: code.s1("0|1").choices(),
Expand Down Expand Up @@ -1290,6 +1295,7 @@ with x(0) + 1 select

let selection = Selection {
expression: code.s1("x(0) + 1").expr(),
is_matching: false,
alternatives: vec![
Alternative {
choices: code.s1("0|1").choices(),
Expand Down Expand Up @@ -1320,6 +1326,51 @@ with x(0) + 1 select
);
}

#[test]
fn parse_matching_selected_assignment() {
let (code, statement) = parse(
"\
with x(0) + 1 select?
foo(0) <= transport bar(1,2) after 2 ns when 0|1,
def when others;",
);

let selection = Selection {
expression: code.s1("x(0) + 1").expr(),
is_matching: true,
alternatives: vec![
Alternative {
choices: code.s1("0|1").choices(),
item: code.s1("bar(1,2) after 2 ns").waveform(),
span: code.s1("bar(1,2) after 2 ns when 0|1").token_span(),
},
Alternative {
choices: code.s1("others").choices(),
item: code.s1("def").waveform(),
span: code.s1("def when others").token_span(),
},
],
};

assert_eq!(
statement,
with_label(
None,
WithTokenSpan::new(
SequentialStatement::SignalAssignment(SignalAssignment {
target: code.s1("foo(0)").name().map_into(Target::Name),
delay_mechanism: Some(WithTokenSpan::new(
DelayMechanism::Transport,
code.s1("transport").token_span()
)),
rhs: AssignmentRightHand::Selected(selection),
}),
code.token_span()
)
)
);
}

#[test]
fn parse_procedure_call_statement() {
let (code, statement) = parse("foo(1,2);");
Expand Down