Updating submodules
[hiphop-php.git] / hphp / hack / src / hackc / bytecode_printer / context.rs
blobc17a76f38c8d7beda01e6636dcc08a391841635b
1 // Copyright (c) Facebook, Inc. and its affiliates.
2 //
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
6 use std::fmt;
7 use std::io::Result;
8 use std::io::Write;
10 use relative_path::RelativePath;
12 /// Indent is an abstraction of indentation. Configurable indentation
13 /// and perf tweaking will be easier.
14 #[derive(Clone)]
15 struct Indent(usize);
17 impl Indent {
18     fn new() -> Self {
19         Self(0)
20     }
22     fn inc(&mut self) {
23         self.0 += 1;
24     }
26     fn dec(&mut self) {
27         self.0 -= 1;
28     }
31 impl fmt::Display for Indent {
32     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33         for _ in 0..self.0 {
34             f.write_str("  ")?;
35         }
36         Ok(())
37     }
40 #[derive(Clone)]
41 pub struct Context<'a> {
42     pub(crate) path: Option<&'a RelativePath>,
43     indent: Indent,
46 impl<'a> Context<'a> {
47     pub fn new(path: Option<&'a RelativePath>) -> Self {
48         Self {
49             path,
50             indent: Indent::new(),
51         }
52     }
54     /// Insert a newline with indentation
55     pub(crate) fn newline(&self, w: &mut dyn Write) -> Result<()> {
56         write!(w, "\n{}", self.indent)
57     }
59     /// Start a new indented block
60     pub(crate) fn block<F>(&self, w: &mut dyn Write, f: F) -> Result<()>
61     where
62         F: FnOnce(&Self, &mut dyn Write) -> Result<()>,
63     {
64         let mut ctx = self.clone();
65         ctx.indent.inc();
66         f(&ctx, w)
67     }
69     pub(crate) fn unblock<F>(&self, w: &mut dyn Write, f: F) -> Result<()>
70     where
71         F: FnOnce(&Self, &mut dyn Write) -> Result<()>,
72     {
73         let mut ctx = self.clone();
74         ctx.indent.dec();
75         f(&ctx, w)
76     }
78     /// Printing instruction list requires manually control indentation,
79     /// where indent_inc/indent_dec are called
80     pub(crate) fn indent_inc(&mut self) {
81         self.indent.inc();
82     }
84     pub(crate) fn indent_dec(&mut self) {
85         self.indent.dec();
86     }
89 pub(crate) struct FmtIndent<'a>(pub(crate) &'a Context<'a>);
91 impl fmt::Display for FmtIndent<'_> {
92     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93         self.0.indent.fmt(f)?;
94         Ok(())
95     }
98 write_bytes::display_bytes_using_display!(FmtIndent<'_>);