Skip to content

Commit a9008e7

Browse files
committed
Merge branch 'main' of https://gitlab.com/mech-lang/mech
2 parents 198cde4 + dc4bffd commit a9008e7

31 files changed

+5572
-9480
lines changed

Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mech"
3-
version = "0.2.2"
3+
version = "0.2.3"
44
authors = ["Corey Montella <[email protected]>"]
55
description = "Toolchain for the Mech programming language."
66
documentation = "https://mech-lang.org/docs"
@@ -18,20 +18,20 @@ gitlab = { repository = "mech-lang/mech", branch = "main" }
1818
maintenance = { status = "actively-developed" }
1919

2020
[dependencies]
21-
mech-core = "0.2.2"
22-
mech-syntax = {version = "0.2.2", features = ["lang-server"]}
21+
mech-core = "0.2.3"
22+
mech-syntax = "0.2.3"
2323
#mech-program = "0.2.2"
24-
mech-utilities = "0.2.2"
24+
#mech-utilities = "0.2.2"
2525

2626
clap = {version = "4.5.8", features = ["cargo"]}
2727
colored = "2.1.0"
2828
#nom = "7.1.3"
2929
#hashbrown = "0.14.5"
3030
#reqwest = {version = "0.12.4", features = ["blocking"]}
3131
bincode = "1.3.3"
32-
#serde = "1.0.203"
33-
#serde_derive = "1.0.203"
34-
#serde_json = "1.0.117"
32+
serde = "1.0.204"
33+
serde_derive = "1.0.204"
34+
serde_json = "1.0.120"
3535
crossbeam-channel = "0.5.13"
3636
#seahash = "4.1.0"
3737
crossterm = "0.27.0"

src/bin/mech.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#![feature(hash_extract_if)]
22
#![allow(warnings)]
3+
use mech::format_parse_tree;
34
use mech_core::*;
4-
use mech_syntax::parser2;
5+
use mech_syntax::parser;
56
//use mech_syntax::analyzer::*;
67
use mech_syntax::interpreter::*;
78
use std::time::Instant;
@@ -20,9 +21,11 @@ use tabled::{
2021
settings::{object::Rows,Panel, Span, Alignment, Modify, Style},
2122
Tabled,
2223
};
24+
use serde_json;
25+
2326

