Skip to content

Commit 8dec8c2

Browse files
[Metadata] Initial redesign (#2396)
An initial redesign of the metadata table. This PR ended up a little chunky, so to break things down it does the following: - Introduces a `SetAttribute` to Calyx which stores multiple unique numbers rather than only one. The syntax is `@Attribute_name{ n1, n2, n3 }` and `"attribute_name"={ n1, n2, n3 }` depending on the context. - Move `pos` from `Attribute` to `SetAttribute`. If a `pos` attribute is written with the standard syntax, the compiler will emit a warning and ignore the attribute. E.g. `@pos(1)` is incorrect and will be ignored since it should be `@pos{1}`. - Also adds an `Unknown` set attribute, which works the same as its corresponding variant in the standard attributes - Adds a new `MetadataTable` construct which is parsed in a `fileinfo #{ .. }#` block and made available in the `Workspace` and `Context` structures as an optional field. - At present, the table maps file identifiers to paths and positions to pairs of files and line numbers. We will likely want to extend this in the future. - The actual syntax of the table is a very basic placeholder which we can iterate on later as needed - There is currently a limited metadata lookup construct which will read the file contents into memory and return the given lines. It's pretty brittle right now - We may in the future want a special signifier for the current file / input stream as calyx->calyx mappings will want this. Though perhaps there is a better way of approaching this - Also moves the cider index implementation into a separate crate `cider-idx` as we were initially going to use that with the new table, but we moved away from that approach for the moment, so these changes are largely irrelevant. Didn't want to do git magic since it was already pushed and the branch is being used by @ayakayorihiro.
1 parent 13a942b commit 8dec8c2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1237
-245
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ members = [
2020
"tools/component_cells",
2121
"tools/yxi",
2222
"tools/calyx-writer",
23+
"cider-idx",
2324
]
2425
exclude = ["site"]
2526

@@ -43,7 +44,7 @@ log = "0.4"
4344
string-interner = "0.14.0"
4445
lazy_static = "1"
4546
linked-hash-map = "0.5"
46-
smallvec = "1"
47+
smallvec = { version = "1", features = ["const_generics"] }
4748
serde = { version = "1.0", features = ["derive"] }
4849
serde_json = "1.0"
4950
serde_sexpr = "0.1.0"

calyx-backend/src/mlir.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,13 @@ impl MlirBackend {
6060
} else {
6161
format!(
6262
" {{{}}}",
63-
attrs.to_string_with(", ", |k, v| { format!("{k}={v}") })
63+
attrs.to_string_with(
64+
", ",
65+
|k, v| { format!("{k}={v}") },
66+
// this is a placeholder for set attributes until they can
67+
// be added to the MLIR dialect
68+
|_, _| "".to_string()
69+
)
6470
)
6571
}
6672
}

calyx-frontend/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ readme.workspace = true
1515

1616
[features]
1717
default = []
18-
serialize = ["serde/derive", "dep:serde_with"]
18+
serialize = ["serde/derive", "dep:serde_with", "calyx-utils/serialize"]
1919

2020
[dependencies]
2121
atty.workspace = true
@@ -30,6 +30,7 @@ pest_derive.workspace = true
3030
pest_consume.workspace = true
3131
itertools.workspace = true
3232

33+
thiserror = "2"
3334
calyx-utils.workspace = true
3435

3536
strum_macros = "0.25"

calyx-frontend/src/ast.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Abstract Syntax Tree for Calyx
22
use super::parser;
3-
use crate::{Attributes, PortDef, Primitive};
3+
use crate::{source_info::SourceInfoTable, Attributes, PortDef, Primitive};
44
use atty::Stream;
55
use calyx_utils::{CalyxResult, Error, GPosIdx, Id, PosString};
66
use std::{num::NonZeroU64, path::PathBuf};
@@ -14,8 +14,10 @@ pub struct NamespaceDef {
1414
pub components: Vec<ComponentDef>,
1515
/// Extern statements and any primitive declarations in them.
1616
pub externs: Vec<(Option<PosString>, Vec<Primitive>)>,
17-
/// Optional opaque metadata
17+
/// Optional opaque metadata.
1818
pub metadata: Option<String>,
19+
/// Optional Source Info table
20+
pub source_info_table: Option<SourceInfoTable>,
1921
}
2022

