Skip to content

Commit

Permalink
Import/export metadata in new representation.
Browse files Browse the repository at this point in the history
Moved names for compat.* constructors to model.
  • Loading branch information
zrho committed Jan 8, 2025
1 parent 4c1e776 commit e1aeb18
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 57 deletions.
37 changes: 14 additions & 23 deletions hugr-core/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ use std::fmt::Write;

pub(crate) const OP_FUNC_CALL_INDIRECT: &str = "func.call-indirect";
const TERM_PARAM_TUPLE: &str = "param.tuple";
const TERM_JSON: &str = "prelude.json";
const META_DESCRIPTION: &str = "docs.description";
const TERM_JSON_CONST: &str = "prelude.const-json";

/// Export a [`Hugr`] graph to its representation in the model.
pub fn export_hugr<'a>(hugr: &'a Hugr, bump: &'a Bump) -> model::Module<'a> {
Expand Down Expand Up @@ -558,15 +555,12 @@ impl<'a> Context<'a> {
let mut meta = BumpVec::with_capacity_in(meta_len, self.bump);

if let Some(description) = description {
let name = META_DESCRIPTION;
let value = self.make_term(model::Term::Str(self.bump.alloc_str(description)));
meta.push(model::MetaItem { name, value })
meta.push(self.make_term_apply(model::CORE_META_DESCRIPTION, &[value]));
}

for (name, value) in opdef.iter_misc() {
let name = self.bump.alloc_str(name);
let value = self.export_json_meta(value);
meta.push(model::MetaItem { name, value });
meta.push(self.export_json_meta(name, value));
}

self.bump.alloc_slice_copy(&meta)
Expand Down Expand Up @@ -1013,7 +1007,7 @@ impl<'a> Context<'a> {
let args = self
.bump
.alloc_slice_copy(&[runtime_type, json, extensions]);
let symbol = self.resolve_symbol(TERM_JSON_CONST);
let symbol = self.resolve_symbol(model::COMPAT_CONST_JSON);
self.make_term(model::Term::ApplyFull { symbol, args })
}

Expand Down Expand Up @@ -1052,30 +1046,21 @@ impl<'a> Context<'a> {
}
}

pub fn export_node_metadata(
&mut self,
metadata_map: &NodeMetadataMap,
) -> &'a [model::MetaItem<'a>] {
pub fn export_node_metadata(&mut self, metadata_map: &NodeMetadataMap) -> &'a [model::TermId] {
let mut meta = BumpVec::with_capacity_in(metadata_map.len(), self.bump);

for (name, value) in metadata_map {
let name = self.bump.alloc_str(name);
let value = self.export_json_meta(value);
meta.push(model::MetaItem { name, value });
meta.push(self.export_json_meta(name, value));
}

meta.into_bump_slice()
}

pub fn export_json_meta(&mut self, value: &serde_json::Value) -> model::TermId {
pub fn export_json_meta(&mut self, name: &str, value: &serde_json::Value) -> model::TermId {
let value = serde_json::to_string(value).expect("json values are always serializable");
let value = self.make_term(model::Term::Str(self.bump.alloc_str(&value)));
let value = self.bump.alloc_slice_copy(&[value]);
let symbol = self.resolve_symbol(TERM_JSON);
self.make_term(model::Term::ApplyFull {
symbol,
args: value,
})
let name = self.make_term(model::Term::Str(self.bump.alloc_str(name)));
self.make_term_apply(model::COMPAT_META_JSON, &[name, value])
}

fn resolve_symbol(&mut self, name: &'a str) -> model::NodeId {
Expand All @@ -1091,6 +1076,12 @@ impl<'a> Context<'a> {
}),
}
}

fn make_term_apply(&mut self, name: &'a str, args: &[model::TermId]) -> model::TermId {
let symbol = self.resolve_symbol(name);
let args = self.bump.alloc_slice_copy(args);
self.make_term(model::Term::ApplyFull { symbol, args })
}
}

#[cfg(test)]
Expand Down
21 changes: 11 additions & 10 deletions hugr-core/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ use itertools::Either;
use smol_str::{SmolStr, ToSmolStr};
use thiserror::Error;

const TERM_JSON: &str = "prelude.json";
const TERM_JSON_CONST: &str = "prelude.const-json";