2427
fn main() -> Result<(), MechError> {
25-
let version = "0.2.2";
28+
let version = "0.2.3";
2629
let text_logo = r#"
2730
┌─────────┐ ┌──────┐ ┌─┐ ┌──┐ ┌─┐ ┌─┐
2831
└───┐ ┌───┘ └──────┘ │ │ └┐ │ │ │ │ │
@@ -56,13 +59,15 @@ fn main() -> Result<(), MechError> {
5659
let mut intrp = Interpreter::new();
5760
if let Some(mech_paths) = matches.get_one::<String>("mech_paths") {
5861
let s = fs::read_to_string(&mech_paths).unwrap();
59-
match parser2::parse(&s) {
62+
match parser::parse(&s) {
6063
Ok(tree) => {
6164
let result = intrp.interpret(&tree);
65+
let pretty_json = format_parse_tree(&tree);
66+
6267
let debug_flag = matches.get_flag("debug");
6368
if debug_flag {
6469
let tree_hash = hash_str(&format!("{:#?}", tree));
65-
let syntax_tree_str = format!("Tree Hash: {:?}\n{:#?}", tree_hash, tree);
70+
let syntax_tree_str = format!("Tree Hash: {:?}\n{}", tree_hash, pretty_json);
6671

6772
let mut interpreter_str = format!("Symbols: {:#?}\n", intrp.symbols);
6873
interpreter_str = format!("{}Plan:\n", interpreter_str);
@@ -76,7 +81,10 @@ fn main() -> Result<(), MechError> {
7681
for fxn in intrp.plan.borrow().iter() {
7782
fxn.solve();
7883
}
79-
let result_str = format!("{:#?}", result);
84+
let result_str = match result {
85+
Ok(r) => format!("{}", r.pretty_print()),
86+
Err(err) => format!("{:?}", err),
87+
};
8088

8189
let data = vec!["🌳 Syntax Tree", &syntax_tree_str,
8290
"💻 Interpreter", &interpreter_str,
@@ -88,12 +96,16 @@ fn main() -> Result<(), MechError> {
8896

8997
println!("{table}");
9098
} else {
91-
println!("{:#?}", result);
99+
let result_str = match result {
100+
Ok(r) => format!("{}", r.pretty_print()),
101+
Err(err) => format!("{:?}", err),
102+
};
103+
println!("{}", result_str);
92104
}
93105
},
94106
Err(err) => {
95107
if let MechErrorKind::ParserError(report, _) = err.kind {
96-
parser2::print_err_report(&s, &report);
108+
parser::print_err_report(&s, &report);
97109
} else {
98110
panic!("Unexpected error type");
99111
}
@@ -125,7 +137,7 @@ fn main() -> Result<(), MechError> {
125137
io::stdout().flush().unwrap();
126138
let mut input = String::new();
127139
io::stdin().read_line(&mut input).unwrap();
128-
match parser2::parse(&input) {
140+
match parser::parse(&input) {
129141
Ok(tree) => {
130142
let result = intrp.interpret(&tree);
131143
match result {
@@ -135,7 +147,7 @@ fn main() -> Result<(), MechError> {
135147
}
136148
Err(err) => {
137149
if let MechErrorKind::ParserError(report, _) = err.kind {
138-
parser2::print_err_report(&input, &report);
150+
parser::print_err_report(&input, &report);
139151
} else {
140152
panic!("Unexpected error type");
141153
}

src/core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mech-core"
3-
version = "0.2.2"
3+
version = "0.2.3"
44
authors = ["Corey Montella <[email protected]>"]
55
description = "The Mech language runtime."
66
documentation = "http://docs.mech-lang.org"

src/core/src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub enum MechErrorKind {
3636
PendingExpression, // id of pending variable
3737
PendingTable(u64), // TableId of pending table
3838
DimensionMismatch(Vec<(Rows,Cols)>), // Argument dimensions are mismatched ((row,col),(row,col))
39+
UnhandledIndexKind,
3940
//MissingColumn((TableId,TableIndex)), // The identified table is missing a needed column
4041
//ColumnKindMismatch(Vec<ValueKind>), // Excepted kind versus given kind
4142
//SubscriptOutOfBounds(((Rows,Cols),(Rows,Cols))), // (target) vs (actual) index

src/core/src/nodes.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,8 @@ impl Term {
891891
pub enum Factor {
892892
Term(Box<Term>),
893893
Expression(Box<Expression>),
894-
Negated(Box<Factor>),
894+
Negate(Box<Factor>),
895+
Not(Box<Factor>),
895896
Transpose(Box<Factor>),
896897
}
897898

@@ -900,7 +901,8 @@ impl Factor {
900901
match self {
901902
Factor::Term(x) => x.tokens(),
902903
Factor::Expression(x) => x.tokens(),
903-
Factor::Negated(x) => x.tokens(),
904+
Factor::Negate(x) => x.tokens(),
905+
Factor::Not(x) => x.tokens(),
904906
Factor::Transpose(x) => x.tokens(),
905907
}
906908
}

src/lib.rs

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
pub extern crate mech_core as core;
77
pub extern crate mech_syntax as syntax;
88
//pub extern crate mech_program as program;
9-
pub extern crate mech_utilities as utilities;
9+
//pub extern crate mech_utilities as utilities;
1010

1111
//mod repl;
1212

1313
pub use mech_core::*;
14+
use mech_core::nodes::Program;
1415
//pub use mech_syntax::compiler::*;
1516
//pub use mech_program::*;
16-
pub use mech_utilities::*;
17+
//pub use mech_utilities::*;
1718
//pub use self::repl::*;
1819

1920
extern crate colored;
@@ -40,6 +41,164 @@ lazy_static! {
4041
static ref CORE_MAP: Mutex<HashMap<SocketAddr, (String, SystemTime)>> = Mutex::new(HashMap::new());
4142
}
4243

44+
pub fn format_parse_tree(program: &Program) -> String {
45+
let json_string = serde_json::to_string_pretty(&program).unwrap();
46+
47+
let depth = |line: &str|->usize{line.chars().take_while(|&c| c == ' ').count()};
48+
let mut result = String::new();
49+
let lines: Vec<&str> = json_string.lines().collect();
50+
result.push_str("Program\n");
51+
for (index, line) in lines.iter().enumerate() {
52+
let trm = line.trim();
53+
if trm == "}" ||
54+
trm == "},"||
55+
trm == "{" ||
56+
trm == "[" ||
57+
trm == "],"||
58+
trm == "]" {
59+
continue;
60+
}
61+
62+
// Count leading spaces to determine depth
63+
let d = depth(line);
64+
// Construct the tree-like prefix
65+
let mut prefix = String::new();
66+
for _ in 0..d {
67+
prefix.push_str(" ");
68+
}
69+
if index == lines.len() {
70+
prefix.push_str("└ ");
71+
} else {
72+
if depth(lines[index + 1]) != d {
73+
prefix.push_str("└ ");
74+
} else {
75+
prefix.push_str("├ ");
76+
}
77+
}
78+
let trm = line.trim();
79+
let trm = trm.trim_end_matches('{')
80+
.trim_start_matches('"')
81+
.trim_end_matches(':')
82+
.trim_end_matches('"')
83+
.trim_end_matches('[');
84+
prefix.push_str(trm);
85+
86+
// Append formatted line to result
87+
result.push_str(&prefix);
88+
result.push('\n');
89+
result = result.replace("\":", "");
90+
}
91+
let mut indexed_str = IndexedString::new(&result);
92+
'rows: for i in 0..indexed_str.rows {
93+
let rowz = &indexed_str.index_map[i];
94+
for j in 0..rowz.len() {
95+
let c = match indexed_str.get(i,j) {
96+
Some(c) => c,
97+
None => continue,
98+
};
99+
if c == '└' {
100+
for k in i+1..indexed_str.rows {
101+
match indexed_str.get(k,j) {
102+
Some(c2) => {
103+
if c2 == '└' {
104+
indexed_str.set(i,j,'├');
105+
for l in i+1..k {
106+
match indexed_str.get(l,j) {
107+
Some(' ') => {indexed_str.set(l,j,'│');},
108+
Some('└') => {indexed_str.set(l,j,'├');},
109+
_ => (),
110+
}
111+
}
112+
} else if c2 == ' ' {
113+
continue;
114+
} else {
115+
continue 'rows;
116+
}
117+
},
118+
None => continue,
119+
}
120+
121+
}
122+
} else if c == ' ' || c == '│' {
123+
continue;
124+
} else {
125+
continue 'rows;
126+
}
127+
}
128+
}
129+
indexed_str.to_string()
130+
}
131+
132+
#[derive(Clone, Debug, PartialEq, Eq)]
133+
struct IndexedString {
134+
pub data: Vec<char>,
135+
pub index_map: Vec<Vec<usize>>,
136+
pub rows: usize,
137+
pub cols: usize,
138+
}
139+
140+
impl IndexedString {
141+
fn new(input: &str) -> Self {
142+
let mut data = Vec::new();
143+
let mut index_map = Vec::new();
144+
let mut current_row = 0;
145+
let mut current_col = 0;
146+
index_map.push(Vec::new());
147+
for c in input.chars() {
148+
data.push(c);
149+
if c == '\n' {
150+
index_map.push(Vec::new());
151+
current_row += 1;
152+
current_col = 0;
153+
} else {
154+
index_map[current_row].push(data.len() - 1);
155+
current_col += 1;
156+
}
157+
}
158+
let rows = index_map.len();
159+
let cols = if rows > 0 { index_map[0].len() } else { 0 };
160+
IndexedString {
161+
data,
162+
index_map,
163+
rows,
164+
cols,
165+
}
166+
}
167+
fn to_string(&self) -> String {
168+
self.data.iter().collect()
169+
}
170+
fn get(&self, row: usize, col: usize) -> Option<char> {
171+
if row < self.rows {
172+
let rowz = &self.index_map[row];
173+
if col < rowz.len() {
174+
let index = self.index_map[row][col];
175+
Some(self.data[index])
176+
} else {
177+
None
178+
}
179+
} else {
180+
None
181+
}
182+
}
183+
184+
fn set(&mut self, row: usize, col: usize, new_char: char) -> Result<(), String> {
185+
if row < self.rows {
186+
let row_indices = &mut self.index_map[row];
187+
if col < row_indices.len() {
188+
let index = row_indices[col];
189+
self.data[index] = new_char;
190+
Ok(())
191+
} else {
192+
Err("Column index out of bounds".to_string())
193+
}
194+
} else {
195+
Err("Row index out of bounds".to_string())
196+
}
197+
}
198+
199+
200+
}
201+
43202
//extern crate nom;
44203

45204
/*

src/syntax/Cargo.toml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mech-syntax"
3-
version = "0.2.2"
3+
version = "0.2.3"
44
authors = ["Corey Montella <[email protected]>"]
55
description = "A toolchain for compiling textual syntax into Mech blocks."
66
documentation = "http://docs.mech-lang.org"
@@ -19,10 +19,9 @@ maintenance = { status = "actively-developed" }
1919
[features]
2020
default = []
2121
no-std = ["mech-core/no-std", "rlibc"]
22-
lang-server = ["tower-lsp", "tokio"]
2322

2423
[dependencies]
25-
mech-core = "0.2.2"
24+
mech-core = "0.2.3"
2625

2726
hashbrown = "0.14.5"
2827
lazy_static = "1.4.0"
@@ -40,9 +39,6 @@ libm = "0.2.8"
4039
simba = "0.9.0"
4140
paste = "1.0.15"
4241

43-
tower-lsp = {version = "0.20.0", optional = true}
44-
tokio = { version = "1.37.0", features = ["full"], optional = true }
45-
4642
[dependencies.num-traits]
4743
version = "0.2.19"
4844
default-features = false

0 commit comments

Comments
 (0)