From b6836b37d4b1a914d86e224527e526667506950b Mon Sep 17 00:00:00 2001 From: collin Date: Mon, 8 Jun 2020 14:07:06 -0700 Subject: [PATCH] add leo-inputs ast --- leo-inputs/src/assignments/assignment.rs | 14 + leo-inputs/src/assignments/mod.rs | 2 + leo-inputs/src/ast.rs | 302 +----------------- leo-inputs/src/circuits/circuit_field.rs | 13 + leo-inputs/src/circuits/mod.rs | 4 + leo-inputs/src/common/eoi.rs | 7 + leo-inputs/src/common/identifier.rs | 20 ++ leo-inputs/src/common/line_end.rs | 7 + leo-inputs/src/common/mod.rs | 11 + leo-inputs/src/common/visibility.rs | 18 ++ leo-inputs/src/errors/syntax.rs | 2 +- .../array_initializer_expression.rs | 13 + .../expressions/array_inline_expression.rs | 12 + .../expressions/circuit_inline_expression.rs | 13 + leo-inputs/src/expressions/expression.rs | 40 +++ leo-inputs/src/expressions/mod.rs | 11 + leo-inputs/src/files/file.rs | 13 + leo-inputs/src/files/mod.rs | 2 + leo-inputs/src/leo-inputs.pest | 39 ++- leo-inputs/src/lib.rs | 13 +- leo-inputs/src/parameters/mod.rs | 2 + leo-inputs/src/parameters/parameter.rs | 14 + leo-inputs/src/sections/header.rs | 12 + leo-inputs/src/sections/mod.rs | 5 + leo-inputs/src/sections/section.rs | 13 + leo-inputs/src/types/array_type.rs | 13 + leo-inputs/src/types/boolean_type.rs | 7 + leo-inputs/src/types/circuit_type.rs | 12 + leo-inputs/src/types/data_type.rs | 12 + leo-inputs/src/types/field_type.rs | 7 + leo-inputs/src/types/group_type.rs | 7 + leo-inputs/src/types/integer_type.rs | 33 ++ leo-inputs/src/types/mod.rs | 23 ++ leo-inputs/src/types/type_.rs | 22 ++ leo-inputs/src/values/boolean_value.rs | 20 ++ leo-inputs/src/values/field_value.rs | 20 ++ leo-inputs/src/values/group_value.rs | 51 +++ leo-inputs/src/values/integer_value.rs | 20 ++ leo-inputs/src/values/mod.rs | 20 ++ .../src/values/number_implicit_value.rs | 19 ++ leo-inputs/src/values/number_value.rs | 20 ++ leo-inputs/src/values/value.rs | 39 +++ 42 files changed, 638 insertions(+), 309 deletions(-) create mode 100644 leo-inputs/src/assignments/assignment.rs create mode 100644 leo-inputs/src/assignments/mod.rs create mode 100644 leo-inputs/src/circuits/circuit_field.rs create mode 100644 leo-inputs/src/circuits/mod.rs create mode 100644 leo-inputs/src/common/eoi.rs create mode 100644 leo-inputs/src/common/identifier.rs create mode 100644 leo-inputs/src/common/line_end.rs create mode 100644 leo-inputs/src/common/mod.rs create mode 100644 leo-inputs/src/common/visibility.rs create mode 100644 leo-inputs/src/expressions/array_initializer_expression.rs create mode 100644 leo-inputs/src/expressions/array_inline_expression.rs create mode 100644 leo-inputs/src/expressions/circuit_inline_expression.rs create mode 100644 leo-inputs/src/expressions/expression.rs create mode 100644 leo-inputs/src/expressions/mod.rs create mode 100644 leo-inputs/src/files/file.rs create mode 100644 leo-inputs/src/files/mod.rs create mode 100644 leo-inputs/src/parameters/mod.rs create mode 100644 leo-inputs/src/parameters/parameter.rs create mode 100644 leo-inputs/src/sections/header.rs create mode 100644 leo-inputs/src/sections/mod.rs create mode 100644 leo-inputs/src/sections/section.rs create mode 100644 leo-inputs/src/types/array_type.rs create mode 100644 leo-inputs/src/types/boolean_type.rs create mode 100644 leo-inputs/src/types/circuit_type.rs create mode 100644 leo-inputs/src/types/data_type.rs create mode 100644 leo-inputs/src/types/field_type.rs create mode 100644 leo-inputs/src/types/group_type.rs create mode 100644 leo-inputs/src/types/integer_type.rs create mode 100644 leo-inputs/src/types/mod.rs create mode 100644 leo-inputs/src/types/type_.rs create mode 100644 leo-inputs/src/values/boolean_value.rs create mode 100644 leo-inputs/src/values/field_value.rs create mode 100644 leo-inputs/src/values/group_value.rs create mode 100644 leo-inputs/src/values/integer_value.rs create mode 100644 leo-inputs/src/values/mod.rs create mode 100644 leo-inputs/src/values/number_implicit_value.rs create mode 100644 leo-inputs/src/values/number_value.rs create mode 100644 leo-inputs/src/values/value.rs diff --git a/leo-inputs/src/assignments/assignment.rs b/leo-inputs/src/assignments/assignment.rs new file mode 100644 index 0000000000..0945a146a1 --- /dev/null +++ b/leo-inputs/src/assignments/assignment.rs @@ -0,0 +1,14 @@ +use crate::{ast::Rule, common::LineEnd, expressions::Expression, parameters::Parameter}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::assignment))] +pub struct Assignment<'ast> { + pub parameter: Parameter<'ast>, + pub expression: Expression<'ast>, + pub line_end: LineEnd, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/assignments/mod.rs b/leo-inputs/src/assignments/mod.rs new file mode 100644 index 0000000000..e02881fe86 --- /dev/null +++ b/leo-inputs/src/assignments/mod.rs @@ -0,0 +1,2 @@ +pub mod assignment; +pub use assignment::*; diff --git a/leo-inputs/src/ast.rs b/leo-inputs/src/ast.rs index 9738652480..9d82bbb91d 100644 --- a/leo-inputs/src/ast.rs +++ b/leo-inputs/src/ast.rs @@ -1,7 +1,5 @@ //! Abstract syntax tree (ast) representation from leo-inputs.pest. - use pest::{error::Error, iterators::Pairs, Parser, Span}; -use pest_ast::FromPest; #[derive(Parser)] #[grammar = "leo-inputs.pest"] @@ -11,304 +9,6 @@ pub fn parse(input: &str) -> Result, Error> { LanguageParser::parse(Rule::file, input) } -fn span_into_string(span: Span) -> String { +pub fn span_into_string(span: Span) -> String { span.as_str().to_string() } - -// Visibility - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::visibility_public))] -pub struct Public {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::visibility_private))] -pub struct Private {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::visibility))] -pub enum Visibility { - Public(Public), - Private(Private), -} - -// Types - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_field))] -pub struct FieldType {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_group))] -pub struct GroupType {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_boolean))] -pub struct BooleanType {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_data))] -pub enum DataType { - Integer(IntegerType), - Field(FieldType), - Group(GroupType), - Boolean(BooleanType), -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_circuit))] -pub struct CircuitType<'ast> { - pub variable: Identifier<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_array))] -pub struct ArrayType<'ast> { - pub _type: DataType, - pub dimensions: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::_type))] -pub enum Type<'ast> { - Data(DataType), - Array(ArrayType<'ast>), - Circuit(CircuitType<'ast>), -} - -// Values - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_number))] -pub struct NumberValue<'ast> { - #[pest_ast(outer(with(span_into_string)))] - pub value: String, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_field))] -pub struct FieldValue<'ast> { - pub number: NumberValue<'ast>, - pub _type: FieldType, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_group))] -pub struct GroupValue<'ast> { - pub value: GroupRepresentation<'ast>, - pub _type: GroupType, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::group_single_or_tuple))] -pub enum GroupRepresentation<'ast> { - Single(NumberValue<'ast>), - Tuple(GroupTuple<'ast>), -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::group_tuple))] -pub struct GroupTuple<'ast> { - pub x: NumberValue<'ast>, - pub y: NumberValue<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_boolean))] -pub struct BooleanValue<'ast> { - #[pest_ast(outer(with(span_into_string)))] - pub value: String, - #[pest_ast(outer())] - pub span: Span<'ast>, -} -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_integer))] -pub enum IntegerType { - U8Type(U8Type), - U16Type(U16Type), - U32Type(U32Type), - U64Type(U64Type), - U128Type(U128Type), -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u8))] -pub struct U8Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u16))] -pub struct U16Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u32))] -pub struct U32Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u64))] -pub struct U64Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::type_u128))] -pub struct U128Type {} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_integer))] -pub struct IntegerValue<'ast> { - pub number: NumberValue<'ast>, - pub _type: IntegerType, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value_implicit))] -pub struct NumberImplicitValue<'ast> { - pub number: NumberValue<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::value))] -pub enum Value<'ast> { - Integer(IntegerValue<'ast>), - Field(FieldValue<'ast>), - Group(GroupValue<'ast>), - Boolean(BooleanValue<'ast>), - Implicit(NumberImplicitValue<'ast>), -} -// Identifier - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::identifier))] -pub struct Identifier<'ast> { - #[pest_ast(outer(with(span_into_string)))] - pub value: String, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Arrays - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression_array_inline))] -pub struct ArrayInlineExpression<'ast> { - pub expressions: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression_array_initializer))] -pub struct ArrayInitializerExpression<'ast> { - pub expression: Box>, - pub count: Value<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Circuits - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::circuit_field))] -pub struct CircuitField<'ast> { - pub variable: Identifier<'ast>, - pub expression: Expression<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression_circuit_inline))] -pub struct CircuitInlineExpression<'ast> { - pub variable: Identifier<'ast>, - pub members: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Expressions - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expression))] -pub enum Expression<'ast> { - CircuitInline(CircuitInlineExpression<'ast>), - ArrayInline(ArrayInlineExpression<'ast>), - ArrayInitializer(ArrayInitializerExpression<'ast>), - Value(Value<'ast>), - Variable(Identifier<'ast>), -} - -// Parameters - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::parameter))] -pub struct Parameter<'ast> { - pub variable: Identifier<'ast>, - pub visibility: Option, - pub _type: Type<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Sections - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::section))] -pub struct Section<'ast> { - pub header: Header<'ast>, - pub assignments: Vec>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::header))] -pub struct Header<'ast> { - pub name: Identifier<'ast>, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::assignment))] -pub struct Assignment<'ast> { - pub parameter: Parameter<'ast>, - pub expression: Expression<'ast>, - pub line_end: LineEnd, - #[pest_ast(outer())] - pub span: Span<'ast>, -} - -// Utilities - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::EOI))] -pub struct EOI; - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::LINE_END))] -pub struct LineEnd; - -// File - -#[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::file))] -pub struct File<'ast> { - pub sections: Vec>, - pub eoi: EOI, - #[pest_ast(outer())] - pub span: Span<'ast>, -} diff --git a/leo-inputs/src/circuits/circuit_field.rs b/leo-inputs/src/circuits/circuit_field.rs new file mode 100644 index 0000000000..0c48dec655 --- /dev/null +++ b/leo-inputs/src/circuits/circuit_field.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, common::Identifier, expressions::Expression}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::circuit_field))] +pub struct CircuitField<'ast> { + pub identifier: Identifier<'ast>, + pub expression: Expression<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/circuits/mod.rs b/leo-inputs/src/circuits/mod.rs new file mode 100644 index 0000000000..5b7ea46f55 --- /dev/null +++ b/leo-inputs/src/circuits/mod.rs @@ -0,0 +1,4 @@ + +pub mod circuit_field; +pub use circuit_field::*; + diff --git a/leo-inputs/src/common/eoi.rs b/leo-inputs/src/common/eoi.rs new file mode 100644 index 0000000000..1293320f1a --- /dev/null +++ b/leo-inputs/src/common/eoi.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::EOI))] +pub struct EOI; diff --git a/leo-inputs/src/common/identifier.rs b/leo-inputs/src/common/identifier.rs new file mode 100644 index 0000000000..35c74e30be --- /dev/null +++ b/leo-inputs/src/common/identifier.rs @@ -0,0 +1,20 @@ +use crate::ast::{span_into_string, Rule}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::identifier))] +pub struct Identifier<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for Identifier<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} diff --git a/leo-inputs/src/common/line_end.rs b/leo-inputs/src/common/line_end.rs new file mode 100644 index 0000000000..ee34060bd6 --- /dev/null +++ b/leo-inputs/src/common/line_end.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::LINE_END))] +pub struct LineEnd; diff --git a/leo-inputs/src/common/mod.rs b/leo-inputs/src/common/mod.rs new file mode 100644 index 0000000000..b0b7155373 --- /dev/null +++ b/leo-inputs/src/common/mod.rs @@ -0,0 +1,11 @@ +pub mod eoi; +pub use eoi::*; + +pub mod identifier; +pub use identifier::*; + +pub mod line_end; +pub use line_end::*; + +pub mod visibility; +pub use visibility::*; diff --git a/leo-inputs/src/common/visibility.rs b/leo-inputs/src/common/visibility.rs new file mode 100644 index 0000000000..cd63bb1119 --- /dev/null +++ b/leo-inputs/src/common/visibility.rs @@ -0,0 +1,18 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility))] +pub enum Visibility { + Public(Public), + Private(Private), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility_public))] +pub struct Public {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::visibility_private))] +pub struct Private {} diff --git a/leo-inputs/src/errors/syntax.rs b/leo-inputs/src/errors/syntax.rs index 358a23af85..a436ec15b1 100644 --- a/leo-inputs/src/errors/syntax.rs +++ b/leo-inputs/src/errors/syntax.rs @@ -17,7 +17,7 @@ impl From> for SyntaxError { Rule::type_group => "`group`".to_owned(), Rule::file => "an import, circuit, or function".to_owned(), Rule::identifier => "a variable name".to_owned(), - Rule::_type => "a type".to_owned(), + Rule::type_ => "a type".to_owned(), rule => format!("{:?}", rule), }); diff --git a/leo-inputs/src/expressions/array_initializer_expression.rs b/leo-inputs/src/expressions/array_initializer_expression.rs new file mode 100644 index 0000000000..37ebc032d5 --- /dev/null +++ b/leo-inputs/src/expressions/array_initializer_expression.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, expressions::Expression, values::Value}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_array_initializer))] +pub struct ArrayInitializerExpression<'ast> { + pub expression: Box>, + pub count: Value<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/expressions/array_inline_expression.rs b/leo-inputs/src/expressions/array_inline_expression.rs new file mode 100644 index 0000000000..bb25e12721 --- /dev/null +++ b/leo-inputs/src/expressions/array_inline_expression.rs @@ -0,0 +1,12 @@ +use crate::{ast::Rule, expressions::Expression}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_array_inline))] +pub struct ArrayInlineExpression<'ast> { + pub expressions: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/expressions/circuit_inline_expression.rs b/leo-inputs/src/expressions/circuit_inline_expression.rs new file mode 100644 index 0000000000..52d8b99983 --- /dev/null +++ b/leo-inputs/src/expressions/circuit_inline_expression.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, circuits::CircuitField, common::Identifier,}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression_circuit_inline))] +pub struct CircuitInlineExpression<'ast> { + pub identifier: Identifier<'ast>, + pub members: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/expressions/expression.rs b/leo-inputs/src/expressions/expression.rs new file mode 100644 index 0000000000..af8f20a4ea --- /dev/null +++ b/leo-inputs/src/expressions/expression.rs @@ -0,0 +1,40 @@ +use crate::{ast::Rule, common::Identifier, expressions::*, values::Value,}; + +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expression))] +pub enum Expression<'ast> { + CircuitInline(CircuitInlineExpression<'ast>), + ArrayInline(ArrayInlineExpression<'ast>), + ArrayInitializer(ArrayInitializerExpression<'ast>), + Value(Value<'ast>), + Variable(Identifier<'ast>), +} + +impl<'ast> fmt::Display for Expression<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Expression::Value(ref expression) => write!(f, "{}", expression), + Expression::Variable(ref expression) => write!(f, "{}", expression), + Expression::ArrayInline(ref expression) => { + for (i, spread_or_expression) in expression.expressions.iter().enumerate() { + write!(f, "{}", spread_or_expression)?; + if i < expression.expressions.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, "") + } + Expression::ArrayInitializer(ref expression) => { + write!(f, "[{} ; {}]", expression.expression, expression.count) + } + Expression::CircuitInline(ref expression) => write!( + f, + "inline circuit display not impl {}", + expression.identifier + ), + } + } +} diff --git a/leo-inputs/src/expressions/mod.rs b/leo-inputs/src/expressions/mod.rs new file mode 100644 index 0000000000..f79e25ae50 --- /dev/null +++ b/leo-inputs/src/expressions/mod.rs @@ -0,0 +1,11 @@ +pub mod array_initializer_expression; +pub use array_initializer_expression::*; + +pub mod array_inline_expression; +pub use array_inline_expression::*; + +pub mod circuit_inline_expression; +pub use circuit_inline_expression::*; + +pub mod expression; +pub use expression::*; \ No newline at end of file diff --git a/leo-inputs/src/files/file.rs b/leo-inputs/src/files/file.rs new file mode 100644 index 0000000000..48f720d841 --- /dev/null +++ b/leo-inputs/src/files/file.rs @@ -0,0 +1,13 @@ +use crate::{ast::{Rule}, common::EOI, sections::Section }; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::file))] +pub struct File<'ast> { + pub sections: Vec>, + pub eoi: EOI, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/files/mod.rs b/leo-inputs/src/files/mod.rs new file mode 100644 index 0000000000..de03a628a4 --- /dev/null +++ b/leo-inputs/src/files/mod.rs @@ -0,0 +1,2 @@ +pub mod file; +pub use file::*; diff --git a/leo-inputs/src/leo-inputs.pest b/leo-inputs/src/leo-inputs.pest index 90f76c96e8..73ef11cbe5 100644 --- a/leo-inputs/src/leo-inputs.pest +++ b/leo-inputs/src/leo-inputs.pest @@ -1,20 +1,23 @@ /// Common -file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI } - +// Declared in common/identifier.rs identifier = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } protected_name = { visibility | "let" | "for"| "if" | "else" | "as" | "return" } - +// Declared in common/line_end.rs LINE_END = { ";" ~ NEWLINE* } +// Declared in common/visibility.rs visibility = { visibility_public | visibility_private } visibility_public = { "public" } visibility_private = { "private" } /// Types -_type = { type_array | type_data | type_circuit } +// Declared in types/type_.rs +type_ = { type_array | type_data | type_circuit } + +// Declared in types/integer_type.rs type_integer = { type_u8 | type_u16 @@ -28,47 +31,64 @@ type_u32 = { "u32" } type_u64 = { "u64" } type_u128 = { "u128" } +// Declared in types/field_type.rs type_field = { "field" } +// Declared in types/group_type.rs type_group = { "group" } +// Declared in types/boolean_type.rs type_boolean = { "bool" } +// Declared in types/data_type.rs type_data = { type_field | type_group | type_boolean | type_integer } +// Declared in types/circuit_type.rs type_circuit = { identifier } +// Declared in types/array_type.rs type_array = { type_data ~ ("[" ~ value ~ "]")+ } /// Values +// Declared in values/value.rs value = { value_field | value_group | value_boolean | value_integer | value_implicit } +// Declared in values/number_value.rs value_number = @{ "0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* } +// Declared in values/number_implicit_value.rs value_implicit = { value_number } +// Declared in values/integer_value.rs value_integer = { value_number ~ type_integer } +// Declared in values/boolean_value.rs value_boolean = { "true" | "false" } +// Declared in values/field_value.rs value_field = { value_number ~ type_field } +// Declared in values/group_value.rs value_group = { group_single_or_tuple ~ type_group } group_tuple = { "(" ~ NEWLINE* ~ value_number ~ "," ~ NEWLINE* ~ value_number ~ NEWLINE* ~")" } group_single_or_tuple = { value_number | group_tuple } /// Expressions +// Declared in expressions/array_initializer_expression.rs expression_array_initializer = { "[" ~ expression ~ ";" ~ value ~ "]" } +// Declared in expressions/array_inline_expression.rs expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"} inline_array_inner = _{ (expression ~ ("," ~ NEWLINE* ~ expression)*)? } +// Declared in expressions/circuit_inline_expression.rs expression_circuit_inline = { identifier ~ "{" ~ NEWLINE* ~ circuit_field_list ~ NEWLINE* ~ "}" } circuit_field = { identifier ~ ":" ~ expression } circuit_field_list = _{ (circuit_field ~ ("," ~ NEWLINE* ~ circuit_field)*)? ~ ","? } +// Declared in expressions/expression.rs expression = { expression_circuit_inline | expression_array_inline @@ -79,14 +99,20 @@ expression = { /// Parameters -parameter = { identifier ~ ":" ~ visibility? ~ _type } +// Declared in parameters/parameters.rs +parameter = { identifier ~ ":" ~ visibility? ~ type_ } /// Section +// Declared in sections/section.rs section = { header ~ NEWLINE+ ~ (assignment ~ NEWLINE*)* } +// Declared in sections/header.rs header = { "[" ~ identifier ~ "]" } +/// Assignments + +// Declared in assignment/assignment.rs assignment = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } /// Utilities @@ -94,4 +120,7 @@ assignment = { parameter ~ "=" ~ NEWLINE* ~ expression ~ LINE_END } COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) } WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* } +/// Files +// Declared in files/file.rs +file = { SOI ~ NEWLINE* ~ section* ~ NEWLINE* ~ EOI } diff --git a/leo-inputs/src/lib.rs b/leo-inputs/src/lib.rs index 156b7890e1..1c8a339458 100644 --- a/leo-inputs/src/lib.rs +++ b/leo-inputs/src/lib.rs @@ -8,6 +8,15 @@ pub use errors::*; //extern crate from_pest; mod ast; +pub mod assignments; +pub mod circuits; +pub mod common; +pub mod expressions; +pub mod files; +pub mod parameters; +pub mod sections; +pub mod types; +pub mod values; use from_pest::FromPest; use std::{fs, path::PathBuf}; @@ -25,14 +34,14 @@ impl LeoInputsParser { pub fn parse_file<'a>( file_path: &'a PathBuf, input_file: &'a str, - ) -> Result, ParserError> { + ) -> Result, ParserError> { // Parse the file using leo.pest let mut file = ast::parse(input_file) .map_err(|error| ParserError::from(error.with_path(file_path.to_str().unwrap())))?; // Build the abstract syntax tree let syntax_tree = - ast::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?; + files::File::from_pest(&mut file).map_err(|_| ParserError::SyntaxTreeError)?; // println!("{:?}", syntax_tree); Ok(syntax_tree) diff --git a/leo-inputs/src/parameters/mod.rs b/leo-inputs/src/parameters/mod.rs new file mode 100644 index 0000000000..861bb16a1a --- /dev/null +++ b/leo-inputs/src/parameters/mod.rs @@ -0,0 +1,2 @@ +pub mod parameter; +pub use parameter::*; \ No newline at end of file diff --git a/leo-inputs/src/parameters/parameter.rs b/leo-inputs/src/parameters/parameter.rs new file mode 100644 index 0000000000..ee4469eac0 --- /dev/null +++ b/leo-inputs/src/parameters/parameter.rs @@ -0,0 +1,14 @@ +use crate::{ast::Rule, common::{Identifier, Visibility}, types::Type}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::parameter))] +pub struct Parameter<'ast> { + pub variable: Identifier<'ast>, + pub visibility: Option, + pub _type: Type<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} \ No newline at end of file diff --git a/leo-inputs/src/sections/header.rs b/leo-inputs/src/sections/header.rs new file mode 100644 index 0000000000..3805431def --- /dev/null +++ b/leo-inputs/src/sections/header.rs @@ -0,0 +1,12 @@ +use crate::{ast::Rule, common::Identifier}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::header))] +pub struct Header<'ast> { + pub name: Identifier<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} \ No newline at end of file diff --git a/leo-inputs/src/sections/mod.rs b/leo-inputs/src/sections/mod.rs new file mode 100644 index 0000000000..2ed80e53e5 --- /dev/null +++ b/leo-inputs/src/sections/mod.rs @@ -0,0 +1,5 @@ +pub mod header; +pub use header::*; + +pub mod section; +pub use section::*; \ No newline at end of file diff --git a/leo-inputs/src/sections/section.rs b/leo-inputs/src/sections/section.rs new file mode 100644 index 0000000000..c12ad67db6 --- /dev/null +++ b/leo-inputs/src/sections/section.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, sections::Header, assignments::Assignment}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::section))] +pub struct Section<'ast> { + pub header: Header<'ast>, + pub assignments: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} \ No newline at end of file diff --git a/leo-inputs/src/types/array_type.rs b/leo-inputs/src/types/array_type.rs new file mode 100644 index 0000000000..01650cdfb3 --- /dev/null +++ b/leo-inputs/src/types/array_type.rs @@ -0,0 +1,13 @@ +use crate::{ast::Rule, types::DataType, values::Value}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_array))] +pub struct ArrayType<'ast> { + pub _type: DataType, + pub dimensions: Vec>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} diff --git a/leo-inputs/src/types/boolean_type.rs b/leo-inputs/src/types/boolean_type.rs new file mode 100644 index 0000000000..9abd021ffa --- /dev/null +++ b/leo-inputs/src/types/boolean_type.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_boolean))] +pub struct BooleanType {} diff --git a/leo-inputs/src/types/circuit_type.rs b/leo-inputs/src/types/circuit_type.rs new file mode 100644 index 0000000000..8b87935568 --- /dev/null +++ b/leo-inputs/src/types/circuit_type.rs @@ -0,0 +1,12 @@ +use crate::{ast::Rule, common::Identifier}; + +use pest::Span; +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_circuit))] +pub struct CircuitType<'ast> { + pub identifier: Identifier<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} \ No newline at end of file diff --git a/leo-inputs/src/types/data_type.rs b/leo-inputs/src/types/data_type.rs new file mode 100644 index 0000000000..8cf3a0f75c --- /dev/null +++ b/leo-inputs/src/types/data_type.rs @@ -0,0 +1,12 @@ +use crate::{ast::Rule, types::{IntegerType, FieldType, GroupType, BooleanType}}; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_data))] +pub enum DataType { + Integer(IntegerType), + Field(FieldType), + Group(GroupType), + Boolean(BooleanType), +} \ No newline at end of file diff --git a/leo-inputs/src/types/field_type.rs b/leo-inputs/src/types/field_type.rs new file mode 100644 index 0000000000..64d12a67ab --- /dev/null +++ b/leo-inputs/src/types/field_type.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_field))] +pub struct FieldType {} \ No newline at end of file diff --git a/leo-inputs/src/types/group_type.rs b/leo-inputs/src/types/group_type.rs new file mode 100644 index 0000000000..c099ab778a --- /dev/null +++ b/leo-inputs/src/types/group_type.rs @@ -0,0 +1,7 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_group))] +pub struct GroupType {} diff --git a/leo-inputs/src/types/integer_type.rs b/leo-inputs/src/types/integer_type.rs new file mode 100644 index 0000000000..6d74555f09 --- /dev/null +++ b/leo-inputs/src/types/integer_type.rs @@ -0,0 +1,33 @@ +use crate::ast::Rule; + +use pest_ast::FromPest; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_integer))] +pub enum IntegerType { + U8Type(U8Type), + U16Type(U16Type), + U32Type(U32Type), + U64Type(U64Type), + U128Type(U128Type), +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u8))] +pub struct U8Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u16))] +pub struct U16Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u32))] +pub struct U32Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u64))] +pub struct U64Type {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_u128))] +pub struct U128Type {} diff --git a/leo-inputs/src/types/mod.rs b/leo-inputs/src/types/mod.rs new file mode 100644 index 0000000000..cd0d08ac60 --- /dev/null +++ b/leo-inputs/src/types/mod.rs @@ -0,0 +1,23 @@ +pub mod array_type; +pub use array_type::*; + +pub mod boolean_type; +pub use boolean_type::*; + +pub mod circuit_type; +pub use circuit_type::*; + +pub mod data_type; +pub use data_type::*; + +pub mod field_type; +pub use field_type::*; + +pub mod group_type; +pub use group_type::*; + +pub mod integer_type; +pub use integer_type::*; + +pub mod type_; +pub use type_::*; diff --git a/leo-inputs/src/types/type_.rs b/leo-inputs/src/types/type_.rs new file mode 100644 index 0000000000..ddf650563d --- /dev/null +++ b/leo-inputs/src/types/type_.rs @@ -0,0 +1,22 @@ +use crate::{ast::Rule, types::*}; + +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::type_))] +pub enum Type<'ast> { + Basic(DataType), + Array(ArrayType<'ast>), + Circuit(CircuitType<'ast>), +} + +impl<'ast> fmt::Display for Type<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Type::Basic(ref _type) => write!(f, "basic"), + Type::Array(ref _type) => write!(f, "array"), + Type::Circuit(ref _type) => write!(f, "struct"), + } + } +} diff --git a/leo-inputs/src/values/boolean_value.rs b/leo-inputs/src/values/boolean_value.rs new file mode 100644 index 0000000000..43f1c71060 --- /dev/null +++ b/leo-inputs/src/values/boolean_value.rs @@ -0,0 +1,20 @@ +use crate::ast::{Rule, span_into_string}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_boolean))] +pub struct BooleanValue<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for BooleanValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} diff --git a/leo-inputs/src/values/field_value.rs b/leo-inputs/src/values/field_value.rs new file mode 100644 index 0000000000..716aa44a3b --- /dev/null +++ b/leo-inputs/src/values/field_value.rs @@ -0,0 +1,20 @@ +use crate::{ast::Rule, types::FieldType, values::NumberValue,}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_field))] +pub struct FieldValue<'ast> { + pub number: NumberValue<'ast>, + pub _type: FieldType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for FieldValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.number) + } +} diff --git a/leo-inputs/src/values/group_value.rs b/leo-inputs/src/values/group_value.rs new file mode 100644 index 0000000000..78250cd6dc --- /dev/null +++ b/leo-inputs/src/values/group_value.rs @@ -0,0 +1,51 @@ +use crate::{ast::Rule, types::GroupType, values::NumberValue,}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_group))] +pub struct GroupValue<'ast> { + pub value: GroupRepresentation<'ast>, + pub _type: GroupType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for GroupValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::group_single_or_tuple))] +pub enum GroupRepresentation<'ast> { + Single(NumberValue<'ast>), + Tuple(GroupTuple<'ast>), +} + +impl<'ast> fmt::Display for GroupRepresentation<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + GroupRepresentation::Single(number) => write!(f, "{}", number), + GroupRepresentation::Tuple(tuple) => write!(f, "{}", tuple), + } + } +} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::group_tuple))] +pub struct GroupTuple<'ast> { + pub x: NumberValue<'ast>, + pub y: NumberValue<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for GroupTuple<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({}, {})", self.x, self.y) + } +} diff --git a/leo-inputs/src/values/integer_value.rs b/leo-inputs/src/values/integer_value.rs new file mode 100644 index 0000000000..141cb9aab6 --- /dev/null +++ b/leo-inputs/src/values/integer_value.rs @@ -0,0 +1,20 @@ +use crate::{ast::Rule, types::IntegerType, values::NumberValue}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_integer))] +pub struct IntegerValue<'ast> { + pub number: NumberValue<'ast>, + pub _type: IntegerType, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for IntegerValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.number) + } +} diff --git a/leo-inputs/src/values/mod.rs b/leo-inputs/src/values/mod.rs new file mode 100644 index 0000000000..87090f0ffa --- /dev/null +++ b/leo-inputs/src/values/mod.rs @@ -0,0 +1,20 @@ +pub mod boolean_value; +pub use boolean_value::*; + +pub mod field_value; +pub use field_value::*; + +pub mod group_value; +pub use group_value::*; + +pub mod integer_value; +pub use integer_value::*; + +pub mod number_implicit_value; +pub use number_implicit_value::*; + +pub mod number_value; +pub use number_value::*; + +pub mod value; +pub use value::*; diff --git a/leo-inputs/src/values/number_implicit_value.rs b/leo-inputs/src/values/number_implicit_value.rs new file mode 100644 index 0000000000..0aae2cc51e --- /dev/null +++ b/leo-inputs/src/values/number_implicit_value.rs @@ -0,0 +1,19 @@ +use crate::{ast::Rule, values::NumberValue}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_implicit))] +pub struct NumberImplicitValue<'ast> { + pub number: NumberValue<'ast>, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for NumberImplicitValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.number) + } +} diff --git a/leo-inputs/src/values/number_value.rs b/leo-inputs/src/values/number_value.rs new file mode 100644 index 0000000000..0401d56d7b --- /dev/null +++ b/leo-inputs/src/values/number_value.rs @@ -0,0 +1,20 @@ +use crate::ast::{Rule, span_into_string}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value_number))] +pub struct NumberValue<'ast> { + #[pest_ast(outer(with(span_into_string)))] + pub value: String, + #[pest_ast(outer())] + pub span: Span<'ast>, +} + +impl<'ast> fmt::Display for NumberValue<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} \ No newline at end of file diff --git a/leo-inputs/src/values/value.rs b/leo-inputs/src/values/value.rs new file mode 100644 index 0000000000..c1b869241c --- /dev/null +++ b/leo-inputs/src/values/value.rs @@ -0,0 +1,39 @@ +use crate::{ast::Rule, values::{BooleanValue, IntegerValue, FieldValue, GroupValue, NumberImplicitValue}}; + +use pest::Span; +use pest_ast::FromPest; +use std::fmt; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::value))] +pub enum Value<'ast> { + Integer(IntegerValue<'ast>), + Field(FieldValue<'ast>), + Group(GroupValue<'ast>), + Boolean(BooleanValue<'ast>), + Implicit(NumberImplicitValue<'ast>), +} + +impl<'ast> Value<'ast> { + pub fn span(&self) -> &Span<'ast> { + match self { + Value::Integer(value) => &value.span, + Value::Field(value) => &value.span, + Value::Group(value) => &value.span, + Value::Boolean(value) => &value.span, + Value::Implicit(value) => &value.span, + } + } +} + +impl<'ast> fmt::Display for Value<'ast> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Value::Integer(ref value) => write!(f, "{}", value), + Value::Field(ref value) => write!(f, "{}", value), + Value::Group(ref value) => write!(f, "{}", value), + Value::Boolean(ref value) => write!(f, "{}", value), + Value::Implicit(ref value) => write!(f, "{}", value), + } + } +}