Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add integer types to metadata #167

Merged
merged 1 commit into from
Mar 26, 2024
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
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = '2021'
license = 'Apache-2.0'
repository = 'https://github.com/digicatapult/sqnc-node/'
name = 'sqnc-node'
version = '11.0.0'
version = '11.1.0'

[[bin]]
name = 'sqnc-node'
Expand Down
2 changes: 1 addition & 1 deletion runtime/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sqnc-node-runtime"
version = "11.0.0"
version = "11.1.0"
authors = ["Digital Catapult <https://www.digicatapult.org.uk>"]
edition = "2021"
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("sqnc"),
impl_name: create_runtime_str!("sqnc"),
authoring_version: 1,
spec_version: 1100,
spec_version: 1110,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
2 changes: 1 addition & 1 deletion runtime/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = '2021'
license = 'Apache-2.0'
repository = 'https://github.com/digicatapult/sqnc-node/'
name = 'sqnc-runtime-types'
version = "1.0.2"
version = "1.1.0"

[package.metadata.docs.rs]
targets = ['x86_64-unknown-linux-gnu']
Expand Down
1 change: 1 addition & 0 deletions runtime/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub enum MetadataValue<TokenId> {
File(Hash),
Literal(BoundedVec<u8, ConstU32<32>>),
TokenId(TokenId),
Integer(i128),
None,
}

Expand Down
2 changes: 1 addition & 1 deletion tools/lang/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "sqnc-lang"
authors = ['Digital Catapult <https://www.digicatapult.org.uk>']
version = "0.3.0"
version = "0.4.0"
edition = "2021"

[lib]
Expand Down
36 changes: 36 additions & 0 deletions tools/lang/src/ast/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,38 @@ fn parse_literal<'a>(pair: pest::iterators::Pair<'a, Rule>) -> Result<AstNode<'a
})
}

fn parse_integer<'a>(pair: pest::iterators::Pair<'a, Rule>) -> Result<AstNode<'a, i128>, CompilationError> {
let integer_value_string = pair.into_inner().next().unwrap(); // integer_value
let parsed_integer = integer_value_string.as_str().parse::<i128>();

match parsed_integer {
Ok(val) => Ok(AstNode {
value: val,
span: integer_value_string.as_span(),
}),
Err(_) => Err(CompilationError {
stage: CompilationStage::BuildAst,
exit_code: exitcode::DATAERR,
inner: PestError::new_from_span(
ErrorVariant::CustomError {
message: "Error parsing integer".into(),
},
integer_value_string.as_span(),
),
}),
}
}

