mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-21 18:10:42 -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 crate::ast::*;
|
||||
use crate::build::assets;
|
||||
use crate::build::{FileBuilder, Val};
|
||||
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,
|
||||
builder: RefCell<FileBuilder<'a>>,
|
||||
builder: RefCell<FileBuilder<'a, C>>,
|
||||
}
|
||||
|
||||
impl<'a> ExpressionFormatter<'a> {
|
||||
pub fn new<S: Into<String>>(tmpl: S, builder: FileBuilder<'a>) -> Self {
|
||||
impl<'a, C> ExpressionFormatter<'a, C>
|
||||
where
|
||||
C: assets::Cache,
|
||||
{
|
||||
pub fn new<S: Into<String>>(tmpl: S, builder: FileBuilder<'a, C>) -> Self {
|
||||
ExpressionFormatter {
|
||||
tmpl: tmpl.into(),
|
||||
builder: RefCell::new(builder),
|
||||
@ -100,7 +107,7 @@ impl<'a> ExpressionFormatter<'a> {
|
||||
|
||||
fn consume_expr(
|
||||
&self,
|
||||
builder: &mut FileBuilder,
|
||||
builder: &mut FileBuilder<'a, C>,
|
||||
iter: &mut Chars,
|
||||
pos: &Position,
|
||||
) -> 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>> {
|
||||
let mut buf = String::new();
|
||||
let mut should_escape = false;
|
||||
|
@ -53,11 +53,14 @@ enum ProcessingOpType {
|
||||
|
||||
impl FuncDef {
|
||||
/// Expands a ucg function using the given arguments into a new Val.
|
||||
pub fn eval(
|
||||
pub fn eval<C>(
|
||||
&self,
|
||||
parent_builder: &FileBuilder,
|
||||
parent_builder: &FileBuilder<C>,
|
||||
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
|
||||
// func call error.
|
||||
if args.len() > self.argdefs.len() {
|
||||
@ -98,7 +101,10 @@ pub struct AssertCollector {
|
||||
}
|
||||
|
||||
/// 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,
|
||||
std: Rc<HashMap<String, &'static str>>,
|
||||
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
|
||||
// so multiple imports of the same file don't have to be parsed
|
||||
// multiple times.
|
||||
assets: Rc<RefCell<assets::Cache>>,
|
||||
assets: Rc<RefCell<C>>,
|
||||
pub is_module: bool,
|
||||
pub last: Option<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.
|
||||
pub fn new<P: Into<PathBuf>>(
|
||||
working_dir: P,
|
||||
import_paths: &'a Vec<PathBuf>,
|
||||
cache: Rc<RefCell<assets::Cache>>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
) -> Self {
|
||||
let env_vars: Vec<(String, String)> = env::vars().collect();
|
||||
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.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
use super::assets;
|
||||
use super::assets::MemoryCache;
|
||||
use super::{FileBuilder, SelectDef, Val};
|
||||
use crate::ast::*;
|
||||
@ -19,7 +20,10 @@ use std;
|
||||
use std::cell::RefCell;
|
||||
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..) {
|
||||
assert_eq!(
|
||||
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())
|
||||
}
|
||||
|
||||
fn build_file<'a>(
|
||||
fn build_file<'a, C: Cache>(
|
||||
file: &'a str,
|
||||
validate: bool,
|
||||
strict: bool,
|
||||
import_paths: &'a Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
) -> Result<build::FileBuilder<'a>, Box<dyn Error>> {
|
||||
cache: Rc<RefCell<C>>,
|
||||
) -> Result<build::FileBuilder<'a, C>, Box<dyn Error>> {
|
||||
let mut file_path_buf = PathBuf::from(file);
|
||||
if file_path_buf.is_relative() {
|
||||
file_path_buf = std::env::current_dir()?.join(file_path_buf);
|
||||
@ -116,11 +116,11 @@ fn build_file<'a>(
|
||||
Ok(builder)
|
||||
}
|
||||
|
||||
fn do_validate(
|
||||
fn do_validate<C: Cache>(
|
||||
file: &str,
|
||||
strict: bool,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
) -> bool {
|
||||
println!("Validating {}", file);
|
||||
match build_file(file, true, strict, import_paths, cache) {
|
||||
@ -140,11 +140,11 @@ fn do_validate(
|
||||
return true;
|
||||
}
|
||||
|
||||
fn do_compile(
|
||||
fn do_compile<C: Cache>(
|
||||
file: &str,
|
||||
strict: bool,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
registry: &ConverterRegistry,
|
||||
) -> bool {
|
||||
println!("Building {}", file);
|
||||
@ -175,13 +175,13 @@ fn do_compile(
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ucg_files(
|
||||
fn visit_ucg_files<C: Cache>(
|
||||
path: &Path,
|
||||
recurse: bool,
|
||||
validate: bool,
|
||||
strict: bool,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
registry: &ConverterRegistry,
|
||||
) -> Result<bool, Box<dyn Error>> {
|
||||
let our_path = String::from(path.to_string_lossy());
|
||||
@ -252,10 +252,10 @@ fn visit_ucg_files(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn inspect_command(
|
||||
fn inspect_command<C: Cache>(
|
||||
matches: &clap::ArgMatches,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
registry: &ConverterRegistry,
|
||||
strict: bool,
|
||||
) {
|
||||
@ -315,10 +315,10 @@ fn inspect_command(
|
||||
}
|
||||
}
|
||||
|
||||
fn build_command(
|
||||
fn build_command<C: Cache>(
|
||||
matches: &clap::ArgMatches,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
registry: &ConverterRegistry,
|
||||
strict: bool,
|
||||
) {
|
||||
@ -414,10 +414,10 @@ fn fmt_command(matches: &clap::ArgMatches) -> std::result::Result<(), Box<dyn Er
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_command(
|
||||
fn test_command<C: Cache>(
|
||||
matches: &clap::ArgMatches,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
registry: &ConverterRegistry,
|
||||
strict: bool,
|
||||
) {
|
||||
@ -513,9 +513,9 @@ fn env_help() {
|
||||
);
|
||||
}
|
||||
|
||||
fn do_repl(
|
||||
fn do_repl<C: Cache>(
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
cache: Rc<RefCell<C>>,
|
||||
) -> std::result::Result<(), Box<dyn Error>> {
|
||||
let config = rustyline::Config::builder();
|
||||
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) {
|
||||
eprintln!("{}", e);
|
||||
process::exit(1);
|
||||
@ -590,7 +590,7 @@ fn repl(import_paths: &Vec<PathBuf>, cache: Rc<RefCell<Cache>>) {
|
||||
fn main() {
|
||||
let mut app = do_flags();
|
||||
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 mut import_paths = Vec::new();
|
||||
if let Some(mut p) = dirs::home_dir() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user