mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
Refactor: Use trait constraints instead of a trait object for our assets cache.
This commit is contained in:
parent
fc9595ab38
commit
1589aaf7d7
@ -19,6 +19,7 @@ use std::error::Error;
|
|||||||
use std::str::Chars;
|
use std::str::Chars;
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
use crate::build::assets;
|
||||||
use crate::build::{FileBuilder, Val};
|
use crate::build::{FileBuilder, Val};
|
||||||
use crate::error;
|
use crate::error;
|
||||||
|
|
||||||
@ -85,13 +86,19 @@ impl<V: Into<String> + Clone> FormatRenderer for SimpleFormatter<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ExpressionFormatter<'a> {
|
pub struct ExpressionFormatter<'a, C>
|
||||||
|
where
|
||||||
|
C: assets::Cache,
|
||||||
|
{
|
||||||
tmpl: String,
|
tmpl: String,
|
||||||
builder: RefCell<FileBuilder<'a>>,
|
builder: RefCell<FileBuilder<'a, C>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ExpressionFormatter<'a> {
|
impl<'a, C> ExpressionFormatter<'a, C>
|
||||||
pub fn new<S: Into<String>>(tmpl: S, builder: FileBuilder<'a>) -> Self {
|
where
|
||||||
|
C: assets::Cache,
|
||||||
|
{
|
||||||
|
pub fn new<S: Into<String>>(tmpl: S, builder: FileBuilder<'a, C>) -> Self {
|
||||||
ExpressionFormatter {
|
ExpressionFormatter {
|
||||||
tmpl: tmpl.into(),
|
tmpl: tmpl.into(),
|
||||||
builder: RefCell::new(builder),
|
builder: RefCell::new(builder),
|
||||||
@ -100,7 +107,7 @@ impl<'a> ExpressionFormatter<'a> {
|
|||||||
|
|
||||||
fn consume_expr(
|
fn consume_expr(
|
||||||
&self,
|
&self,
|
||||||
builder: &mut FileBuilder,
|
builder: &mut FileBuilder<'a, C>,
|
||||||
iter: &mut Chars,
|
iter: &mut Chars,
|
||||||
pos: &Position,
|
pos: &Position,
|
||||||
) -> Result<Val, Box<dyn Error>> {
|
) -> Result<Val, Box<dyn Error>> {
|
||||||
@ -176,7 +183,10 @@ impl<'a> ExpressionFormatter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FormatRenderer for ExpressionFormatter<'a> {
|
impl<'a, C> FormatRenderer for ExpressionFormatter<'a, C>
|
||||||
|
where
|
||||||
|
C: assets::Cache,
|
||||||
|
{
|
||||||
fn render(&self, pos: &Position) -> Result<String, Box<dyn Error>> {
|
fn render(&self, pos: &Position) -> Result<String, Box<dyn Error>> {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let mut should_escape = false;
|
let mut should_escape = false;
|
||||||
|
@ -53,11 +53,14 @@ enum ProcessingOpType {
|
|||||||
|
|
||||||
impl FuncDef {
|
impl FuncDef {
|
||||||
/// Expands a ucg function using the given arguments into a new Val.
|
/// Expands a ucg function using the given arguments into a new Val.
|
||||||
pub fn eval(
|
pub fn eval<C>(
|
||||||
&self,
|
&self,
|
||||||
parent_builder: &FileBuilder,
|
parent_builder: &FileBuilder<C>,
|
||||||
mut args: Vec<Rc<Val>>,
|
mut args: Vec<Rc<Val>>,
|
||||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
) -> Result<Rc<Val>, Box<dyn Error>>
|
||||||
|
where
|
||||||
|
C: assets::Cache,
|
||||||
|
{
|
||||||
// Error conditions. If the args don't match the length and types of the argdefs then this is
|
// Error conditions. If the args don't match the length and types of the argdefs then this is
|
||||||
// func call error.
|
// func call error.
|
||||||
if args.len() > self.argdefs.len() {
|
if args.len() > self.argdefs.len() {
|
||||||
@ -98,7 +101,10 @@ pub struct AssertCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builder handles building ucg code for a single file.
|
/// Builder handles building ucg code for a single file.
|
||||||
pub struct FileBuilder<'a> {
|
pub struct FileBuilder<'a, C>
|
||||||
|
where
|
||||||
|
C: assets::Cache,
|
||||||
|
{
|
||||||
working_dir: PathBuf,
|
working_dir: PathBuf,
|
||||||
std: Rc<HashMap<String, &'static str>>,
|
std: Rc<HashMap<String, &'static str>>,
|
||||||
import_path: &'a Vec<PathBuf>,
|
import_path: &'a Vec<PathBuf>,
|
||||||
@ -117,7 +123,7 @@ pub struct FileBuilder<'a> {
|
|||||||
// are keyed by the canonicalized import path. This acts as a cache
|
// are keyed by the canonicalized import path. This acts as a cache
|
||||||
// so multiple imports of the same file don't have to be parsed
|
// so multiple imports of the same file don't have to be parsed
|
||||||
// multiple times.
|
// multiple times.
|
||||||
assets: Rc<RefCell<assets::Cache>>,
|
assets: Rc<RefCell<C>>,
|
||||||
pub is_module: bool,
|
pub is_module: bool,
|
||||||
pub last: Option<Rc<Val>>,
|
pub last: Option<Rc<Val>>,
|
||||||
pub out_lock: Option<(String, Rc<Val>)>,
|
pub out_lock: Option<(String, Rc<Val>)>,
|
||||||
@ -141,12 +147,15 @@ macro_rules! eval_binary_expr {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FileBuilder<'a> {
|
impl<'a, C> FileBuilder<'a, C>
|
||||||
|
where
|
||||||
|
C: assets::Cache,
|
||||||
|
{
|
||||||
/// Constructs a new Builder.
|
/// Constructs a new Builder.
|
||||||
pub fn new<P: Into<PathBuf>>(
|
pub fn new<P: Into<PathBuf>>(
|
||||||
working_dir: P,
|
working_dir: P,
|
||||||
import_paths: &'a Vec<PathBuf>,
|
import_paths: &'a Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<assets::Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let env_vars: Vec<(String, String)> = env::vars().collect();
|
let env_vars: Vec<(String, String)> = env::vars().collect();
|
||||||
let scope = scope::Scope::new(Rc::new(Val::Env(env_vars)));
|
let scope = scope::Scope::new(Rc::new(Val::Env(env_vars)));
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
use super::assets;
|
||||||
use super::assets::MemoryCache;
|
use super::assets::MemoryCache;
|
||||||
use super::{FileBuilder, SelectDef, Val};
|
use super::{FileBuilder, SelectDef, Val};
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
@ -19,7 +20,10 @@ use std;
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
fn test_expr_to_val(mut cases: Vec<(Expression, Val)>, b: FileBuilder) {
|
fn test_expr_to_val<'a, C: assets::Cache>(
|
||||||
|
mut cases: Vec<(Expression, Val)>,
|
||||||
|
b: FileBuilder<'a, C>,
|
||||||
|
) {
|
||||||
for tpl in cases.drain(0..) {
|
for tpl in cases.drain(0..) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
b.eval_expr(&tpl.0, &b.scope.spawn_child()).unwrap(),
|
b.eval_expr(&tpl.0, &b.scope.spawn_child()).unwrap(),
|
||||||
|
38
src/main.rs
38
src/main.rs
@ -93,13 +93,13 @@ fn run_converter(c: &traits::Converter, v: Rc<Val>, f: Option<&str>) -> traits::
|
|||||||
c.convert(v, file.as_mut())
|
c.convert(v, file.as_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_file<'a>(
|
fn build_file<'a, C: Cache>(
|
||||||
file: &'a str,
|
file: &'a str,
|
||||||
validate: bool,
|
validate: bool,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &'a Vec<PathBuf>,
|
import_paths: &'a Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
) -> Result<build::FileBuilder<'a>, Box<dyn Error>> {
|
) -> Result<build::FileBuilder<'a, C>, Box<dyn Error>> {
|
||||||
let mut file_path_buf = PathBuf::from(file);
|
let mut file_path_buf = PathBuf::from(file);
|
||||||
if file_path_buf.is_relative() {
|
if file_path_buf.is_relative() {
|
||||||
file_path_buf = std::env::current_dir()?.join(file_path_buf);
|
file_path_buf = std::env::current_dir()?.join(file_path_buf);
|
||||||
@ -116,11 +116,11 @@ fn build_file<'a>(
|
|||||||
Ok(builder)
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_validate(
|
fn do_validate<C: Cache>(
|
||||||
file: &str,
|
file: &str,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
println!("Validating {}", file);
|
println!("Validating {}", file);
|
||||||
match build_file(file, true, strict, import_paths, cache) {
|
match build_file(file, true, strict, import_paths, cache) {
|
||||||
@ -140,11 +140,11 @@ fn do_validate(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_compile(
|
fn do_compile<C: Cache>(
|
||||||
file: &str,
|
file: &str,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
registry: &ConverterRegistry,
|
registry: &ConverterRegistry,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
println!("Building {}", file);
|
println!("Building {}", file);
|
||||||
@ -175,13 +175,13 @@ fn do_compile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ucg_files(
|
fn visit_ucg_files<C: Cache>(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
recurse: bool,
|
recurse: bool,
|
||||||
validate: bool,
|
validate: bool,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
registry: &ConverterRegistry,
|
registry: &ConverterRegistry,
|
||||||
) -> Result<bool, Box<dyn Error>> {
|
) -> Result<bool, Box<dyn Error>> {
|
||||||
let our_path = String::from(path.to_string_lossy());
|
let our_path = String::from(path.to_string_lossy());
|
||||||
@ -252,10 +252,10 @@ fn visit_ucg_files(
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inspect_command(
|
fn inspect_command<C: Cache>(
|
||||||
matches: &clap::ArgMatches,
|
matches: &clap::ArgMatches,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
registry: &ConverterRegistry,
|
registry: &ConverterRegistry,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
) {
|
) {
|
||||||
@ -315,10 +315,10 @@ fn inspect_command(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_command(
|
fn build_command<C: Cache>(
|
||||||
matches: &clap::ArgMatches,
|
matches: &clap::ArgMatches,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
registry: &ConverterRegistry,
|
registry: &ConverterRegistry,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
) {
|
) {
|
||||||
@ -414,10 +414,10 @@ fn fmt_command(matches: &clap::ArgMatches) -> std::result::Result<(), Box<dyn Er
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_command(
|
fn test_command<C: Cache>(
|
||||||
matches: &clap::ArgMatches,
|
matches: &clap::ArgMatches,
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
registry: &ConverterRegistry,
|
registry: &ConverterRegistry,
|
||||||
strict: bool,
|
strict: bool,
|
||||||
) {
|
) {
|
||||||
@ -513,9 +513,9 @@ fn env_help() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_repl(
|
fn do_repl<C: Cache>(
|
||||||
import_paths: &Vec<PathBuf>,
|
import_paths: &Vec<PathBuf>,
|
||||||
cache: Rc<RefCell<Cache>>,
|
cache: Rc<RefCell<C>>,
|
||||||
) -> std::result::Result<(), Box<dyn Error>> {
|
) -> std::result::Result<(), Box<dyn Error>> {
|
||||||
let config = rustyline::Config::builder();
|
let config = rustyline::Config::builder();
|
||||||
let mut editor = rustyline::Editor::<()>::with_config(
|
let mut editor = rustyline::Editor::<()>::with_config(
|
||||||
@ -580,7 +580,7 @@ fn do_repl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repl(import_paths: &Vec<PathBuf>, cache: Rc<RefCell<Cache>>) {
|
fn repl<C: Cache>(import_paths: &Vec<PathBuf>, cache: Rc<RefCell<C>>) {
|
||||||
if let Err(e) = do_repl(import_paths, cache) {
|
if let Err(e) = do_repl(import_paths, cache) {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
@ -590,7 +590,7 @@ fn repl(import_paths: &Vec<PathBuf>, cache: Rc<RefCell<Cache>>) {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut app = do_flags();
|
let mut app = do_flags();
|
||||||
let app_matches = app.clone().get_matches();
|
let app_matches = app.clone().get_matches();
|
||||||
let cache: Rc<RefCell<Cache>> = Rc::new(RefCell::new(MemoryCache::new()));
|
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||||
let registry = ConverterRegistry::make_registry();
|
let registry = ConverterRegistry::make_registry();
|
||||||
let mut import_paths = Vec::new();
|
let mut import_paths = Vec::new();
|
||||||
if let Some(mut p) = dirs::home_dir() {
|
if let Some(mut p) = dirs::home_dir() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user