2123
impl NamespaceDef {

calyx-frontend/src/attribute.rs

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,6 @@ pub enum NumAttr {
113113
#[strum(serialize = "bound")]
114114
/// The bound of a while loop
115115
Bound,
116-
#[strum(serialize = "pos")]
117-
/// Source location position for this node
118-
Pos,
119116
#[strum(serialize = "promotable")]
120117
/// Can promote the group, control, or @go port of the component to static
121118
/// with the annotated latency
@@ -162,6 +159,91 @@ impl From<InternalAttr> for Attribute {
162159
}
163160
}
164161

162+
#[derive(
163+
AsRefStr,
164+
EnumString,
165+
Clone,
166+
Copy,
167+
Hash,
168+
PartialEq,
169+
Eq,
170+
Debug,
171+
strum_macros::Display,
172+
PartialOrd,
173+
Ord,
174+
)]
175+
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
176+
pub enum SetAttr {
177+
#[strum(serialize = "pos")]
178+
/// Source location position for this node
179+
Pos,
180+
}
181+
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
182+
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
183+
pub enum SetAttribute {
184+
Set(SetAttr),
185+
Unknown(Id),
186+
}
187+
188+
impl Ord for SetAttribute {
189+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
190+
match (self, other) {
191+
(SetAttribute::Set(s1), SetAttribute::Set(s2)) => s1.cmp(s2),
192+
(SetAttribute::Set(_), SetAttribute::Unknown(_)) => {
193+
std::cmp::Ordering::Less
194+
}
195+
(SetAttribute::Unknown(_), SetAttribute::Set(_)) => {
196+
std::cmp::Ordering::Greater
197+
}
198+
(SetAttribute::Unknown(id1), SetAttribute::Unknown(id2)) => {
199+
id1.as_ref().cmp(id2.as_ref())
200+
}
201+
}
202+
}
203+
}
204+
205+
impl PartialOrd for SetAttribute {
206+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
207+
Some(self.cmp(other))
208+
}
209+
}
210+
211+
impl From<Id> for SetAttribute {
212+
fn from(v: Id) -> Self {
213+
Self::Unknown(v)
214+
}
215+
}
216+
217+
impl From<SetAttr> for SetAttribute {
218+
fn from(v: SetAttr) -> Self {
219+
Self::Set(v)
220+
}
221+
}
222+
223+
impl std::fmt::Display for SetAttribute {
224+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225+
match self {
226+
SetAttribute::Set(set_attr) => set_attr.fmt(f),
227+
SetAttribute::Unknown(id) => id.fmt(f),
228+
}
229+
}
230+
}
231+
232+
impl FromStr for SetAttribute {
233+
type Err = Error;
234+
fn from_str(s: &str) -> CalyxResult<Self> {
235+
if let Ok(s) = SetAttr::from_str(s) {
236+
Ok(SetAttribute::Set(s))
237+
} else {
238+
// Reject attributes that all caps since those are reserved for internal attributes
239+
if s.to_uppercase() == s {
240+
return Err(Error::misc(format!("Invalid attribute: {}. All caps attributes are reserved for internal use.", s)));
241+
}
242+
Ok(SetAttribute::Unknown(s.into()))
243+
}
244+
}
245+
}
246+
165247
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
166248
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
167249
/// Defines the known attributes that can be attached to IR nodes.
@@ -197,6 +279,11 @@ impl FromStr for Attribute {
197279
if DEPRECATED_ATTRIBUTES.contains(&s) {
198280
log::warn!("The attribute @{s} is deprecated and will be ignored by the compiler.");
199281
}
282+
283+
if let Ok(SetAttribute::Set(_)) = SetAttribute::from_str(s) {
284+
log::warn!("Set attribute {s} incorrectly written as a standard attribute, i.e. '@{s}(..)' or '\"{s}\" = ..'. This will be ignored by the compiler. Instead write '@{s}{{..}}' or '\"{s}\" = {{..}}'.");
285+
}
286+
200287
// Reject attributes that all caps since those are reserved for internal attributes
201288
if s.to_uppercase() == s {
202289
return Err(Error::misc(format!("Invalid attribute: {}. All caps attributes are reserved for internal use.", s)));

0 commit comments

Comments
 (0)