fn parse_token_prop_type(pair: pest::iterators::Pair<Rule>) -> Result<AstNode<TokenFieldType>, CompilationError> {
let span = pair.as_span();
let field_type = match pair.as_rule() {
Rule::file => Ok(TokenFieldType::File),
Rule::literal => Ok(TokenFieldType::Literal),
Rule::integer => Ok(TokenFieldType::Integer),
Rule::role => Ok(TokenFieldType::Role),
Rule::none => Ok(TokenFieldType::None),
Rule::literal_value => Ok(TokenFieldType::LiteralValue(parse_literal(pair)?)),
Rule::integer_value => Ok(TokenFieldType::IntegerValue(parse_integer(pair)?)),
Rule::ident => Ok(TokenFieldType::Token(AstNode {
span: pair.as_span(),
value: pair.as_str(),
Expand Down Expand Up @@ -258,6 +282,18 @@ fn parse_bool_cmp(pair: pest::iterators::Pair<Rule>) -> Result<AstNode<Compariso
span,
})
}
Rule::prop_int_cmp => {
let mut pairs = pair.into_inner();

let left = parse_ident_prop(pairs.next().unwrap())?;
let op = parse_bool_cmp_op(pairs.next().unwrap())?;
let right = parse_integer(pairs.next().unwrap())?; // literal_value

Ok(AstNode {
value: Comparison::PropInt { left, op, right },
span,
})
}
Rule::prop_sender_cmp => {
let mut pairs = pair.into_inner();
Ok(AstNode {
Expand Down
18 changes: 18 additions & 0 deletions tools/lang/src/ast/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ pub enum TokenFieldType<'a> {
File,
Role,
Literal,
Integer,
LiteralValue(AstNode<'a, &'a str>),
IntegerValue(AstNode<'a, i128>),
Token(AstNode<'a, &'a str>),
}

Expand All @@ -52,7 +54,9 @@ impl<'a> Display for TokenFieldType<'a> {
TokenFieldType::File => write!(f, "File"),
TokenFieldType::Role => write!(f, "Role"),
TokenFieldType::Literal => write!(f, "Literal"),
TokenFieldType::Integer => write!(f, "Integer"),
TokenFieldType::LiteralValue(s) => write!(f, "\"{}\"", s.value),
TokenFieldType::IntegerValue(s) => write!(f, "{}", s.value),
TokenFieldType::Token(s) => write!(f, "{}", s.value),
}
}
Expand Down Expand Up @@ -151,6 +155,7 @@ pub enum TypeCmpType {
File,
Role,
Literal,
Integer,
Token,
}

Expand All @@ -172,6 +177,11 @@ pub enum Comparison<'a> {
op: BoolCmp,
right: AstNode<'a, &'a str>,
},
PropInt {
left: AstNode<'a, TokenProp<'a>>,
op: BoolCmp,
right: AstNode<'a, i128>,
},
PropSender {
left: AstNode<'a, TokenProp<'a>>,
op: BoolCmp,
Expand Down Expand Up @@ -213,6 +223,13 @@ impl<'a> Display for Comparison<'a> {
};
write!(f, "{}.{} {} \"{}\"", left.value.token, left.value.prop, op, right)
}
Comparison::PropInt { left, op, right } => {
let op = match op {
BoolCmp::Eq => "==",
BoolCmp::Neq => "!=",
};
write!(f, "{}.{} {} {}", left.value.token, left.value.prop, op, right)
}
Comparison::PropSender { left, op } => {
let op = match op {
BoolCmp::Eq => "==",
Expand Down Expand Up @@ -255,6 +272,7 @@ impl<'a> Display for Comparison<'a> {
TypeCmpType::File => "File",
TypeCmpType::Role => "Role",
TypeCmpType::Literal => "Literal",
TypeCmpType::Integer => "Integer",
TypeCmpType::Token => "Token",
};
write!(f, "{}.{}{} {}", left.value.token, left.value.prop, op, right)
Expand Down
73 changes: 71 additions & 2 deletions tools/lang/src/compiler/condition_transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ pub fn transform_condition_to_program(
match comp {
Comparison::Fn { .. } => Err(CompilationError {
stage: crate::compiler::CompilationStage::ReduceTokens,
exit_code: exitcode::DATAERR,
exit_code: exitcode::SOFTWARE,
inner: PestError::new_from_span(
ErrorVariant::CustomError {
message: "Unexpected function call (should have been flattened)?".into(),
message: "Internal Error. Unexpected function call (should have been flattened)?".into(),
},
span,
),
Expand Down Expand Up @@ -205,6 +205,63 @@ pub fn transform_condition_to_program(

Ok(result)
}
Comparison::PropInt { left, op, right } => {
let TokenPropLocation {
is_input, index, types, ..
} = find_token_prop(token_decls, fn_decl, &left.value)?;
if types
.iter()
.find(|field_type| match &field_type.value {
TokenFieldType::Integer => true,
TokenFieldType::IntegerValue(v) => v.value == right.value,
_ => false,
})
.is_none()
{
return Err(CompilationError {
stage: crate::compiler::CompilationStage::GenerateRestrictions,
exit_code: exitcode::DATAERR,
inner: PestError::new_from_span(
ErrorVariant::CustomError {
message: format!(
"Invalid comparison between property {} and value {}",
left.value.prop.value, right.value
),
},
span,
),
});
}

let metadata_key = to_bounded_vec(AstNode {
value: left.value.prop.value.as_bytes().to_owned(),
span: left.value.prop.span,
})?;

let metadata_value = MetadataValue::Integer(right.value);

let mut result = vec![match is_input {
true => BooleanExpressionSymbol::Restriction(Restriction::FixedInputMetadataValue {
index,
metadata_key,
metadata_value,
}),
false => BooleanExpressionSymbol::Restriction(Restriction::FixedOutputMetadataValue {
index,
metadata_key,
metadata_value,
}),
}];

if op == BoolCmp::Neq {
result.append(&mut vec![
BooleanExpressionSymbol::Restriction(Restriction::None),
BooleanExpressionSymbol::Op(BooleanOperator::NotL),
]);
}

Ok(result)
}
Comparison::PropSender { left, op } => {
let TokenPropLocation {
is_input, index, types, ..
Expand Down Expand Up @@ -607,6 +664,18 @@ pub fn transform_condition_to_program(
metadata_value_type: MetadataValueType::Literal,
},
})],
TypeCmpType::Integer => vec![BooleanExpressionSymbol::Restriction(match left.is_input {
true => Restriction::FixedInputMetadataValueType {
index: left.index,
metadata_key: metadata_key.clone(),
metadata_value_type: MetadataValueType::Integer,
},
false => Restriction::FixedOutputMetadataValueType {
index: left.index,
metadata_key: metadata_key.clone(),
metadata_value_type: MetadataValueType::Integer,
},
})],
TypeCmpType::Token => vec![BooleanExpressionSymbol::Restriction(match left.is_input {
true => Restriction::FixedInputMetadataValueType {
index: left.index,
Expand Down
11 changes: 11 additions & 0 deletions tools/lang/src/compiler/flatten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ fn transform_comparison<'a>(
op,
right,
}),
Comparison::PropInt { left, op, right } => Ok(Comparison::PropInt {
left: AstNode {
value: TokenProp {
token: transform_name(left.value.token, token_name_transforms.clone())?,
prop: left.value.prop,
},
span: left.span,
},
op,
right,
}),
Comparison::PropSender { left, op } => Ok(Comparison::PropSender {
left: AstNode {
value: TokenProp {
Expand Down
Loading
Loading