spade_parser/
item_type.rs
1use local_impl::local_impl;
2use spade_ast::UnitKind;
3use spade_common::location_info::Loc;
4use spade_diagnostics::Diagnostic;
5
6fn not_allowed_in_function(message: &str, at: Loc<()>, what: &str, kw_loc: Loc<()>) -> Diagnostic {
7 Diagnostic::error(at, message)
8 .primary_label(format!("{what} not allowed here"))
9 .secondary_label(kw_loc, "this is a function")
10 .note("functions can only contain combinatorial logic")
11 .span_suggest_replace("consider making the function an entity", kw_loc, "entity")
12}
13
14fn bug_no_item_context(at: Loc<()>) -> Diagnostic {
15 Diagnostic::bug(
16 at,
17 "attempted to parse something which requires an item context, but no item context exists",
18 )
19}
20
21fn stage_ref_in(what: &str, at: Loc<()>, kw_loc: Loc<()>) -> Diagnostic {
22 Diagnostic::error(at, format!("pipeline stage reference in {what}"))
23 .primary_label("pipeline stage reference not allowed here")
24 .secondary_label(kw_loc, format!("this is a {what}"))
25 .note("only pipelines can contain pipeline stage references")
26 .span_suggest_replace(
27 format!("consider making the {} a pipeline", what),
28 kw_loc,
29 "pipeline(/* depth */)",
30 )
31}
32
33#[local_impl]
34impl UnitKindLocal for Option<Loc<UnitKind>> {
35 fn allows_reg(&self, at: Loc<()>) -> Result<(), Diagnostic> {
36 match self.as_ref().map(|x| x.split_loc_ref()) {
37 Some((UnitKind::Function, kw_loc)) => Err(not_allowed_in_function(
38 "register declared in function",
39 at,
40 "register",
41 kw_loc,
42 )),
43 Some((UnitKind::Entity | UnitKind::Pipeline(_), _)) => Ok(()),
44 None => Err(bug_no_item_context(at)),
45 }
46 }
47
48 fn allows_inst(&self, at: Loc<()>) -> Result<(), Diagnostic> {
49 match self.as_ref().map(|x| x.split_loc_ref()) {
50 Some((UnitKind::Function, kw_loc)) => Err(not_allowed_in_function(
52 "cannot instantiate entities and pipelines in functions",
53 at,
54 "inst",
55 kw_loc,
56 )),
57 Some((UnitKind::Entity | UnitKind::Pipeline(_), _)) => Ok(()),
58 None => Err(bug_no_item_context(at)),
59 }
60 }
61
62 fn allows_pipeline_ref(&self, at: Loc<()>) -> Result<(), Diagnostic> {
63 match self.as_ref().map(|x| x.split_loc_ref()) {
64 Some((UnitKind::Function, kw_loc)) => Err(stage_ref_in("function", at, kw_loc)),
65 Some((UnitKind::Entity, kw_loc)) => Err(stage_ref_in("entity", at, kw_loc)),
66 Some((UnitKind::Pipeline(_), _)) => Ok(()),
67 None => Err(bug_no_item_context(at)),
68 }
69 }
70}