I think I only now settled on my plan. Anyway, daily update
This commit is contained in:
parent
6ec1a49a00
commit
374d2aef06
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -330,9 +330,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.8.5"
|
version = "0.8.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
|
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler2",
|
"adler2",
|
||||||
]
|
]
|
||||||
@ -348,6 +348,10 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mtgott"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.36.7"
|
version = "0.36.7"
|
||||||
@ -529,9 +533,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.14.0"
|
version = "1.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
|
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
@ -582,9 +586,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.44.1"
|
version = "1.44.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
|
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"libc",
|
"libc",
|
||||||
@ -763,6 +767,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"json5",
|
"json5",
|
||||||
|
"mtgott",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "yyyi_ru"
|
name = "yyyi_ru"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.8.3"
|
axum = "0.8.3"
|
||||||
tokio = { version = "1.44.1", features = ["rt-multi-thread"] }
|
tokio = { version = "1.44.1", features = ["rt-multi-thread"] }
|
||||||
json5 = "0.4.1"
|
json5 = "0.4.1"
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.140"
|
||||||
|
mtgott = { path = "./mtgott" }
|
||||||
|
|||||||
7
mtgott/Cargo.lock
generated
Normal file
7
mtgott/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mtgott"
|
||||||
|
version = "0.1.0"
|
||||||
4
mtgott/Cargo.toml
Normal file
4
mtgott/Cargo.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
name = "mtgott"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
8
mtgott/src/bin/PRIKOL.rs
Normal file
8
mtgott/src/bin/PRIKOL.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let func : & dyn for<'a> Fn(& 'a u32) -> &'a u32;
|
||||||
|
func = &|u: &u32| -> &u32 {u};
|
||||||
|
let y = 6u32;
|
||||||
|
println!("{}", func(&y));
|
||||||
|
}
|
||||||
50
mtgott/src/bin/mtgott_cli.rs
Normal file
50
mtgott/src/bin/mtgott_cli.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
extern crate mtgott;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::process;
|
||||||
|
use crate::mtgott::charclasses::is_bad_name;
|
||||||
|
use crate::mtgott::dirsearch::get_root_html;
|
||||||
|
use crate::mtgott::runtime::{Value, generate_template};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use mtgott::dirsearch::add_path_with_dots_to_root;
|
||||||
|
|
||||||
|
fn usage() -> ! {
|
||||||
|
eprintln!("Usage: program <path> [-D name value]...");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut args = env::args();
|
||||||
|
args.next().unwrap();
|
||||||
|
let path_arg = match args.next() { Some(s) => s, None => usage(), };
|
||||||
|
let template_name = match args.next() { Some(s) => s, None => usage(), };
|
||||||
|
let mut defines: Vec<(String, String)> = Vec::new();
|
||||||
|
while let Some(arg) = args.next() {
|
||||||
|
if arg == "-D" {
|
||||||
|
let name = match args.next() {
|
||||||
|
Some(n) => n,
|
||||||
|
None => usage()
|
||||||
|
};
|
||||||
|
let value = match args.next() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => usage()
|
||||||
|
};
|
||||||
|
for s in name.split('.') {
|
||||||
|
if is_bad_name(s) {
|
||||||
|
eprintln!("Bad name: {}", s);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defines.push((name, value));
|
||||||
|
} else {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut guest_root = Value::Dict(HashMap::new());
|
||||||
|
for (name_path, val) in defines {
|
||||||
|
add_path_with_dots_to_root(&mut guest_root, &name_path, Value::Str(val)).unwrap();
|
||||||
|
}
|
||||||
|
let dir_root = get_root_html(&path_arg).unwrap();
|
||||||
|
let res = generate_template(&dir_root, &guest_root, &template_name).unwrap();
|
||||||
|
print!("{res}")
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use std::{fs, io, fmt};
|
use std::{fs};
|
||||||
use std::fs::{read_dir, metadata, canonicalize};
|
use std::fs::{read_dir, metadata, canonicalize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
@ -6,7 +6,6 @@ use super::charclasses::{escape_for_html, is_bad_name};
|
|||||||
use super::runtime::{HigherLevelFunc, Value, DebugState, val_lambda_check_argc};
|
use super::runtime::{HigherLevelFunc, Value, DebugState, val_lambda_check_argc};
|
||||||
use super::parser::{parse_one_file_simplified, parse_one_file_packed};
|
use super::parser::{parse_one_file_simplified, parse_one_file_packed};
|
||||||
use super::lambda_compilation::{plemege_to_value};
|
use super::lambda_compilation::{plemege_to_value};
|
||||||
use std::rc::Rc;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn search_dir_rec_helper<F: Fn(&str) -> bool>(
|
pub fn search_dir_rec_helper<F: Fn(&str) -> bool>(
|
||||||
@ -46,7 +45,7 @@ pub fn search_dir_rec_helper<F: Fn(&str) -> bool>(
|
|||||||
pub fn search_dir<F: Fn(&str) -> bool>(p: &str, allowed_extensions: &[&str], is_valid_name: &F)
|
pub fn search_dir<F: Fn(&str) -> bool>(p: &str, allowed_extensions: &[&str], is_valid_name: &F)
|
||||||
-> Result<Vec<Vec<String>>, Box<dyn Error>> {
|
-> Result<Vec<Vec<String>>, Box<dyn Error>> {
|
||||||
let mut res: Vec<Vec<String>> = (0..allowed_extensions.len()).map(|_| Vec::new()).collect();
|
let mut res: Vec<Vec<String>> = (0..allowed_extensions.len()).map(|_| Vec::new()).collect();
|
||||||
search_dir_rec_helper(&mut res, PathBuf::new(), String::new(), allowed_extensions, is_valid_name, 100)?;
|
search_dir_rec_helper(&mut res, PathBuf::from(p), String::new(), allowed_extensions, is_valid_name, 100)?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,36 +68,45 @@ pub fn search_mtgott_dir(p: &str, plain_ext: &str) -> Result<MtgottDirContent, B
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Panics if somebody else borrowed root */
|
/* Panics if somebody else borrowed root. splitter is usually / or . */
|
||||||
fn add_path_to_root(root: &mut Value, slash_path: &str, obj: Value) -> Result<(), Box<dyn Error>> {
|
fn add_path_to_root(root: &mut Value, unsplit_path: &str, splitter: char, obj: Value) -> Result<(), Box<dyn Error>> {
|
||||||
let parts: Vec<&str> = slash_path.split('/').collect();
|
let parts: Vec<&str> = unsplit_path.split(splitter).collect();
|
||||||
let mut cur: &mut Value = root;
|
let mut cur: &mut Value = root;
|
||||||
assert!(parts.len() > 0);
|
assert!(parts.len() > 0);
|
||||||
for i in 0..parts.len() {
|
for i in 0usize..parts.len() {
|
||||||
match cur {
|
match cur {
|
||||||
Value::Dict(hashmap) => {
|
Value::Dict(hashmap) => {
|
||||||
cur = Rc::get_mut(hashmap).unwrap().entry(String::from(parts[i])).or_insert(Default::default());
|
cur = hashmap.entry(String::from(parts[i])).or_insert(Default::default());
|
||||||
}
|
}
|
||||||
_ => return Err(format!("Overlapping root elements {}", parts[..i].join("/")).into())
|
_ => return Err(format!("Overlapping root elements {}", parts[..i].join(&*splitter)).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match cur {
|
match cur {
|
||||||
Value::Int(x) if *x == 0 => {},
|
Value::Int(x) if *x == 0 => {},
|
||||||
_ => return Err(format!("Overlapping root elements {}", slash_path).into()),
|
_ => return Err(format!("Overlapping root elements {}", unsplit_path).into()),
|
||||||
}
|
}
|
||||||
|
*cur = obj;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_path_with_slashes_to_root(root: &mut Value, unsplit_path: &str, obj: Value) -> Result<(), Box<dyn Error>> {
|
||||||
|
add_path_to_root(root, unsplit_path, '/', obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_path_with_dots_to_root(root: &mut Value, unsplit_path: &str, obj: Value) -> Result<(), Box<dyn Error>> {
|
||||||
|
add_path_to_root(root, unsplit_path, '.', obj)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_all_templates(p: &str, plain_ext: &str) -> Result<Value, Box<dyn Error>> {
|
pub fn get_all_templates(p: &str, plain_ext: &str) -> Result<Value, Box<dyn Error>> {
|
||||||
let source = search_mtgott_dir(p, plain_ext)?;
|
let source = search_mtgott_dir(p, plain_ext)?;
|
||||||
let mut res: Value = Value::Dict(Rc::new(HashMap::new()));
|
let mut res: Value = Value::Dict(HashMap::new());
|
||||||
for cut_path in source.mtgott {
|
for cut_path in source.mtgott {
|
||||||
let path = format!("{cut_path}.mtgott{plain_ext}");
|
let path = format!("{cut_path}.mtgott{plain_ext}");
|
||||||
let text_bytes = fs::read(PathBuf::from(p).join(&path))?;
|
let text_bytes = fs::read(PathBuf::from(p).join(&path))?;
|
||||||
let text = std::str::from_utf8(&text_bytes)?;
|
let text = std::str::from_utf8(&text_bytes)?;
|
||||||
let plemege = parse_one_file_packed(text)?;
|
let plemege = parse_one_file_packed(text)?;
|
||||||
let compiled = plemege_to_value(plemege, &path)?;
|
let compiled = plemege_to_value(plemege, &path)?;
|
||||||
add_path_to_root(&mut res, &cut_path, compiled)?
|
add_path_to_root(&mut res, &cut_path, '/', compiled)?
|
||||||
}
|
}
|
||||||
for cut_path in source.imtgott {
|
for cut_path in source.imtgott {
|
||||||
let path = format!("{cut_path}.imtgott{plain_ext}");
|
let path = format!("{cut_path}.imtgott{plain_ext}");
|
||||||
@ -106,37 +114,37 @@ pub fn get_all_templates(p: &str, plain_ext: &str) -> Result<Value, Box<dyn Err
|
|||||||
let text = std::str::from_utf8(&text_bytes)?;
|
let text = std::str::from_utf8(&text_bytes)?;
|
||||||
let plemege = parse_one_file_simplified(text)?;
|
let plemege = parse_one_file_simplified(text)?;
|
||||||
let compiled = plemege_to_value(plemege, &path)?;
|
let compiled = plemege_to_value(plemege, &path)?;
|
||||||
add_path_to_root(&mut res, &cut_path, compiled)?
|
add_path_to_root(&mut res, &cut_path, '/', compiled)?
|
||||||
}
|
}
|
||||||
for cut_path in source.plain {
|
for cut_path in source.plain {
|
||||||
let path = format!("{cut_path}{plain_ext}");
|
let path = format!("{cut_path}{plain_ext}");
|
||||||
let text_bytes = fs::read(PathBuf::from(p).join(&path))?;
|
let text_bytes = fs::read(PathBuf::from(p).join(&path))?;
|
||||||
let text = String::from_utf8(text_bytes)?;
|
let text = String::from_utf8(text_bytes)?;
|
||||||
add_path_to_root(&mut res, &cut_path, Value::Str(Rc::new(text)))?
|
add_path_to_root(&mut res, &cut_path, '/', Value::Str(text))?
|
||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_templates_plus_builtins(p: &str, plain_ext: &str, sanitize: HigherLevelFunc) -> Result<Value, Box<dyn Error>>{
|
pub fn get_all_templates_plus_builtins(p: &str, plain_ext: &str, sanitize: HigherLevelFunc) -> Result<Value, Box<dyn Error>>{
|
||||||
let mut root = get_all_templates(p, plain_ext)?;
|
let mut root = get_all_templates(p, plain_ext)?;
|
||||||
add_path_to_root(&mut root, "sanitize", Value::Fn(sanitize))?;
|
add_path_with_slashes_to_root(&mut root, "sanitize", Value::Fn(sanitize))?;
|
||||||
add_path_to_root(&mut root, "cmd_tag_start", Value::Str(Rc::new(String::from("{%"))))?;
|
add_path_with_slashes_to_root(&mut root, "cmd_tag_start", Value::Str("{%".into()))?;
|
||||||
add_path_to_root(&mut root, "write_tag_start", Value::Str(Rc::new(String::from("{{"))))?;
|
add_path_with_slashes_to_root(&mut root, "write_tag_start", Value::Str("{{".into()))?;
|
||||||
add_path_to_root(&mut root, "roughinsert_tag_start", Value::Str(Rc::new(String::from("{["))))?;
|
add_path_with_slashes_to_root(&mut root, "roughinsert_tag_start", Value::Str("{[".into()))?;
|
||||||
add_path_to_root(&mut root, "magic_block_ending_tag", Value::Str(Rc::new(String::from("{%}"))))?;
|
add_path_with_slashes_to_root(&mut root, "magic_block_ending_tag", Value::Str("{%}".into()))?;
|
||||||
add_path_to_root(&mut root, "element_ending_tag", Value::Str(Rc::new(String::from("{@}"))))?;
|
add_path_with_slashes_to_root(&mut root, "element_ending_tag", Value::Str("{@}".into()))?;
|
||||||
Ok(root)
|
Ok(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_root_html(p: &str) -> Result<Value, Box<dyn Error>>{
|
pub fn get_root_html(p: &str) -> Result<Value, Box<dyn Error>>{
|
||||||
get_all_templates_plus_builtins(p, ".html", Rc::new(
|
get_all_templates_plus_builtins(p, ".html", Box::new(
|
||||||
|d_state: &DebugState, _: &Value, args: &[&Value]| -> Result<Value, Box<dyn Error>> {
|
|d_state: &DebugState, _: &Value, _: &Value, args: &[&Value]| -> Result<Value, Box<dyn Error>> {
|
||||||
let _g = d_state.register("In sanitizer".into());
|
let _g = d_state.register("In sanitizer".into());
|
||||||
val_lambda_check_argc(args, 1)?;
|
val_lambda_check_argc(args, 1)?;
|
||||||
match args[0]{
|
match args[0]{
|
||||||
Value::Str(s) => Ok(Value::Str(Rc::new(escape_for_html(&s)))),
|
Value::Str(s) => Ok(Value::Str(escape_for_html(&s))),
|
||||||
Value::Int(num) => Ok(Value::Str(Rc::new(num.to_string()))),
|
Value::Int(num) => Ok(Value::Str(num.to_string())),
|
||||||
_ => Ok(Value::Str(Rc::new(escape_for_html(&format!("{:?}", args[0])))))
|
_ => Ok(Value::Str(escape_for_html(&format!("{:?}", args[0]))))
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -2,7 +2,6 @@ use super::runtime::*;
|
|||||||
use super::parser::*;
|
use super::parser::*;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
fn cat_vec(arr: Vec<String>) -> String {
|
fn cat_vec(arr: Vec<String>) -> String {
|
||||||
let total_len: usize = arr.iter().map(|s| { s.len() }).sum();
|
let total_len: usize = arr.iter().map(|s| { s.len() }).sum();
|
||||||
@ -17,9 +16,10 @@ pub fn plemege_to_value(mut x: Plemege, file_path: &str) -> Result<Value, Box<dy
|
|||||||
for (key, thing) in map {
|
for (key, thing) in map {
|
||||||
new_dict.insert(key, plemege_to_value(thing, file_path)?);
|
new_dict.insert(key, plemege_to_value(thing, file_path)?);
|
||||||
}
|
}
|
||||||
Ok(Value::Dict(Rc::new(new_dict)))
|
Ok(Value::Dict(new_dict))
|
||||||
},
|
},
|
||||||
Plemege::Element(el) => {
|
Plemege::Element(el) => {
|
||||||
|
// Rc::new(|d_state: &DebugState, _: &Value, _: &Value, args: &[&Value]|)
|
||||||
// todo
|
// todo
|
||||||
Ok(Value::default())
|
Ok(Value::default())
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::mtgott::charclasses::{is_bad_name, is_digit, is_illegal_name, is_lnspace, is_normal_word_constituent, is_whitespace};
|
use crate::charclasses::{is_bad_name, is_digit, is_illegal_name, is_lnspace, is_normal_word_constituent, is_whitespace};
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ pub enum FileParsingErrorKind {
|
|||||||
recursion_limit_exceeded,
|
recursion_limit_exceeded,
|
||||||
}
|
}
|
||||||
|
|
||||||
use FileParsingErrorKind::*;
|
use self::FileParsingErrorKind::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct FileParsingError {
|
pub struct FileParsingError {
|
||||||
@ -396,7 +396,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
let fin_static = |p: &Parser, tp1: usize, res: &mut Vec<SubElement>| {
|
let fin_static = |p: &Parser, tp1: usize, res: &mut Vec<SubElement>| {
|
||||||
if tp1 < p.p {
|
if tp1 < p.p {
|
||||||
res.push(SubElement::Static(String::from(&self.text[tp1..p.p])))
|
res.push(SubElement::Static(String::from(&p.text[tp1..p.p])))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -421,9 +421,7 @@ impl<'a> Parser<'a> {
|
|||||||
if !matches!(expr, Expression::None){
|
if !matches!(expr, Expression::None){
|
||||||
res.push(SubElement::InsertExpr(
|
res.push(SubElement::InsertExpr(
|
||||||
Expression::Call(
|
Expression::Call(
|
||||||
Box::new(Expression::Attribute(
|
Box::new(Expression::ToplevelAttribute("sanitize".into())),
|
||||||
Box::new(Expression::Root), String::from("sanitize")
|
|
||||||
)),
|
|
||||||
vec![expr])
|
vec![expr])
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -663,7 +661,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
let mut bg: Expression = match arg_names.iter().rposition(|&n| n == toplevel_name) {
|
let mut bg: Expression = match arg_names.iter().rposition(|&n| n == toplevel_name) {
|
||||||
Some(i) => Expression::Argument(i as u64),
|
Some(i) => Expression::Argument(i as u64),
|
||||||
None => Expression::Attribute(Box::new(Expression::Root), String::from(toplevel_name))
|
None => Expression::ToplevelAttribute(toplevel_name.into())
|
||||||
};
|
};
|
||||||
loop {
|
loop {
|
||||||
self.skip_whitespace();
|
self.skip_whitespace();
|
||||||
@ -1,9 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::ops::{Index, IndexMut};
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
pub struct DebugStateGuard<'a> (
|
pub struct DebugStateGuard<'a> (
|
||||||
@ -27,16 +25,22 @@ impl<'a> DebugState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type HigherLevelFunc = Rc<dyn Fn(&DebugState, &Value, &[&Value]) -> Result<Value, Box<dyn Error>>>;
|
pub type HigherLevelFunc = Box<dyn Fn(&DebugState, &Value, &[&Value]) -> Result<Value, Box<dyn Error>>>;
|
||||||
|
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Str(Rc<String>),
|
Str(String),
|
||||||
Int(u64),
|
Int(u64),
|
||||||
Arr(Rc<Vec<Value>>),
|
Arr(Vec<Value>),
|
||||||
Dict(Rc<HashMap<String, Value>>),
|
Dict(HashMap<String, Value>),
|
||||||
Fn(HigherLevelFunc),
|
Fn(HigherLevelFunc),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Value {
|
||||||
|
fn as_dict(&self) -> &HashMap<String, Value> {
|
||||||
|
match self { Value::Dict(s) => s, _ => panic!(), }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Useful utility to put in every function you see */
|
/* Useful utility to put in every function you see */
|
||||||
pub fn val_lambda_check_argc(argv: &[&Value], argc_required: usize) -> Result<(), String> {
|
pub fn val_lambda_check_argc(argv: &[&Value], argc_required: usize) -> Result<(), String> {
|
||||||
if argv.len() == argc_required {
|
if argv.len() == argc_required {
|
||||||
@ -46,7 +50,6 @@ pub fn val_lambda_check_argc(argv: &[&Value], argc_required: usize) -> Result<()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Default for Value {
|
impl Default for Value {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Value::Int(0)
|
Value::Int(0)
|
||||||
@ -82,3 +85,46 @@ impl<'t> PartialEq for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_sub_value<'a>(root: &'a Value, name: &str) -> Result<&'a Value, String> {
|
||||||
|
let mut cur: &Value = root;
|
||||||
|
let parts = name.split(".").map(String::from).collect();
|
||||||
|
for i in 0usize..parts.len() {
|
||||||
|
match cur {
|
||||||
|
Value::Dict(hashmap) => {
|
||||||
|
match hashmap.get(&parts[i]) {
|
||||||
|
Some(nxt ) => { cur = nxt; }
|
||||||
|
None => return Err(format!("No such root element: {}", parts[..=i].join("/")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(format!("Not a dictionary: {}", parts[..i].join("/")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(cur)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If some `top-level-attribute` was not found in root, we search for it in guest_root.
|
||||||
|
* This is our way of passing arguments for template */
|
||||||
|
pub fn generate_template(root: &Value, guest_root: &Value, name: &str) -> Result<String, Box<dyn Error>> {
|
||||||
|
let main = get_sub_value(root, name)?;
|
||||||
|
let main = match main {
|
||||||
|
Value::Dict(p) => {
|
||||||
|
match p.get("main".into()) {
|
||||||
|
Some(v2) => v2,
|
||||||
|
None => return Err(Box::new(format!("Called {name} template is a dictionary without `main()`")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => main,
|
||||||
|
};
|
||||||
|
match main {
|
||||||
|
Value::Fn(main_func) => {
|
||||||
|
let d_stack = DebugState(RefCell::new(Vec::new()));
|
||||||
|
let rv = main_func(&d_stack, root, &[guest_root])?;
|
||||||
|
match rv {
|
||||||
|
Value::Str(answer) => Ok(answer),
|
||||||
|
_ => Err(Box::new(format!("template {name} returned not a string")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(Box::new(format!("Called {name} template that is not a function")))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,41 +0,0 @@
|
|||||||
use std::env;
|
|
||||||
use std::process;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use yyyi_ru::mtgott::charclasses::is_bad_name;
|
|
||||||
use yyyi_ru::mtgott::dirsearch::{search_dir};
|
|
||||||
|
|
||||||
fn usage() -> ! {
|
|
||||||
eprintln!("Usage: program <path> [-D name value]...");
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut args = env::args();
|
|
||||||
args.next().unwrap();
|
|
||||||
let path_arg = match args.next() {
|
|
||||||
Some(s) => s,
|
|
||||||
None => usage(),
|
|
||||||
};
|
|
||||||
let mut defines: Vec<(Vec<String>, String)> = Vec::new();
|
|
||||||
while let Some(arg) = args.next() {
|
|
||||||
if arg == "-D" {
|
|
||||||
let name = match args.next() {
|
|
||||||
Some(n) => n,
|
|
||||||
None => usage()
|
|
||||||
};
|
|
||||||
let value = match args.next() {
|
|
||||||
Some(v) => v,
|
|
||||||
None => usage()
|
|
||||||
};
|
|
||||||
defines.push((name.split('.').map(|s| {
|
|
||||||
if is_bad_name(s) {
|
|
||||||
eprintln!("Bad name: {}", s);
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
String::from(s)
|
|
||||||
}).collect(), value));
|
|
||||||
} else {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +1 @@
|
|||||||
pub mod yyyi_ru;
|
pub mod yyyi_ru;
|
||||||
pub mod mtgott;
|
|
||||||
Loading…
x
Reference in New Issue
Block a user