-
Notifications
You must be signed in to change notification settings - Fork 530
/
print.rs
145 lines (134 loc) · 4.6 KB
/
print.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use cairo_lang_defs::patcher::{PatchBuilder, RewriteNode};
use cairo_lang_defs::plugin::{
InlineMacroExprPlugin, InlinePluginResult, MacroPluginMetadata, NamedPlugin,
PluginGeneratedFile,
};
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::helpers::WrappedArgListHelper;
use cairo_lang_syntax::node::{TypedSyntaxNode, ast};
use indoc::{formatdoc, indoc};
use super::write::{WriteMacro, WritelnMacro};
/// Macro for printing.
#[derive(Debug, Default)]
pub struct PrintMacro;
impl NamedPlugin for PrintMacro {
const NAME: &'static str = "print";
}
impl InlineMacroExprPlugin for PrintMacro {
fn generate_code(
&self,
db: &dyn SyntaxGroup,
syntax: &ast::ExprInlineMacro,
_metadata: &MacroPluginMetadata<'_>,
) -> InlinePluginResult {
generate_code_inner(syntax, db, false)
}
fn documentation(&self) -> Option<String> {
Some(
indoc! {r#"
Prints to the standard output.
Equivalent to the `println!` macro except that a newline is not printed at the end of \
the message.
# Panics
Panics if any of the formatting of arguments fails.
# Examples
```cairo
println!(\"hello\"); // Prints "hello".
let world: ByteArray = "world";
println!("hello {}", world_ba); // Prints "hello world".
println!("hello {world_ba}"); // Prints "hello world".
```
"#}
.to_string(),
)
}
}
/// Macro for printing with a new line.
#[derive(Debug, Default)]
pub struct PrintlnMacro;
impl NamedPlugin for PrintlnMacro {
const NAME: &'static str = "println";
}
impl InlineMacroExprPlugin for PrintlnMacro {
fn generate_code(
&self,
db: &dyn SyntaxGroup,
syntax: &ast::ExprInlineMacro,
_metadata: &MacroPluginMetadata<'_>,
) -> InlinePluginResult {
generate_code_inner(syntax, db, true)
}
fn documentation(&self) -> Option<String> {
Some(
indoc! {r#"
Prints to the standard output, with a newline.
This macro uses the same syntax as `format!`, but writes to the standard output instead.
# Panics
Panics if any of the formatting of arguments fails.
# Examples
```cairo
println!(); // Prints an empty line.
println!(\"hello\"); // Prints "hello".
let world: ByteArray = "world";
println!("hello {}", world_ba); // Prints "hello world".
println!("hello {world_ba}"); // Prints "hello world".
```
"#}
.to_string(),
)
}
}
fn generate_code_inner(
syntax: &ast::ExprInlineMacro,
db: &dyn SyntaxGroup,
with_newline: bool,
) -> InlinePluginResult {
let arguments = syntax.arguments(db);
let mut builder = PatchBuilder::new(db, syntax);
builder.add_modified(RewriteNode::interpolate_patched(
&formatdoc! {
"
{{
let mut {f}: core::fmt::Formatter = core::traits::Default::default();
core::result::ResultTrait::<(), core::fmt::Error>::unwrap(
{write_func}!$left_bracket${f}, $args$$right_bracket$
);
core::debug::print_byte_array_as_string(@{f}.buffer);
}}
",
f = "__formatter_for_print_macros__",
write_func = if with_newline { WritelnMacro::NAME } else { WriteMacro::NAME },
},
&[
(
"left_bracket".to_string(),
RewriteNode::new_trimmed(arguments.left_bracket_syntax_node(db)),
),
(
"right_bracket".to_string(),
RewriteNode::new_trimmed(arguments.right_bracket_syntax_node(db)),
),
(
"args".to_string(),
arguments.arg_list(db).map_or_else(RewriteNode::empty, |n| {
RewriteNode::new_trimmed(n.as_syntax_node())
}),
),
]
.into(),
));
let (content, code_mappings) = builder.build();
InlinePluginResult {
code: Some(PluginGeneratedFile {
name: format!("{}_macro", get_macro_name(with_newline)).into(),
content,
code_mappings,
aux_data: None,
}),
diagnostics: vec![],
}
}
/// Gets the macro name according to the `with_newline` flag.
fn get_macro_name(with_newline: bool) -> &'static str {
if with_newline { PrintlnMacro::NAME } else { PrintMacro::NAME }
}