Skip to content

Commit 3644e50

Browse files
authored
Merge branch 'main' into test-register-csv-4950216802809289615
2 parents ac12848 + 0a49e92 commit 3644e50

28 files changed

Lines changed: 1187 additions & 904 deletions

File tree

‎.github/workflows/docs.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
uses: actions/checkout@v4
2121

2222
- name: Set up Python
23-
uses: actions/setup-python@v4
23+
uses: actions/setup-python@v7
2424
with:
2525
python-version: '3.10'
2626

‎.github/workflows/graphify.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
uses: actions/checkout@v4
2121

2222
- name: Set up Python ${{ matrix.python-version }}
23-
uses: actions/setup-python@v5
23+
uses: actions/setup-python@v7
2424
with:
2525
python-version: ${{ matrix.python-version }}
2626
cache: 'pip'

‎.github/workflows/pypi-publish.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- uses: actions/checkout@v4
1717

1818
- name: Set up Python
19-
uses: actions/setup-python@v5
19+
uses: actions/setup-python@v7
2020
with:
2121
python-version: "3.12"
2222

@@ -64,7 +64,7 @@ jobs:
6464
- uses: actions/checkout@v4
6565

6666
- name: Set up Python ${{ matrix.python-version }}
67-
uses: actions/setup-python@v5
67+
uses: actions/setup-python@v7
6868
with:
6969
python-version: ${{ matrix.python-version }}
7070

‎.jules/bolt.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@
88
## 2024-05-18 - Removed redundant clone of VM stack during trace logs
99
**Learning:** In `runtime/vm/src/executor.rs`, the debugging instruction trace `self.debugger.trace_instruction` was cloning the entire VM stack using `&self.stack.get_dump()` for every single instruction executed. This caused significant `O(N)` overhead inside the main fetch-decode-execute loop just to format debug output. A new `data_slice()` method was added to `ValueStack` to provide zero-copy slice access (`&[RuntimeValue]`) instead, completely eliminating the allocation overhead.
1010
**Action:** Always scrutinize deep clones in logging, tracing, or hot path loops. Use slice references (`&[T]`) instead of `Vec::clone` when the caller only needs read-only access to a collection.
11+
## 2024-06-25 - Suboptimal Line Search in LSP
12+
**Learning:** Using `chars().nth()` with a byte offset (such as one returned by `.find()`) inside a loop over a string creates an O(N) penalty and may result in an incorrect character lookup if multi-byte unicode characters are present.
13+
**Action:** Use string slicing with the byte index to create a subset string slice, and call `.chars().next_back()` or `.chars().next()` on it for an O(1) and UTF-8 safe boundary lookup.

