instantly refreshable code. untested, but it compiles
This commit is contained in:
parent
f1f32af113
commit
24a852f125
9 changed files with 193 additions and 40 deletions
96
Cargo.lock
generated
96
Cargo.lock
generated
|
|
@ -154,6 +154,12 @@ version = "0.22.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.9.4"
|
version = "2.9.4"
|
||||||
|
|
@ -291,12 +297,14 @@ dependencies = [
|
||||||
name = "crudlang"
|
name = "crudlang"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"arc-swap",
|
||||||
"axum",
|
"axum",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"log",
|
"log",
|
||||||
"log4rs",
|
"log4rs",
|
||||||
|
"notify",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
@ -449,6 +457,15 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fsevent-sys"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
|
|
@ -843,6 +860,26 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.4",
|
||||||
|
"inotify-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify-sys"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.11.0"
|
version = "2.11.0"
|
||||||
|
|
@ -881,6 +918,26 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a"
|
||||||
|
dependencies = [
|
||||||
|
"kqueue-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue-sys"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -899,7 +956,7 @@ version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
]
|
]
|
||||||
|
|
@ -1014,6 +1071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
|
"log",
|
||||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
@ -1041,6 +1099,30 @@ dependencies = [
|
||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notify"
|
||||||
|
version = "8.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.4",
|
||||||
|
"fsevent-sys",
|
||||||
|
"inotify",
|
||||||
|
"kqueue",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"mio",
|
||||||
|
"notify-types",
|
||||||
|
"walkdir",
|
||||||
|
"windows-sys 0.60.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notify-types"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.50.3"
|
version = "0.50.3"
|
||||||
|
|
@ -1077,7 +1159,7 @@ version = "0.10.73"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
|
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
@ -1296,7 +1378,7 @@ version = "0.5.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1361,7 +1443,7 @@ version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
|
|
@ -1443,7 +1525,7 @@ version = "2.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
@ -1678,7 +1760,7 @@ version = "0.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"system-configuration-sys",
|
"system-configuration-sys",
|
||||||
]
|
]
|
||||||
|
|
@ -1879,7 +1961,7 @@ version = "0.6.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
|
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,5 @@ walkdir = "2.5.0"
|
||||||
thiserror = "2.0.17"
|
thiserror = "2.0.17"
|
||||||
url = "2.5.7"
|
url = "2.5.7"
|
||||||
clap = { version = "4.5.51", features = ["derive"] }
|
clap = { version = "4.5.51", features = ["derive"] }
|
||||||
|
notify = "8.2.0"
|
||||||
|
arc-swap = "1.7.1"
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ use crate::errors::CompilerError::{
|
||||||
};
|
};
|
||||||
use crate::errors::CompilerErrorAtLine;
|
use crate::errors::CompilerErrorAtLine;
|
||||||
use crate::tokens::TokenType::{
|
use crate::tokens::TokenType::{
|
||||||
Bang, Bool, Char, Colon, Date, Eof, Eol, Equal, F32, F64, False, FloatingPoint, Fn, Greater,
|
Bang, Bool, Char, Colon, Date, Eof, Eol, Equal, False, FloatingPoint, Fn, Greater, GreaterEqual, GreaterGreater,
|
||||||
GreaterEqual, GreaterGreater, I32, I64, Identifier, Indent, Integer, LeftBrace, LeftBracket,
|
Identifier, Indent, Integer, LeftBrace, LeftBracket, LeftParen, Less, LessEqual, LessLess,
|
||||||
LeftParen, Less, LessEqual, LessLess, Let, ListType, MapType, Minus, Object, Plus, Print,
|
Let, ListType, MapType, Minus, Object, Plus, Print, RightBrace, RightBracket, RightParen, SignedInteger,
|
||||||
RightBrace, RightBracket, RightParen, SignedInteger, SingleRightArrow, Slash, Star, StringType,
|
SingleRightArrow, Slash, Star, StringType, True, UnsignedInteger, F32, F64,
|
||||||
True, U32, U64, UnsignedInteger,
|
I32, I64, U32, U64,
|
||||||
};
|
};
|
||||||
use crate::tokens::{Token, TokenType};
|
use crate::tokens::{Token, TokenType};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
|
|
||||||
54
src/file_watch.rs
Normal file
54
src/file_watch.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
use crate::chunk::Chunk;
|
||||||
|
use crate::compile_sourcedir;
|
||||||
|
use log4rs::append::Append;
|
||||||
|
use notify::{RecursiveMode, Watcher};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::hash::Hash;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::mpsc::channel;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
|
use arc_swap::ArcSwap;
|
||||||
|
|
||||||
|
const ONE_SEC: Duration = Duration::from_secs(1);
|
||||||
|
|
||||||
|
pub fn start_watch_daemon(source: &str, registry: Arc<ArcSwap<HashMap<String, Chunk>>>) {
|
||||||
|
let source = source.to_string();
|
||||||
|
let s = source.to_string();
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
thread::spawn(move || {
|
||||||
|
println!("-- File watch started --");
|
||||||
|
let path = Path::new(&source);
|
||||||
|
if !path.exists() {
|
||||||
|
panic!("source directory {} does not exist", &source);
|
||||||
|
}
|
||||||
|
let mut watcher = notify::recommended_watcher(tx).expect("Failed to create watcher");
|
||||||
|
watcher
|
||||||
|
.watch(path, RecursiveMode::Recursive)
|
||||||
|
.expect("Failed to watch");
|
||||||
|
loop {
|
||||||
|
thread::sleep(Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread::spawn(move || {
|
||||||
|
let mut file_changed = false;
|
||||||
|
loop {
|
||||||
|
let start = SystemTime::now();
|
||||||
|
loop {
|
||||||
|
thread::sleep(Duration::from_millis(50));
|
||||||
|
if let Ok(_) = rx.recv() {
|
||||||
|
file_changed = true;
|
||||||
|
}
|
||||||
|
if file_changed && SystemTime::now().duration_since(start).unwrap() > ONE_SEC {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("refresh"); // TODO implement refresh source
|
||||||
|
let new_registry = Arc::new(compile_sourcedir(&s).unwrap());
|
||||||
|
|
||||||
|
registry.store(new_registry.clone());
|
||||||
|
file_changed = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
11
src/lib.rs
11
src/lib.rs
|
|
@ -6,6 +6,8 @@ use crate::value::Value;
|
||||||
use crate::vm::interpret;
|
use crate::vm::interpret;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use arc_swap::ArcSwap;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub mod ast_compiler;
|
pub mod ast_compiler;
|
||||||
|
|
@ -19,6 +21,7 @@ mod tokens;
|
||||||
mod value;
|
mod value;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
pub mod repl;
|
pub mod repl;
|
||||||
|
pub mod file_watch;
|
||||||
|
|
||||||
pub fn compile_sourcedir(source_dir: &str) -> Result<HashMap<String, Chunk>, CrudLangError> {
|
pub fn compile_sourcedir(source_dir: &str) -> Result<HashMap<String, Chunk>, CrudLangError> {
|
||||||
let mut registry = HashMap::new();
|
let mut registry = HashMap::new();
|
||||||
|
|
@ -26,12 +29,13 @@ pub fn compile_sourcedir(source_dir: &str) -> Result<HashMap<String, Chunk>, Cru
|
||||||
for entry in WalkDir::new(source_dir).into_iter().filter_map(|e| e.ok()) {
|
for entry in WalkDir::new(source_dir).into_iter().filter_map(|e| e.ok()) {
|
||||||
let path = entry.path().to_str().unwrap();
|
let path = entry.path().to_str().unwrap();
|
||||||
if path.ends_with(".crud") {
|
if path.ends_with(".crud") {
|
||||||
print!("compiling {:?}: ", path);
|
print!("-- Compiling ");
|
||||||
let source = fs::read_to_string(path).map_err(map_underlying())?;
|
let source = fs::read_to_string(path).map_err(map_underlying())?;
|
||||||
let tokens = scan(&source)?;
|
let tokens = scan(&source)?;
|
||||||
match ast_compiler::compile(Some(&path), tokens) {
|
match ast_compiler::compile(Some(&path), tokens) {
|
||||||
Ok(statements) => {
|
Ok(statements) => {
|
||||||
let path = path.strip_prefix("source/").unwrap().replace(".crud", "");
|
println!("{}",path);
|
||||||
|
let path = path.strip_prefix(source_dir).unwrap().replace(".crud", "");
|
||||||
bytecode_compiler::compile(Some(&path), &statements, &mut registry)?;
|
bytecode_compiler::compile(Some(&path), &statements, &mut registry)?;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -62,5 +66,6 @@ fn run(src: &str) -> Result<Value, CrudLangError> {
|
||||||
let mut registry = HashMap::new();
|
let mut registry = HashMap::new();
|
||||||
let ast = ast_compiler::compile(None, tokens)?;
|
let ast = ast_compiler::compile(None, tokens)?;
|
||||||
bytecode_compiler::compile(None, &ast, &mut registry)?;
|
bytecode_compiler::compile(None, &ast, &mut registry)?;
|
||||||
interpret(®istry, "main").map_err(CrudLangError::from)
|
let registry = ArcSwap::from(Arc::new(registry));
|
||||||
|
interpret(registry.load(), "main").map_err(CrudLangError::from)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
src/main.rs
35
src/main.rs
|
|
@ -8,8 +8,10 @@ use crudlang::errors::CrudLangError;
|
||||||
use crudlang::errors::CrudLangError::Platform;
|
use crudlang::errors::CrudLangError::Platform;
|
||||||
use crudlang::vm::interpret_async;
|
use crudlang::vm::interpret_async;
|
||||||
use crudlang::{compile_sourcedir, map_underlying};
|
use crudlang::{compile_sourcedir, map_underlying};
|
||||||
|
use notify::Watcher;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use arc_swap::ArcSwap;
|
||||||
|
|
||||||
/// A simple CLI tool to greet users
|
/// A simple CLI tool to greet users
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
|
@ -19,6 +21,9 @@ struct Args {
|
||||||
|
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
source: Option<String>,
|
source: Option<String>,
|
||||||
|
|
||||||
|
#[arg(short, long)]
|
||||||
|
watch: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
@ -26,17 +31,19 @@ async fn main() -> Result<(), CrudLangError> {
|
||||||
println!("-- Crudlang --");
|
println!("-- Crudlang --");
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
let source = args.source.unwrap_or("source".to_string());
|
let source = args.source.unwrap_or("./source".to_string());
|
||||||
let registry = compile_sourcedir(&source)?;
|
let registry = compile_sourcedir(&source)?;
|
||||||
|
|
||||||
let registry = Arc::new(registry);
|
|
||||||
|
|
||||||
if !registry.is_empty() {
|
if !registry.is_empty() {
|
||||||
println!("-- Compilation successful -- Starting server --");
|
let swap = Arc::new(ArcSwap::from(Arc::new(registry)));
|
||||||
let state = Arc::new(AppState {
|
if args.watch {
|
||||||
registry: registry.clone(),
|
crudlang::file_watch::start_watch_daemon(&source, swap.clone());
|
||||||
});
|
}
|
||||||
|
println!("-- Compilation successful --");
|
||||||
|
let state =AppState {
|
||||||
|
registry: swap.clone(),
|
||||||
|
};
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/", any(handle_any).with_state(state.clone()))
|
.route("/", any(handle_any).with_state(state.clone()))
|
||||||
.route("/{*path}", any(handle_any).with_state(state.clone()));
|
.route("/{*path}", any(handle_any).with_state(state.clone()));
|
||||||
|
|
@ -46,12 +53,12 @@ async fn main() -> Result<(), CrudLangError> {
|
||||||
.map_err(map_underlying())?;
|
.map_err(map_underlying())?;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"listening on {}\n",
|
"-- Listening on {} --\n",
|
||||||
listener.local_addr().map_err(map_underlying())?
|
listener.local_addr().map_err(map_underlying())?
|
||||||
);
|
);
|
||||||
|
|
||||||
if args.repl {
|
if args.repl {
|
||||||
std::thread::spawn(move || crudlang::repl::start(registry).unwrap());
|
std::thread::spawn(move || crudlang::repl::start(swap.load()).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
axum::serve(listener, app).await.map_err(map_underlying())?;
|
axum::serve(listener, app).await.map_err(map_underlying())?;
|
||||||
|
|
@ -65,11 +72,11 @@ async fn main() -> Result<(), CrudLangError> {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AppState {
|
struct AppState {
|
||||||
registry: Arc<HashMap<String, Chunk>>,
|
registry: Arc<ArcSwap<HashMap<String, Chunk>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_any(
|
async fn handle_any(
|
||||||
State(state): State<Arc<AppState>>,
|
State(state): State<AppState>,
|
||||||
req: Request,
|
req: Request,
|
||||||
) -> Result<Json<String>, StatusCode> {
|
) -> Result<Json<String>, StatusCode> {
|
||||||
let method = req.method().to_string().to_ascii_lowercase();
|
let method = req.method().to_string().to_ascii_lowercase();
|
||||||
|
|
@ -84,7 +91,7 @@ async fn handle_any(
|
||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let component = format!("{}/web", &uri.path()[1..]);
|
let component = format!("{}/web", &uri.path());
|
||||||
let function_qname = format!("{}.{}", component, method);
|
let function_qname = format!("{}.{}", component, method);
|
||||||
|
|
||||||
let mut headers = HashMap::new();
|
let mut headers = HashMap::new();
|
||||||
|
|
@ -93,7 +100,7 @@ async fn handle_any(
|
||||||
}
|
}
|
||||||
let path = &req.uri().to_string();
|
let path = &req.uri().to_string();
|
||||||
match interpret_async(
|
match interpret_async(
|
||||||
&state.registry,
|
state.registry.load(),
|
||||||
&function_qname,
|
&function_qname,
|
||||||
path,
|
path,
|
||||||
query_params,
|
query_params,
|
||||||
|
|
@ -104,7 +111,7 @@ async fn handle_any(
|
||||||
Ok(value) => Ok(Json(value.to_string())),
|
Ok(value) => Ok(Json(value.to_string())),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// url checks out but function for method not found
|
// url checks out but function for method not found
|
||||||
if state.registry.get(&format!("{}.main", component)).is_some() {
|
if state.registry.load().get(&format!("{}.main", component)).is_some() {
|
||||||
Err(StatusCode::METHOD_NOT_ALLOWED)
|
Err(StatusCode::METHOD_NOT_ALLOWED)
|
||||||
} else {
|
} else {
|
||||||
Err(StatusCode::NOT_FOUND)
|
Err(StatusCode::NOT_FOUND)
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@ use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use arc_swap::{ArcSwap, Guard};
|
||||||
|
|
||||||
pub fn start(registry: Arc<HashMap<String, Chunk>>) -> Result<(), CrudLangError> {
|
pub fn start(registry: Guard<Arc<HashMap<String, Chunk>>>) -> Result<(), CrudLangError> {
|
||||||
println!("REPL started -- Type ctrl-c to exit (both the repl and the server)");
|
println!("REPL started -- Type ctrl-c to exit (both the repl and the server)");
|
||||||
println!(":h for help");
|
println!(":h for help");
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -20,7 +21,7 @@ pub fn start(registry: Arc<HashMap<String, Chunk>>) -> Result<(), CrudLangError>
|
||||||
match input {
|
match input {
|
||||||
":h" => help(),
|
":h" => help(),
|
||||||
":le" => list_endpoints(registry.clone()),
|
":le" => list_endpoints(registry.clone()),
|
||||||
":lf" => list_functions(registry.clone()),
|
":lf" => list_endpoints(registry.clone()),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
// println!("[{}]",input);
|
// println!("[{}]",input);
|
||||||
|
|
|
||||||
18
src/vm.rs
18
src/vm.rs
|
|
@ -5,17 +5,19 @@ use crate::tokens::TokenType;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use axum::http::{Uri};
|
use axum::http::{Uri};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use arc_swap::Guard;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
pub struct Vm<'a> {
|
pub struct Vm {
|
||||||
ip: usize,
|
ip: usize,
|
||||||
stack: Vec<Value>,
|
stack: Vec<Value>,
|
||||||
local_vars: HashMap<String, Value>,
|
local_vars: HashMap<String, Value>,
|
||||||
error_occurred: bool,
|
error_occurred: bool,
|
||||||
registry: &'a HashMap<String, Chunk>,
|
registry: Arc<HashMap<String, Chunk>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpret(registry: &HashMap<String, Chunk>, function: &str) -> Result<Value, RuntimeError> {
|
pub fn interpret(registry: Guard<Arc<HashMap<String, Chunk>>>, function: &str) -> Result<Value, RuntimeError> {
|
||||||
let chunk = registry.get(function).unwrap().clone();
|
let chunk = registry.get(function).unwrap().clone();
|
||||||
// for (key,value) in registry.iter() {
|
// for (key,value) in registry.iter() {
|
||||||
// println!("{}", key);
|
// println!("{}", key);
|
||||||
|
|
@ -26,13 +28,13 @@ pub fn interpret(registry: &HashMap<String, Chunk>, function: &str) -> Result<Va
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
local_vars: HashMap::new(),
|
local_vars: HashMap::new(),
|
||||||
error_occurred: false,
|
error_occurred: false,
|
||||||
registry,
|
registry: registry.clone(),
|
||||||
};
|
};
|
||||||
vm.run(&chunk)
|
vm.run(&chunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn interpret_async(
|
pub async fn interpret_async(
|
||||||
registry: &HashMap<String, Chunk>,
|
registry: Guard<Arc<HashMap<String, Chunk>>>,
|
||||||
function: &str,
|
function: &str,
|
||||||
uri: &str,
|
uri: &str,
|
||||||
query_params: HashMap<String, String>,
|
query_params: HashMap<String, String>,
|
||||||
|
|
@ -46,7 +48,7 @@ pub async fn interpret_async(
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
local_vars: HashMap::new(),
|
local_vars: HashMap::new(),
|
||||||
error_occurred: false,
|
error_occurred: false,
|
||||||
registry,
|
registry:registry.clone(),
|
||||||
};
|
};
|
||||||
vm.local_vars
|
vm.local_vars
|
||||||
.insert("path".to_string(), Value::String(uri.into()));
|
.insert("path".to_string(), Value::String(uri.into()));
|
||||||
|
|
@ -73,13 +75,13 @@ pub fn interpret_function(chunk: &Chunk, args: Vec<Value>) -> Result<Value, Runt
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
local_vars: HashMap::new(),
|
local_vars: HashMap::new(),
|
||||||
error_occurred: false,
|
error_occurred: false,
|
||||||
registry: &HashMap::new(),
|
registry: Arc::new(HashMap::new()),
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.run_function(chunk, args)
|
vm.run_function(chunk, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Vm<'a> {
|
impl Vm {
|
||||||
fn run_function(&mut self, chunk: &Chunk, mut args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn run_function(&mut self, chunk: &Chunk, mut args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
// arguments -> locals
|
// arguments -> locals
|
||||||
for (_, name) in chunk.vars.iter() {
|
for (_, name) in chunk.vars.iter() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue