Skip to content

Commit a297ec6

Browse files
Thunkarjfecher
andauthored
feat: Add Quoted::tokens (#5942)
# Description ## Problem\* While `fmtstr.quoted_contents` is great for 99% of use cases, sometimes the raw str (including double quotes) is needed. Consider this case (fn signature generation in `aztec.nr`) ```noir pub(crate) comptime fn compute_fn_selector(f: FunctionDefinition) -> Field { let fn_name = f.name(); let args_signatures = f.parameters().map( | (_, typ): (Quoted, Type) | { signature_of_type(typ) } ).join(quote {,}); let signature = f"{fn_name}({args_signatures})".quoted_contents(); // from_signature takes a str, quoted_contents is no good here! let computation_quote = quote { protocol_types::abis::function_selector::FunctionSelector::from_signature($signature).to_field() }; unquote!(computation_quote) } ``` We have a bunch of `Quoted` values obtained during comptime that we have to string (ha) together. The result is then needed to compute a hash. ## Summary\* ~~This just adds a builtin that "resolves" the `fmtstr` and then turns it into a `Token::Str`~~ It's possible to create a string from quoted values by doing: ```noir let signature = f"{name}({args})"; let signature_as_str = unquote!(quote { $signature }); ``` But this includes whitespaces around the tokens. To get rid of them, ended up going with the approach suggested by @jfecher, which certainly complicates user code, but avoids the "eating whitespaces" problem: > Going forward I think we'll need to instead control the formatting of Quoted values more. The compiler itself can never guess what exact formatting users will want of them since spaces are already not present. So I'm leaning towards a Quoted::tokens(self) -> [Quoted] method to return a slice of each individual token in the Quoted value. Then users could iterate over it and apply (or not apply) spacing in between each token as they see fit. Also, the returned values are `str<_>`, since the compiler has no idea of the returned length after formatting. This means values can only be used by unquoting them and not directly. ## Additional Context My first intuition was to do ```noir let signature = f"\"{quotedvalues}\"" ``` But it doesn't work =/ ## Documentation\* Check one: - [ ] No documentation needed. - [x] Documentation included in this PR. - [ ] **[For Experimental Features]** Documentation to be submitted in a separate PR. # PR Checklist\* - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: jfecher <[email protected]>
1 parent b84009c commit a297ec6

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ impl<'local, 'context> Interpreter<'local, 'context> {
123123
"quoted_as_trait_constraint" => quoted_as_trait_constraint(self, arguments, location),
124124
"quoted_as_type" => quoted_as_type(self, arguments, location),
125125
"quoted_eq" => quoted_eq(arguments, location),
126+
"quoted_tokens" => quoted_tokens(arguments, location),
126127
"slice_insert" => slice_insert(interner, arguments, location),
127128
"slice_pop_back" => slice_pop_back(interner, arguments, location, call_stack),
128129
"slice_pop_front" => slice_pop_front(interner, arguments, location, call_stack),
@@ -535,6 +536,17 @@ fn quoted_as_type(
535536
Ok(Value::Type(typ))
536537
}
537538

539+
// fn tokens(quoted: Quoted) -> [Quoted]
540+
fn quoted_tokens(arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
541+
let argument = check_one_argument(arguments, location)?;
542+
let value = get_quoted(argument)?;
543+
544+
Ok(Value::Slice(
545+
value.iter().map(|token| Value::Quoted(Rc::new(vec![token.clone()]))).collect(),
546+
Type::Slice(Box::new(Type::Quoted(QuotedType::Quoted))),
547+
))
548+
}
549+
538550
fn to_le_radix(
539551
arguments: Vec<(Value, Location)>,
540552
return_type: Type,

docs/docs/noir/standard_library/meta/quoted.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ stream doesn't parse to a type or if the type isn't a valid type in scope.
5050

5151
#include_code implements_example test_programs/compile_success_empty/comptime_type/src/main.nr rust
5252

53+
### tokens
54+
55+
#include_code tokens noir_stdlib/src/meta/quoted.nr rust
56+
57+
Returns a slice of the individual tokens that form this token stream.
58+
5359
## Trait Implementations
5460

5561
```rust

noir_stdlib/src/meta/quoted.nr

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,29 @@ use crate::option::Option;
33

44
impl Quoted {
55
#[builtin(quoted_as_expr)]
6-
// docs:start:as_expr
6+
// docs:start:as_expr
77
fn as_expr(self) -> Option<Expr> {}
88
// docs:end:as_expr
99

1010
#[builtin(quoted_as_module)]
11-
// docs:start:as_module
11+
// docs:start:as_module
1212
fn as_module(self) -> Option<Module> {}
1313
// docs:end:as_module
1414

1515
#[builtin(quoted_as_trait_constraint)]
16-
// docs:start:as_trait_constraint
16+
// docs:start:as_trait_constraint
1717
fn as_trait_constraint(self) -> TraitConstraint {}
1818
// docs:end:as_trait_constraint
1919

2020
#[builtin(quoted_as_type)]
21-
// docs:start:as_type
21+
// docs:start:as_type
2222
fn as_type(self) -> Type {}
2323
// docs:end:as_type
24+
25+
#[builtin(quoted_tokens)]
26+
// docs:start:tokens
27+
fn tokens(self) -> [Quoted] {}
28+
// docs:end:tokens
2429
}
2530

2631
impl Eq for Quoted {

0 commit comments

Comments
 (0)