From e4ef47bcf57fbd1b6aa894f9400e5f971f896c07 Mon Sep 17 00:00:00 2001 From: zong-zhe Date: Tue, 9 Aug 2022 16:53:38 +0800 Subject: [PATCH] feat(compiler-base-error): add text rendering and related helper functions. Reuse 'styled_buffer.rs' in 'rustc_errors', and 'styled_buffer.rs' has been modified to fit the feature of 'Compiler-Base'. - add method 'appendl()' and 'pushs()' to 'StyledBuffer'. - replaced the `enum Style` with generics `T: Clone + PartialEq + Eq + Style` to support extending more styles. - add some test cases for 'StyledBuffer'. issue #115 add comments for `putl()` and `appendl()` add comments to trait Style add more README use generic to replace `dyn trait` rename `putl` to `pushs`. rename `appendl` to `append_last_line`. rename `render_style` to `render_style_to_color_spec`. fix comments mistake rename `append_last_line` to `appendl` --- .../3rdparty/rustc_errors/Cargo.toml | 9 + .../3rdparty/rustc_errors/src/LICENSE | 231 ++++++++++++++ .../3rdparty/rustc_errors/src/README.md | 13 + .../3rdparty/rustc_errors/src/lib.rs | 301 ++++++++++++++++++ .../rustc_errors/src/styled_buffer.rs | 169 ++++++++++ kclvm/compiler_base/Cargo.toml | 13 + kclvm/compiler_base/src/lib.rs | 1 + 7 files changed, 737 insertions(+) create mode 100644 kclvm/compiler_base/3rdparty/rustc_errors/Cargo.toml create mode 100644 kclvm/compiler_base/3rdparty/rustc_errors/src/LICENSE create mode 100644 kclvm/compiler_base/3rdparty/rustc_errors/src/README.md create mode 100644 kclvm/compiler_base/3rdparty/rustc_errors/src/lib.rs create mode 100644 kclvm/compiler_base/3rdparty/rustc_errors/src/styled_buffer.rs create mode 100644 kclvm/compiler_base/Cargo.toml create mode 100644 kclvm/compiler_base/src/lib.rs diff --git a/kclvm/compiler_base/3rdparty/rustc_errors/Cargo.toml b/kclvm/compiler_base/3rdparty/rustc_errors/Cargo.toml new file mode 100644 index 000000000..2ed78e5f8 --- /dev/null +++ b/kclvm/compiler_base/3rdparty/rustc_errors/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rustc_errors" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +termcolor = "1.0" \ No newline at end of file diff --git a/kclvm/compiler_base/3rdparty/rustc_errors/src/LICENSE b/kclvm/compiler_base/3rdparty/rustc_errors/src/LICENSE new file mode 100644 index 000000000..8467a0168 --- /dev/null +++ b/kclvm/compiler_base/3rdparty/rustc_errors/src/LICENSE @@ -0,0 +1,231 @@ +Short version for non-lawyers: + +The Rust Project is dual-licensed under Apache 2.0 and MIT +terms. + + +Longer version: + +Copyrights in the Rust project are retained by their contributors. No +copyright assignment is required to contribute to the Rust project. + +Some files include explicit copyright notices and/or license notices. +For full authorship information, see the version control history or +https://thanks.rust-lang.org + +Except as otherwise noted (below and/or in individual files), Rust is +licensed under the Apache License, Version 2.0 or + or the MIT license + or , at your option. + + +The Rust Project includes packages written by third parties. +The following third party packages are included, and carry +their own copyright notices and license terms: + +* LLVM. Code for this package is found in src/llvm-project. + + Copyright (c) 2003-2013 University of Illinois at + Urbana-Champaign. All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any + person obtaining a copy of this software and associated + documentation files (the "Software"), to deal with the + Software without restriction, including without + limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software + is furnished to do so, subject to the following + conditions: + + * Redistributions of source code must retain the + above copyright notice, this list of conditions + and the following disclaimers. + + * Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimers in the documentation + and/or other materials provided with the + distribution. + + * Neither the names of the LLVM Team, University of + Illinois at Urbana-Champaign, nor the names of its + contributors may be used to endorse or promote + products derived from this Software without + specific prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT + OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS WITH THE SOFTWARE. + +* Additional libraries included in LLVM carry separate + BSD-compatible licenses. See src/llvm-project/llvm/LICENSE.TXT + for details. + +* compiler-rt, in src/compiler-rt is dual licensed under + LLVM's license and MIT: + + Copyright (c) 2009-2014 by the contributors listed in + CREDITS.TXT + + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any + person obtaining a copy of this software and associated + documentation files (the "Software"), to deal with the + Software without restriction, including without + limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software + is furnished to do so, subject to the following + conditions: + + * Redistributions of source code must retain the + above copyright notice, this list of conditions + and the following disclaimers. + + * Redistributions in binary form must reproduce the + above copyright notice, this list of conditions + and the following disclaimers in the documentation + and/or other materials provided with the + distribution. + + * Neither the names of the LLVM Team, University of + Illinois at Urbana-Champaign, nor the names of its + contributors may be used to endorse or promote + products derived from this Software without + specific prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT + OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS WITH THE SOFTWARE. + + ======================================================== + + Copyright (c) 2009-2014 by the contributors listed in + CREDITS.TXT + + Permission is hereby granted, free of charge, to any + person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the + Software without restriction, including without + limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software + is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice + shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +* Portions of the FFI code for interacting with the native ABI + is derived from the Clay programming language, which carries + the following license. + + Copyright (C) 2008-2010 Tachyon Technologies. + All rights reserved. + + Redistribution and use in source and binary forms, with + or without modification, are permitted provided that the + following conditions are met: + + 1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + 2. Redistributions in binary form must reproduce the + above copyright notice, this list of conditions and + the following disclaimer in the documentation and/or + other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + OF SUCH DAMAGE. + +* libbacktrace, under src/libbacktrace: + + Copyright (C) 2012-2014 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Google. + + Redistribution and use in source and binary forms, with + or without modification, are permitted provided that the + following conditions are met: + + (1) Redistributions of source code must retain the + above copyright notice, this list of conditions and + the following disclaimer. + + (2) Redistributions in binary form must reproduce + the above copyright notice, this list of conditions + and the following disclaimer in the documentation + and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + OF SUCH DAMAGE. */ \ No newline at end of file diff --git a/kclvm/compiler_base/3rdparty/rustc_errors/src/README.md b/kclvm/compiler_base/3rdparty/rustc_errors/src/README.md new file mode 100644 index 000000000..7066f4053 --- /dev/null +++ b/kclvm/compiler_base/3rdparty/rustc_errors/src/README.md @@ -0,0 +1,13 @@ +Porting ['rustc_errors/styled_buffer.rs'] code here to enable code reuse due to the unstable and unreusable of the ['rustc_errors'] crate now. +We mainly reuse helper structs and functions like `StyledBuffer`, `StyledString` to render text in Compiler-Base. +Note: the structs and functions here exist as implementations and will not be exposed to other crates directly. + +Reuse 'styled_buffer.rs' in 'rustc_errors', +and 'styled_buffer.rs' has been modified to fit the feature of 'Compiler-Base'. + +We modified some features on porting code: +- add method `appendl()` and `pushs()` to 'StyledBuffer'. +- replaced the `enum Style` with generics `T: Clone + PartialEq + Eq + Style` to support extending more styles, because we need that `StyledBuffer` is still valid when facing the user-defined style, rather than just supporting a built-in `enum Style`. +- added some test cases for 'StyledBuffer' with 'trait Style'. + +If anyone feels uncomfortable, please feel free to contact us. \ No newline at end of file diff --git a/kclvm/compiler_base/3rdparty/rustc_errors/src/lib.rs b/kclvm/compiler_base/3rdparty/rustc_errors/src/lib.rs new file mode 100644 index 000000000..32f02482d --- /dev/null +++ b/kclvm/compiler_base/3rdparty/rustc_errors/src/lib.rs @@ -0,0 +1,301 @@ +//! Text rendering and related helper functions. +//! +//! Reuse 'styled_buffer.rs' in 'rustc_errors', +//! and 'styled_buffer.rs' has been modified to fit the feature of 'Compiler-Base'. +//! +//! - add method `appendl()` and `pushs()` to `StyledBuffer`. +//! +//! - replaced the `enum Style` with generics `T: Clone + PartialEq + Eq + Style` to support extending more styles. +//! `StyledBuffer` still should be valid when facing the user-defined style, rather than just supporting a built-in `enum Style`. +//! +//! - add some test cases for 'StyledBuffer'. +use termcolor::ColorSpec; + +pub mod styled_buffer; + +/// 'Style' is a trait used to specify the user customize 'XXXStyle' can be accepted by 'StyleBuffer'. +/// +/// It provides the following method `render_style_to_color_spec()`. +/// render_style_to_color_spec(&self) : render style to terminal color/font configuration. +pub trait Style { + /// render style to terminal color/font configuration. + /// + /// # Example + /// + /// ```rust + /// #[derive(Copy, Clone, Debug, PartialEq, Eq)] + /// pub enum DummyStyle { + /// Dummy, + /// NoStyle, + /// } + /// + /// impl Style for DummyStyle { + /// fn render_style_to_color_spec(&self) -> ColorSpec { + /// let mut spec = ColorSpec::new(); + /// match self{ + /// // For `DummyStyle::Dummy`, the font is intense and the font color is red. + /// DummyStyle::Dummy => { + /// spec.set_fg(Some(Color::Red)).set_intense(true); + /// } + /// } + /// spec + /// } + /// } + /// ``` + fn render_style_to_color_spec(&self) -> ColorSpec; +} + +#[cfg(test)] +mod test_styled_buffer { + use crate::{ + styled_buffer::{StyledBuffer, StyledString}, + Style, + }; + use termcolor::{Color, ColorSpec}; + + // DummyStyle for testing 'StyledBuffer'. + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + pub enum DummyStyle { + Dummy, + NoStyle, + } + + impl Style for DummyStyle { + fn render_style_to_color_spec(&self) -> ColorSpec { + let mut spec = ColorSpec::new(); + match self { + DummyStyle::Dummy => { + spec.set_fg(Some(Color::Red)).set_intense(true); + } + DummyStyle::NoStyle => { + spec.set_fg(Some(Color::Green)).set_intense(false); + } + } + spec + } + } + + fn construct_new_styledbuffer() -> StyledBuffer { + StyledBuffer::new() + } + + fn putc_hello_world(sb: &mut StyledBuffer) { + sb.putc(0, 0, 'H', Some(DummyStyle::NoStyle)); + sb.putc(0, 1, 'e', Some(DummyStyle::NoStyle)); + sb.putc(0, 2, 'l', Some(DummyStyle::NoStyle)); + sb.putc(0, 3, 'l', Some(DummyStyle::NoStyle)); + sb.putc(0, 4, 'o', Some(DummyStyle::NoStyle)); + sb.putc(0, 5, 'W', Some(DummyStyle::Dummy)); + sb.putc(0, 6, 'o', Some(DummyStyle::Dummy)); + sb.putc(0, 7, 'r', Some(DummyStyle::Dummy)); + sb.putc(0, 8, 'l', Some(DummyStyle::Dummy)); + sb.putc(0, 9, 'd', Some(DummyStyle::Dummy)); + } + + fn puts_hello_world(sb: &mut StyledBuffer) { + sb.puts(0, 0, "Hello", Some(DummyStyle::NoStyle)); + sb.puts(0, 5, "World", Some(DummyStyle::Dummy)); + } + + fn pushs_hello_world(sb: &mut StyledBuffer) { + sb.pushs("Hello", Some(DummyStyle::NoStyle)); + sb.pushs("World", Some(DummyStyle::Dummy)); + } + + fn appendl_hello_world(sb: &mut StyledBuffer) { + sb.appendl("Hello", Some(DummyStyle::NoStyle)); + sb.appendl("World", Some(DummyStyle::Dummy)); + } + + fn require_hello_world(styled_strings: Vec>>) { + assert_eq!(styled_strings.len(), 1); + assert_eq!(styled_strings.get(0).unwrap().len(), 2); + + assert_eq!(styled_strings.get(0).unwrap().get(0).unwrap().text, "Hello"); + assert!( + DummyStyle::NoStyle + == *styled_strings + .get(0) + .unwrap() + .get(0) + .unwrap() + .style + .as_ref() + .unwrap() + ); + assert_eq!(styled_strings.get(0).unwrap().get(1).unwrap().text, "World"); + assert!( + DummyStyle::Dummy + == *styled_strings + .get(0) + .unwrap() + .get(1) + .unwrap() + .style + .as_ref() + .unwrap() + ); + } + + #[test] + fn test_putc() { + let mut sb = construct_new_styledbuffer(); + putc_hello_world(&mut sb); + + let styled_strings = sb.render(); + + require_hello_world(styled_strings); + + sb.putc(0, 0, 'H', Some(DummyStyle::NoStyle)); + sb.putc(0, 1, 'E', Some(DummyStyle::NoStyle)); + sb.putc(0, 2, 'L', Some(DummyStyle::NoStyle)); + sb.putc(0, 3, 'L', Some(DummyStyle::NoStyle)); + sb.putc(0, 4, 'O', Some(DummyStyle::NoStyle)); + let styled_strings = sb.render(); + assert_eq!(styled_strings.get(0).unwrap().get(0).unwrap().text, "HELLO"); + assert!( + DummyStyle::NoStyle + == *styled_strings + .get(0) + .unwrap() + .get(0) + .unwrap() + .style + .as_ref() + .unwrap(), + "style error: expected style : {:?}", + DummyStyle::NoStyle + ); + } + + #[test] + fn test_putc_new_line() { + let mut sb = construct_new_styledbuffer(); + putc_hello_world(&mut sb); + + sb.putc(2, 0, 'A', Some(DummyStyle::Dummy)); + let styled_strings = sb.render(); + assert_eq!(styled_strings.len(), 3); + assert_eq!(styled_strings.get(0).unwrap().len(), 2); + assert_eq!(styled_strings.get(1).unwrap().len(), 0); + assert_eq!(styled_strings.get(2).unwrap().len(), 1); + assert_eq!(styled_strings.get(2).unwrap().get(0).unwrap().text, "A"); + assert!( + DummyStyle::Dummy + == *styled_strings + .get(2) + .unwrap() + .get(0) + .unwrap() + .style + .as_ref() + .unwrap(), + "style error: expected style : {:?}", + DummyStyle::Dummy + ); + } + + #[test] + fn test_puts() { + let mut sb = construct_new_styledbuffer(); + puts_hello_world(&mut sb); + let styled_strings = sb.render(); + require_hello_world(styled_strings); + } + + #[test] + fn test_puts_new_line() { + let mut sb = construct_new_styledbuffer(); + puts_hello_world(&mut sb); + + sb.puts(2, 0, "A", Some(DummyStyle::Dummy)); + let styled_strings = sb.render(); + assert_eq!(styled_strings.len(), 3); + assert_eq!(styled_strings.get(0).unwrap().len(), 2); + assert_eq!(styled_strings.get(1).unwrap().len(), 0); + assert_eq!(styled_strings.get(2).unwrap().len(), 1); + assert_eq!(styled_strings.get(2).unwrap().get(0).unwrap().text, "A"); + assert!( + DummyStyle::Dummy + == *styled_strings + .get(2) + .unwrap() + .get(0) + .unwrap() + .style + .as_ref() + .unwrap(), + "style error: expected style : {:?}", + DummyStyle::Dummy + ); + } + + #[test] + fn test_pushs() { + let mut sb = construct_new_styledbuffer(); + pushs_hello_world(&mut sb); + let styled_strings = sb.render(); + assert_eq!(styled_strings.len(), 2); + assert_eq!(styled_strings.get(0).unwrap().len(), 1); + + assert_eq!(styled_strings.get(0).unwrap().get(0).unwrap().text, "Hello"); + assert!( + DummyStyle::NoStyle + == *styled_strings + .get(0) + .unwrap() + .get(0) + .unwrap() + .style + .as_ref() + .unwrap(), + "style error: expected style : {:?}", + DummyStyle::NoStyle + ); + + assert_eq!(styled_strings.get(1).unwrap().get(0).unwrap().text, "World"); + assert!( + DummyStyle::Dummy + == *styled_strings + .get(1) + .unwrap() + .get(0) + .unwrap() + .style + .as_ref() + .unwrap(), + "style error: expected style : {:?}", + DummyStyle::Dummy + ); + } + + #[test] + fn test_appendl() { + let mut sb = construct_new_styledbuffer(); + appendl_hello_world(&mut sb); + let styled_strings = sb.render(); + require_hello_world(styled_strings); + } + + #[test] + fn test_prepend() { + let mut sb = construct_new_styledbuffer(); + sb.appendl("World", Some(DummyStyle::Dummy)); + sb.prepend(0, "Hello", Some(DummyStyle::NoStyle)); + let styled_strings = sb.render(); + require_hello_world(styled_strings); + } + + #[test] + fn test_num_lines() { + let mut sb = construct_new_styledbuffer(); + putc_hello_world(&mut sb); + assert_eq!(sb.num_lines(), 1); + sb.appendl("World", Some(DummyStyle::Dummy)); + assert_eq!(sb.num_lines(), 1); + pushs_hello_world(&mut sb); + assert_eq!(sb.num_lines(), 3); + puts_hello_world(&mut sb); + assert_eq!(sb.num_lines(), 3); + } +} diff --git a/kclvm/compiler_base/3rdparty/rustc_errors/src/styled_buffer.rs b/kclvm/compiler_base/3rdparty/rustc_errors/src/styled_buffer.rs new file mode 100644 index 000000000..f32362b02 --- /dev/null +++ b/kclvm/compiler_base/3rdparty/rustc_errors/src/styled_buffer.rs @@ -0,0 +1,169 @@ +//! 'StyledBuffer', a generic, is responsible for text rendering. +//! +//! An acceptable custom `XXXStyle` for `StyledBuffer` must implement trait `Clone`, `PartialEq`, `Eq` and `Style`. +use crate::Style; + +/// An acceptable custom `XXXStyle` for `StyledBuffer` must implement trait `Clone`, `PartialEq`, `Eq` and `Style`. +pub struct StyledBuffer +where + T: Clone + PartialEq + Eq + Style, +{ + lines: Vec>>, +} + +#[derive(Clone)] +struct StyledChar +where + T: Clone + PartialEq + Eq + Style, +{ + chr: char, + style: Option, +} + +/// An acceptable custom `XXXStyle` for `StyledString` must implement trait `Clone`, `PartialEq`, `Eq` and `Style`. +pub struct StyledString +where + T: Clone + PartialEq + Eq + Style, +{ + pub text: String, + pub style: Option, +} + +impl StyledChar +where + T: Clone + PartialEq + Eq + Style, +{ + const SPACE: StyledChar = StyledChar::new(' ', None); + + const fn new(chr: char, style: Option) -> Self { + StyledChar { chr, style } + } +} + +impl StyledBuffer +where + T: Clone + PartialEq + Eq + Style, +{ + pub fn new() -> StyledBuffer { + StyledBuffer { lines: vec![] } + } + + /// Returns content of `StyledBuffer` split by lines and line styles + pub fn render(&self) -> Vec>> { + let mut output: Vec>> = vec![]; + let mut styled_vec: Vec> = vec![]; + + for styled_line in &self.lines { + let mut current_style = None; + let mut current_text = String::new(); + + for sc in styled_line { + if sc.style != current_style { + if !current_text.is_empty() { + styled_vec.push(StyledString { + text: current_text, + style: current_style, + }); + } + current_style = sc.style.clone(); + current_text = String::new(); + } + current_text.push(sc.chr); + } + if !current_text.is_empty() { + styled_vec.push(StyledString { + text: current_text, + style: current_style, + }); + } + + // done with the row, push and keep going + output.push(styled_vec); + + styled_vec = vec![]; + } + + output + } + + fn ensure_lines(&mut self, line: usize) { + if line >= self.lines.len() { + self.lines.resize(line + 1, Vec::new()); + } + } + + /// Sets `chr` with `style` for given `line`, `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. + pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Option) { + self.ensure_lines(line); + if col >= self.lines[line].len() { + self.lines[line].resize(col + 1, StyledChar::SPACE); + } + self.lines[line][col] = StyledChar::new(chr, style); + } + + /// Sets `string` with `style` for given `line`, starting from `col`. + /// If `line` does not exist in our buffer, adds empty lines up to the given + /// and fills the last line with unstyled whitespace. + pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Option) { + let mut n = col; + for c in string.chars() { + self.putc(line, n, c, style.clone()); + n += 1; + } + } + + /// Sets `string` with `style` for a new line, starting from col 0. + /// It will add an new empty line after all the buffer lines for the `string`. + pub fn pushs(&mut self, string: &str, style: Option) { + let line = self.num_lines(); + let mut col = 0; + for c in string.chars() { + self.putc(line, col, c, style.clone()); + col += 1; + } + } + + /// For the last line inserts `string` with `style` after old content of that line, + /// adding a new line if the `StyledBuffer` has no line. + pub fn appendl(&mut self, string: &str, style: Option) { + let line = if self.num_lines() > 0 { + self.num_lines() - 1 + } else { + self.num_lines() + }; + self.append(line, string, style); + } + + /// For given `line` inserts `string` with `style` before old content of that line, + /// adding lines if needed + pub fn prepend(&mut self, line: usize, string: &str, style: Option) { + self.ensure_lines(line); + let string_len = string.chars().count(); + + if !self.lines[line].is_empty() { + // Push the old content over to make room for new content + for _ in 0..string_len { + self.lines[line].insert(0, StyledChar::SPACE); + } + } + + self.puts(line, 0, string, style); + } + + /// For given `line` inserts `string` with `style` after old content of that line, + /// adding lines if needed + pub fn append(&mut self, line: usize, string: &str, style: Option) { + if line >= self.lines.len() { + self.puts(line, 0, string, style); + } else { + let col = self.lines[line].len(); + self.puts(line, col, string, style); + } + } + + pub fn num_lines(&self) -> usize { + self.lines.len() + } +} diff --git a/kclvm/compiler_base/Cargo.toml b/kclvm/compiler_base/Cargo.toml new file mode 100644 index 000000000..ea1140a77 --- /dev/null +++ b/kclvm/compiler_base/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "compiler_base" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[workspace] +members = [ + "3rdparty/rustc_errors", +] \ No newline at end of file diff --git a/kclvm/compiler_base/src/lib.rs b/kclvm/compiler_base/src/lib.rs new file mode 100644 index 000000000..a02d74547 --- /dev/null +++ b/kclvm/compiler_base/src/lib.rs @@ -0,0 +1 @@ +// TODO(zong-zhe): add more external interfaces of CompilerBase.