/// Error during import.
#[derive(Debug, Clone, Error)]
pub enum ImportError {
Expand Down Expand Up @@ -174,8 +171,8 @@ impl<'a> Context<'a> {
for meta_item in node_data.meta {
// TODO: For now we expect all metadata to be JSON since this is how
// it is handled in `hugr-core`.
let value = self.import_json_meta(meta_item.value)?;
self.hugr.set_metadata(node, meta_item.name, value);
let (name, value) = self.import_json_meta(*meta_item)?;
self.hugr.set_metadata(node, name, value);
}

Ok(node)
Expand Down Expand Up @@ -1268,7 +1265,7 @@ impl<'a> Context<'a> {
fn import_json_meta(
&mut self,
term_id: model::TermId,
) -> Result<serde_json::Value, ImportError> {
) -> Result<(&'a str, serde_json::Value), ImportError> {
let (global, args) = match self.get_term(term_id)? {
model::Term::Apply { symbol, args } | model::Term::ApplyFull { symbol, args } => {
(symbol, args)
Expand All @@ -1277,11 +1274,15 @@ impl<'a> Context<'a> {
};

let global = self.get_symbol_name(*global)?;
if global != TERM_JSON {
if global != model::COMPAT_META_JSON {
return Err(model::ModelError::TypeError(term_id).into());
}

let [json_arg] = args else {
let [name_arg, json_arg] = args else {
return Err(model::ModelError::TypeError(term_id).into());
};

let model::Term::Str(name) = self.get_term(*name_arg)? else {
return Err(model::ModelError::TypeError(term_id).into());
};

Expand All @@ -1292,7 +1293,7 @@ impl<'a> Context<'a> {
let json_value =
serde_json::from_str(json_str).map_err(|_| model::ModelError::TypeError(term_id))?;

Ok(json_value)
Ok((name, json_value))
}

fn import_value(
Expand All @@ -1312,7 +1313,7 @@ impl<'a> Context<'a> {
model::Term::ApplyFull { symbol, args } => {
let symbol_name = self.get_symbol_name(*symbol)?;

if symbol_name == TERM_JSON_CONST {
if symbol_name == model::COMPAT_CONST_JSON {
let value = args.get(1).ok_or(model::ModelError::TypeError(term_id))?;

let model::Term::Str(json) = self.get_term(*value)? else {
Expand Down
14 changes: 8 additions & 6 deletions hugr-core/tests/snapshots/model__roundtrip_call.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-call
---
(hugr 0)

(import prelude.json)
(import compat.meta-json)

(import arithmetic.int.types.int)

Expand All @@ -13,18 +13,20 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-call
[(@ arithmetic.int.types.int)]
[(@ arithmetic.int.types.int)]
(ext ?0 ... arithmetic.int)
(meta doc.description (@ prelude.json "\"This is a function declaration.\""))
(meta doc.title (@ prelude.json "\"Callee\"")))
(meta
(@ compat.meta-json "description" "\"This is a function declaration.\""))
(meta (@ compat.meta-json "title" "\"Callee\"")))

(define-func example.caller
[(@ arithmetic.int.types.int)]
[(@ arithmetic.int.types.int)]
(ext arithmetic.int)
(meta doc.description
(meta
(@
prelude.json
compat.meta-json
"description"
"\"This defines a function that calls the function which we declared earlier.\""))
(meta doc.title (@ prelude.json "\"Caller\""))
(meta (@ compat.meta-json "title" "\"Caller\""))
(dfg
[%0] [%1]
(signature
Expand Down
10 changes: 5 additions & 5 deletions hugr-core/tests/snapshots/model__roundtrip_const.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-cons
---
(hugr 0)

(import prelude.const-json)
(import compat.const-json)

(import arithmetic.float.types.float64)

Expand Down Expand Up @@ -34,12 +34,12 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-cons
(tag
0
[(@
prelude.const-json
compat.const-json
(@ arithmetic.float.types.float64)
"{\"c\":\"ConstF64\",\"v\":{\"value\":2.0}}"
(ext arithmetic.float.types))
(@
prelude.const-json
compat.const-json
(@ arithmetic.float.types.float64)
"{\"c\":\"ConstF64\",\"v\":{\"value\":3.0}}"
(ext arithmetic.float.types))])
Expand All @@ -63,15 +63,15 @@ expression: "roundtrip(include_str!(\"../../hugr-model/tests/fixtures/model-cons
(ext)))
(const
(@
prelude.const-json
compat.const-json
(@ arithmetic.float.types.float64)
"{\"c\":\"ConstF64\",\"v\":{\"value\":1.0}}"
(ext arithmetic.float.types))
[] [%0]
(signature (-> [] [(@ arithmetic.float.types.float64)] (ext))))
(const
(@
prelude.const-json
compat.const-json
(@ arithmetic.float.types.float64)
"{\"c\":\"ConstUnknown\",\"v\":{\"value\":1.0}}"
(ext))
Expand Down
29 changes: 29 additions & 0 deletions hugr-model/src/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,35 @@
use smol_str::SmolStr;
use thiserror::Error;

/// Constructor for documentation metadata.
///
/// - **Parameter:** `?description : str`
/// - **Result:** `meta`
pub const CORE_META_DESCRIPTION: &str = "core.meta.description";

/// Constructor for JSON encoded metadata.
///
/// This is included in the model to allow for compatibility with `hugr-core`.
/// The intention is to deprecate this in the future in favor of metadata
/// expressed with custom constructors.
///
/// - **Parameter:** `?name : str`
/// - **Parameter:** `?json : str`
/// - **Result:** `meta`
pub const COMPAT_META_JSON: &str = "compat.meta-json";

/// Constructor for JSON encoded constants.
///
/// This is included in the model to allow for compatibility with `hugr-core`.
/// The intention is to deprecate this in the future in favor of constants
/// expressed with custom constructors.
///
/// - **Parameter:** `?type : type`
/// - **Parameter:** `?json : str`
/// - **Parameter:** `?exts : ext-set`
/// - **Result:** `(const ?type ?exts)`
pub const COMPAT_CONST_JSON: &str = "compat.const-json";

pub mod binary;
pub mod scope;
pub mod text;
Expand Down
8 changes: 4 additions & 4 deletions hugr-model/tests/fixtures/model-call.edn
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
(declare-func example.callee
(forall ?ext ext-set)
[(@ arithmetic.int.types.int)] [(@ arithmetic.int.types.int)] (ext arithmetic.int ?ext ...)
(meta doc.title (prelude.json "\"Callee\""))
(meta doc.description (prelude.json "\"This is a function declaration.\"")))
(meta (compat.meta-json "title" "\"Callee\""))
(meta (compat.meta-json "description" "\"This is a function declaration.\"")))

(define-func example.caller
[(@ arithmetic.int.types.int)] [(@ arithmetic.int.types.int)] (ext arithmetic.int)
(meta doc.title (prelude.json "\"Caller\""))
(meta doc.description (prelude.json "\"This defines a function that calls the function which we declared earlier.\""))
(meta (compat.meta-json "title" "\"Caller\""))
(meta (compat.meta-json "description" "\"This defines a function that calls the function which we declared earlier.\""))
(dfg [%3] [%4]
(signature (-> [(@ arithmetic.int.types.int)] [(@ arithmetic.int.types.int)] (ext)))
(call (@ example.callee (ext)) [%3] [%4]
Expand Down
8 changes: 4 additions & 4 deletions hugr-model/tests/fixtures/model-const.edn
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
(const
(tag
0
[(@ prelude.const-json (@ arithmetic.float.types.float64) "{\"c\":\"ConstF64\",\"v\":{\"value\":2.0}}" (ext))
(@ prelude.const-json (@ arithmetic.float.types.float64) "{\"c\":\"ConstF64\",\"v\":{\"value\":3.0}}" (ext))])
[(@ compat.const-json (@ arithmetic.float.types.float64) "{\"c\":\"ConstF64\",\"v\":{\"value\":2.0}}" (ext))
(@ compat.const-json (@ arithmetic.float.types.float64) "{\"c\":\"ConstF64\",\"v\":{\"value\":3.0}}" (ext))])
[] [%pair]
(signature
(->
Expand All @@ -40,11 +40,11 @@
(dfg [] [%0 %1]
(signature (-> [] [(@ arithmetic.float.types.float64) (@ arithmetic.float.types.float64)] (ext)))
(const
(@ prelude.const-json (@ arithmetic.float.types.float64) "{\"c\":\"ConstF64\",\"v\":{\"value\":1.0}}" (ext))
(@ compat.const-json (@ arithmetic.float.types.float64) "{\"c\":\"ConstF64\",\"v\":{\"value\":1.0}}" (ext))
[] [%0]
(signature (-> [] [(@ arithmetic.float.types.float64)] (ext))))
; The following const is to test that import/export can deal with unknown constants.
(const
(@ prelude.const-json (@ arithmetic.float.types.float64) "{\"c\":\"ConstUnknown\",\"v\":{\"value\":1.0}}" (ext))
(@ compat.const-json (@ arithmetic.float.types.float64) "{\"c\":\"ConstUnknown\",\"v\":{\"value\":1.0}}" (ext))
[] [%1]
(signature (-> [] [(@ arithmetic.float.types.float64)] (ext))))))
4 changes: 2 additions & 2 deletions hugr-model/tests/fixtures/model-decl-exts.edn
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
(param ?t type)
(param ?n nat)
type
(meta docs.description "Fixed size array."))
(meta (core.meta.description "Fixed size array.")))

(declare-operation array.Init
(param ?t type)
(param ?n nat)
(-> [?t] [(array.Array ?t ?n)] (ext array))
(meta docs.description "Initialize an array of size ?n with copies of a default value."))
(meta (core.meta.description "Initialize an array of size ?n with copies of a default value.")))
9 changes: 6 additions & 3 deletions hugr-model/tests/snapshots/text__declarative_extensions.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ expression: "roundtrip(include_str!(\"fixtures/model-decl-exts.edn\"))"
(param ?t type)
(param ?n nat)
type
(meta docs.description "Fixed size array."))
(meta (core.meta.description "Fixed size array.")))

(declare-operation array.Init
(param ?t type)
(param ?n nat)
(-> [?t] [(array.Array ?t ?n)] (ext array))
(meta docs.description
"Initialize an array of size ?n with copies of a default value."))
(meta
(core.meta.description
"Initialize an array of size ?n with copies of a default value.")))

(import core.meta.description)

0 comments on commit e1aeb18

Please sign in to comment.