‎cli/src/commands/migrate.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,9 @@ fn replace_call(source: &str, prefix: &str, keyword: &str) -> String {
263263
remaining = &remaining[pos + full.len()..];
264264
if let Some(close) = remaining.find(')') {
265265
let args = &remaining[..close];
266-
result.push_str(&format!("{keyword} {args}"));
266+
result.push_str(keyword);
267+
result.push(' ');
268+
result.push_str(args);
267269
remaining = &remaining[close + 1..];
268270
} else {
269271
result.push_str(remaining);

‎cli/src/commands/repl.rs‎

Lines changed: 92 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -68,86 +68,8 @@ pub fn execute() -> ExitCode {
6868
// Process REPL Metacommand
6969
let parts: Vec<&str> = trimmed.split_whitespace().collect();
7070
let cmd = parts[0];
71-
match cmd {
72-
":quit" | ":q" => {
73-
println!("Goodbye!");
74-
break;
75-
}
76-
":help" | ":h" => {
77-
print_help();
78-
}
79-
":clear" | ":c" => {
80-
interpreter = techscript_interpreter::Interpreter::new();
81-
println!("REPL environment state cleared.");
82-
}
83-
":history" => {
84-
for (i, h) in session_history.iter().enumerate() {
85-
println!("{:>4}: {}", i + 1, h);
86-
}
87-
}
88-
":type" => {
89-
if parts.len() < 2 {
90-
println!("Usage: :type <expr>");
91-
} else {
92-
let expr = parts[1..].join(" ");
93-
evaluate_type(&expr, &mut interpreter);
94-
}
95-
}
96-
":ast" => {
97-
if parts.len() < 2 {
98-
println!("Usage: :ast <expr>");
99-
} else {
100-
let expr = parts[1..].join(" ");
101-
dump_repl_ast(&expr);
102-
}
103-
}
104-
":ir" => {
105-
if parts.len() < 2 {
106-
println!("Usage: :ir <expr>");
107-
} else {
108-
let expr = parts[1..].join(" ");
109-
dump_repl_ir(&expr);
110-
}
111-
}
112-
":bytecode" => {
113-
if parts.len() < 2 {
114-
println!("Usage: :bytecode <expr>");
115-
} else {
116-
let expr = parts[1..].join(" ");
117-
dump_repl_bytecode(&expr);
118-
}
119-
}
120-
":load" => {
121-
if parts.len() < 2 {
122-
println!("Usage: :load <file>");
123-
} else {
124-
let file = parts[1];
125-
if let Ok(content) = std::fs::read_to_string(file) {
126-
eval_code(&content, &mut interpreter);
127-
} else {
128-
println!("Error: Could not read file '{}'.", file);
129-
}
130-
}
131-
}
132-
":save" => {
133-
if parts.len() < 2 {
134-
println!("Usage: :save <file>");
135-
} else {
136-
let file = parts[1];
137-
let session_data = session_history.join("\n");
138-
if std::fs::write(file, session_data).is_ok() {
139-
println!("Session history saved to '{}'.", file);
140-
} else {
141-
println!("Error: Could not write to file '{}'.", file);
142-
}
143-
}
144-
}
145-
other => {
146-
println!(
147-
"Unknown command '{}'. Type ':help' for instructions.",
148-
other
149-
);
150-
}
71+
if handle_metacommand(cmd, &parts, &mut interpreter, &session_history) {
72+
break;
15173
}
15274
} else {
15375
// Regular statement/expression evaluation
@@ -172,6 +94,96 @@ pub fn execute() -> ExitCode {
17294
ExitCode::Success
17395
}
17496

97+
fn handle_metacommand(
98+
cmd: &str,
99+
parts: &[&str],
100+
interpreter: &mut techscript_interpreter::Interpreter,
101+
session_history: &[String],
102+
) -> bool {
103+
match cmd {
104+
":quit" | ":q" => {
105+
println!("Goodbye!");
106+
return true;
107+
}
108+
":help" | ":h" => {
109+
print_help();
110+
}
111+
":clear" | ":c" => {
112+
*interpreter = techscript_interpreter::Interpreter::new();
113+
println!("REPL environment state cleared.");
114+
}
115+
":history" => {
116+
for (i, h) in session_history.iter().enumerate() {
117+
println!("{:>4}: {}", i + 1, h);
118+
}
119+
}
120+
":type" => {
121+
if parts.len() < 2 {
122+
println!("Usage: :type <expr>");
123+
} else {
124+
let expr = parts[1..].join(" ");
125+
evaluate_type(&expr, interpreter);
126+
}
127+
}
128+
":ast" => {
129+
if parts.len() < 2 {
130+
println!("Usage: :ast <expr>");
131+
} else {
132+
let expr = parts[1..].join(" ");
133+
dump_repl_ast(&expr);
134+
}
135+
}
136+
":ir" => {
137+
if parts.len() < 2 {
138+
println!("Usage: :ir <expr>");
139+
} else {
140+
let expr = parts[1..].join(" ");
141+
dump_repl_ir(&expr);
142+
}
143+
}
144+
":bytecode" => {
145+
if parts.len() < 2 {
146+
println!("Usage: :bytecode <expr>");
147+
} else {
148+
let expr = parts[1..].join(" ");
149+
dump_repl_bytecode(&expr);
150+
}
151+
}
152+
":load" => {
153+
if parts.len() < 2 {
154+
println!("Usage: :load <file>");
155+
} else {
156+
let file = parts[1];
157+
if let Ok(content) = std::fs::read_to_string(file) {
158+
eval_code(&content, interpreter);
159+
} else {
160+
println!("Error: Could not read file '{}'.", file);
161+
}
162+
}
163+
}
164+
":save" => {
165+
if parts.len() < 2 {
166+
println!("Usage: :save <file>");
167+
} else {
168+
let file = parts[1];
169+
let session_data = session_history.join("\n");
170+
if std::fs::write(file, session_data).is_ok() {
171+
println!("Session history saved to '{}'.", file);
172+
} else {
173+
println!("Error: Could not write to file '{}'.", file);
174+
}
175+
}
176+
}
177+
other => {
178+
println!(
179+
"Unknown command '{}'. Type ':help' for instructions.",
180+
other
181+
);
182+
}
183+
}
184+
false
185+
}
186+
175187
fn print_help() {
176188
println!("TechScript REPL Shell Metacommands:");
177189
println!(" :help, :h Show this help text");

‎cli/src/watch.rs‎

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,29 +71,7 @@ impl FileWatcher {
7171
fn scan_files(&self, states: &mut HashMap<PathBuf, SystemTime>) -> anyhow::Result<()> {
7272
let mut dirs = vec![self.root.clone()];
7373
while let Some(dir) = dirs.pop() {
74-
if dir.is_dir() {
75-
if let Ok(entries) = std::fs::read_dir(dir) {
76-
for entry in entries.flatten() {
77-
let path = entry.path();
78-
if path.is_dir() {
79-
// Don't watch build or cache directories to prevent infinite loops
80-
let name = path.file_name().unwrap_or_default().to_string_lossy();
81-
if name != "build" && name != ".git" && name != "target" {
82-
dirs.push(path);
83-
}
84-
} else {
85-
let ext = path.extension().unwrap_or_default().to_string_lossy();
86-
if ext == "txs" || ext == "ts" {
87-
if let Ok(metadata) = entry.metadata() {
88-
if let Ok(modified) = metadata.modified() {
89-
states.insert(path, modified);
90-
}
91-
}
92-
}
93-
}
94-
}
95-
}
96-
} else {
74+
if !dir.is_dir() {
9775
// Root is a single file
9876
let ext = self.root.extension().unwrap_or_default().to_string_lossy();
9977
if ext == "txs" || ext == "ts" {
@@ -103,6 +81,32 @@ impl FileWatcher {
10381
}
10482
}
10583
}
84+
continue;
85+
}
86+
87+
if let Ok(entries) = std::fs::read_dir(dir) {
88+
for entry in entries.flatten() {
89+
let path = entry.path();
90+
if path.is_dir() {
91+
// Don't watch build or cache directories to prevent infinite loops
92+
let name = path.file_name().unwrap_or_default().to_string_lossy();
93+
if name != "build" && name != ".git" && name != "target" {
94+
dirs.push(path);
95+
}
96+
continue;
97+
}
98+
99+
let ext = path.extension().unwrap_or_default().to_string_lossy();
100+
if ext != "txs" && ext != "ts" {
101+
continue;
102+
}
103+
104+
if let Ok(metadata) = entry.metadata() {
105+
if let Ok(modified) = metadata.modified() {
106+
states.insert(path, modified);
107+
}
108+
}
109+
}
106110
}
107111
}
108112
Ok(())

0 commit comments

Comments
 (0)