mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
parent
f26e26d2ad
commit
2b47ca8617
@ -19,8 +19,9 @@ use super::assets::MemoryCache;
|
||||
use super::Builder;
|
||||
|
||||
fn assert_build(input: &str) {
|
||||
let i_paths = Vec::new();
|
||||
let cache = MemoryCache::new();
|
||||
let mut b = Builder::new("<Eval>", Rc::new(RefCell::new(cache)));
|
||||
let mut b = Builder::new("<Eval>", &i_paths, Rc::new(RefCell::new(cache)));
|
||||
b.enable_validate_mode();
|
||||
b.eval_string(input).unwrap();
|
||||
if !b.assert_collector.success {
|
||||
|
@ -93,9 +93,9 @@ pub struct AssertCollector {
|
||||
}
|
||||
|
||||
/// Builder handles building ucg code for a single file.
|
||||
pub struct Builder {
|
||||
pub struct Builder<'a> {
|
||||
file: PathBuf,
|
||||
import_path: Vec<PathBuf>,
|
||||
import_path: &'a Vec<PathBuf>,
|
||||
validate_mode: bool,
|
||||
pub assert_collector: AssertCollector,
|
||||
strict: bool,
|
||||
@ -139,24 +139,36 @@ macro_rules! eval_binary_expr {
|
||||
};
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
impl<'a> Builder<'a> {
|
||||
/// Constructs a new Builder.
|
||||
pub fn new<P: Into<PathBuf>>(file: P, cache: Rc<RefCell<assets::Cache>>) -> Self {
|
||||
Self::new_with_scope(file, cache, HashMap::new())
|
||||
pub fn new<P: Into<PathBuf>>(
|
||||
file: P,
|
||||
import_paths: &'a Vec<PathBuf>,
|
||||
cache: Rc<RefCell<assets::Cache>>,
|
||||
) -> Self {
|
||||
Self::new_with_scope(file, import_paths, cache, HashMap::new())
|
||||
}
|
||||
|
||||
/// Constructs a new Builder with a provided scope.
|
||||
pub fn new_with_scope<P: Into<PathBuf>>(
|
||||
root: P,
|
||||
import_paths: &'a Vec<PathBuf>,
|
||||
cache: Rc<RefCell<assets::Cache>>,
|
||||
scope: ValueMap,
|
||||
) -> Self {
|
||||
let env_vars: Vec<(String, String)> = env::vars().collect();
|
||||
Self::new_with_env_and_scope(root, cache, scope, Rc::new(Val::Env(env_vars)))
|
||||
Self::new_with_env_and_scope(
|
||||
root,
|
||||
import_paths,
|
||||
cache,
|
||||
scope,
|
||||
Rc::new(Val::Env(env_vars)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_with_env_and_scope<P: Into<PathBuf>>(
|
||||
file: P,
|
||||
import_paths: &'a Vec<PathBuf>,
|
||||
cache: Rc<RefCell<assets::Cache>>,
|
||||
scope: ValueMap,
|
||||
env: Rc<Val>,
|
||||
@ -166,7 +178,7 @@ impl Builder {
|
||||
// Our import stack is initialized with ourself.
|
||||
import_stack: vec![file.to_string_lossy().to_string()],
|
||||
file: file,
|
||||
import_path: Vec::new(),
|
||||
import_path: import_paths,
|
||||
validate_mode: false,
|
||||
assert_collector: AssertCollector {
|
||||
success: true,
|
||||
@ -189,7 +201,7 @@ impl Builder {
|
||||
// Our import stack is initialized with ourself.
|
||||
import_stack: self.import_stack.clone(),
|
||||
file: file.into(),
|
||||
import_path: self.import_path.clone(),
|
||||
import_path: self.import_path,
|
||||
validate_mode: false,
|
||||
assert_collector: AssertCollector {
|
||||
success: true,
|
||||
@ -215,10 +227,6 @@ impl Builder {
|
||||
self.strict = to;
|
||||
}
|
||||
|
||||
pub fn set_import_paths(&mut self, paths: Vec<PathBuf>) {
|
||||
self.import_path = paths;
|
||||
}
|
||||
|
||||
pub fn prepend_import_stack(&mut self, imports: &Vec<String>) {
|
||||
let mut new_stack = self.import_stack.clone();
|
||||
new_stack.append(imports.clone().as_mut());
|
||||
|
@ -28,8 +28,9 @@ fn test_expr_to_val(mut cases: Vec<(Expression, Val)>, mut b: Builder) {
|
||||
#[test]
|
||||
#[should_panic(expected = "Expected Float")]
|
||||
fn test_eval_div_expr_fail() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
test_expr_to_val(
|
||||
vec![(
|
||||
Expression::Binary(BinaryOpDef {
|
||||
@ -53,8 +54,9 @@ fn test_eval_div_expr_fail() {
|
||||
#[test]
|
||||
#[should_panic(expected = "Expected Float")]
|
||||
fn test_eval_mul_expr_fail() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
test_expr_to_val(
|
||||
vec![(
|
||||
Expression::Binary(BinaryOpDef {
|
||||
@ -78,8 +80,9 @@ fn test_eval_mul_expr_fail() {
|
||||
#[test]
|
||||
#[should_panic(expected = "Expected Float")]
|
||||
fn test_eval_subtract_expr_fail() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
test_expr_to_val(
|
||||
vec![(
|
||||
Expression::Binary(BinaryOpDef {
|
||||
@ -102,8 +105,9 @@ fn test_eval_subtract_expr_fail() {
|
||||
#[test]
|
||||
#[should_panic(expected = "Expected Float")]
|
||||
fn test_eval_add_expr_fail() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
test_expr_to_val(
|
||||
vec![(
|
||||
Expression::Binary(BinaryOpDef {
|
||||
@ -126,8 +130,9 @@ fn test_eval_add_expr_fail() {
|
||||
|
||||
#[test]
|
||||
fn test_eval_simple_lookup_error() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
b.build_output
|
||||
.entry(value_node!("var1".to_string(), Position::new(1, 0, 0)))
|
||||
.or_insert(Rc::new(Val::Int(1)));
|
||||
@ -142,8 +147,9 @@ fn test_eval_simple_lookup_error() {
|
||||
#[test]
|
||||
#[should_panic(expected = "Unable to find binding tpl1")]
|
||||
fn test_expr_copy_no_such_tuple() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
test_expr_to_val(
|
||||
vec![(
|
||||
Expression::Copy(CopyDef {
|
||||
@ -163,8 +169,9 @@ fn test_expr_copy_no_such_tuple() {
|
||||
#[test]
|
||||
#[should_panic(expected = "Expected Tuple or Module got Int(1)")]
|
||||
fn test_expr_copy_not_a_tuple() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
b.build_output
|
||||
.entry(value_node!("tpl1".to_string(), Position::new(1, 0, 0)))
|
||||
.or_insert(Rc::new(Val::Int(1)));
|
||||
@ -187,8 +194,9 @@ fn test_expr_copy_not_a_tuple() {
|
||||
#[test]
|
||||
#[should_panic(expected = "Expected type Integer for field fld1 but got String")]
|
||||
fn test_expr_copy_field_type_error() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
b.build_output
|
||||
.entry(value_node!("tpl1".to_string(), Position::new(1, 0, 0)))
|
||||
.or_insert(Rc::new(Val::Tuple(vec![(
|
||||
@ -223,8 +231,9 @@ fn test_expr_copy_field_type_error() {
|
||||
#[test]
|
||||
#[should_panic(expected = "Unable to find binding arg1")]
|
||||
fn test_macro_hermetic() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
b.build_output
|
||||
.entry(value_node!("arg1".to_string(), Position::new(1, 0, 0)))
|
||||
.or_insert(Rc::new(Val::Str("bar".to_string())));
|
||||
@ -266,8 +275,9 @@ fn test_macro_hermetic() {
|
||||
#[test]
|
||||
#[should_panic(expected = "Expected String but got Integer in Select expression")]
|
||||
fn test_select_expr_not_a_string() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
b.build_output
|
||||
.entry(value_node!("foo".to_string(), Position::new(1, 0, 0)))
|
||||
.or_insert(Rc::new(Val::Int(4)));
|
||||
|
@ -205,8 +205,9 @@ mod exec_test {
|
||||
|
||||
#[test]
|
||||
fn convert_just_command_test() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
let conv = ExecConverter::new();
|
||||
b.eval_string(
|
||||
"let script = {
|
||||
@ -226,8 +227,9 @@ mod exec_test {
|
||||
|
||||
#[test]
|
||||
fn convert_command_with_env_test() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
let conv = ExecConverter::new();
|
||||
b.eval_string(
|
||||
"let script = {
|
||||
@ -254,8 +256,9 @@ mod exec_test {
|
||||
|
||||
#[test]
|
||||
fn convert_command_with_arg_test() {
|
||||
let i_paths = Vec::new();
|
||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), cache);
|
||||
let mut b = Builder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
||||
let conv = ExecConverter::new();
|
||||
b.eval_string(
|
||||
"let script = {
|
||||
|
67
src/main.rs
67
src/main.rs
@ -72,17 +72,18 @@ fn run_converter(c: &traits::Converter, v: Rc<Val>, f: Option<&str>) -> traits::
|
||||
c.convert(v, file.as_mut())
|
||||
}
|
||||
|
||||
fn build_file(
|
||||
file: &str,
|
||||
fn build_file<'a>(
|
||||
file: &'a str,
|
||||
validate: bool,
|
||||
strict: bool,
|
||||
import_paths: &'a Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
) -> Result<build::Builder, Box<Error>> {
|
||||
) -> Result<build::Builder<'a>, Box<Error>> {
|
||||
let mut file_path_buf = PathBuf::from(file);
|
||||
if file_path_buf.is_relative() {
|
||||
file_path_buf = std::env::current_dir().unwrap().join(file_path_buf);
|
||||
}
|
||||
let mut builder = build::Builder::new(file_path_buf, cache);
|
||||
let mut builder = build::Builder::new(file_path_buf, import_paths, cache);
|
||||
builder.set_strict(strict);
|
||||
if validate {
|
||||
builder.enable_validate_mode();
|
||||
@ -94,9 +95,14 @@ fn build_file(
|
||||
Ok(builder)
|
||||
}
|
||||
|
||||
fn do_validate(file: &str, strict: bool, cache: Rc<RefCell<Cache>>) -> bool {
|
||||
fn do_validate(
|
||||
file: &str,
|
||||
strict: bool,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
) -> bool {
|
||||
println!("Validating {}", file);
|
||||
match build_file(file, true, strict, cache) {
|
||||
match build_file(file, true, strict, import_paths, cache) {
|
||||
Ok(b) => {
|
||||
if b.assert_collector.success {
|
||||
println!("File {} Pass\n", file);
|
||||
@ -116,11 +122,12 @@ fn do_validate(file: &str, strict: bool, cache: Rc<RefCell<Cache>>) -> bool {
|
||||
fn do_compile(
|
||||
file: &str,
|
||||
strict: bool,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
registry: &ConverterRegistry,
|
||||
) -> bool {
|
||||
println!("Building {}", file);
|
||||
let builder = match build_file(file, false, strict, cache.clone()) {
|
||||
let builder = match build_file(file, false, strict, import_paths, cache.clone()) {
|
||||
Ok(builder) => builder,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
@ -152,6 +159,7 @@ fn visit_ucg_files(
|
||||
recurse: bool,
|
||||
validate: bool,
|
||||
strict: bool,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
registry: &ConverterRegistry,
|
||||
) -> Result<bool, Box<Error>> {
|
||||
@ -177,6 +185,7 @@ fn visit_ucg_files(
|
||||
recurse,
|
||||
validate,
|
||||
strict,
|
||||
import_paths,
|
||||
cache.clone(),
|
||||
registry,
|
||||
) {
|
||||
@ -185,28 +194,34 @@ fn visit_ucg_files(
|
||||
}
|
||||
} else {
|
||||
if validate && path_as_string.ends_with("_test.ucg") {
|
||||
if !do_validate(&path_as_string, strict, cache.clone()) {
|
||||
if !do_validate(&path_as_string, strict, import_paths, cache.clone()) {
|
||||
result = false;
|
||||
summary.push_str(format!("{} - FAIL\n", path_as_string).as_str())
|
||||
} else {
|
||||
summary.push_str(format!("{} - PASS\n", path_as_string).as_str())
|
||||
}
|
||||
} else if !validate && path_as_string.ends_with(".ucg") {
|
||||
if !do_compile(&path_as_string, strict, cache.clone(), registry) {
|
||||
if !do_compile(
|
||||
&path_as_string,
|
||||
strict,
|
||||
import_paths,
|
||||
cache.clone(),
|
||||
registry,
|
||||
) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if validate && our_path.ends_with("_test.ucg") {
|
||||
if !do_validate(&our_path, strict, cache) {
|
||||
if !do_validate(&our_path, strict, import_paths, cache) {
|
||||
result = false;
|
||||
summary.push_str(format!("{} - FAIL\n", our_path).as_str());
|
||||
} else {
|
||||
summary.push_str(format!("{} - PASS\n", &our_path).as_str());
|
||||
}
|
||||
} else if !validate {
|
||||
if !do_compile(&our_path, strict, cache, registry) {
|
||||
if !do_compile(&our_path, strict, import_paths, cache, registry) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
@ -219,6 +234,7 @@ fn visit_ucg_files(
|
||||
|
||||
fn inspect_command(
|
||||
matches: &clap::ArgMatches,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
registry: &ConverterRegistry,
|
||||
strict: bool,
|
||||
@ -226,7 +242,7 @@ fn inspect_command(
|
||||
let file = matches.value_of("INPUT").unwrap();
|
||||
let sym = matches.value_of("sym");
|
||||
let target = matches.value_of("target").unwrap();
|
||||
let mut builder = build::Builder::new(file, cache);
|
||||
let mut builder = build::Builder::new(file, import_paths, cache);
|
||||
builder.set_strict(strict);
|
||||
match registry.get_converter(target) {
|
||||
Some(converter) => {
|
||||
@ -262,6 +278,7 @@ fn inspect_command(
|
||||
|
||||
fn build_command(
|
||||
matches: &clap::ArgMatches,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
registry: &ConverterRegistry,
|
||||
strict: bool,
|
||||
@ -276,6 +293,7 @@ fn build_command(
|
||||
recurse,
|
||||
false,
|
||||
strict,
|
||||
import_paths,
|
||||
cache.clone(),
|
||||
®istry,
|
||||
);
|
||||
@ -286,7 +304,15 @@ fn build_command(
|
||||
}
|
||||
for file in files.unwrap() {
|
||||
let pb = PathBuf::from(file);
|
||||
if let Ok(false) = visit_ucg_files(&pb, recurse, false, strict, cache.clone(), ®istry) {
|
||||
if let Ok(false) = visit_ucg_files(
|
||||
&pb,
|
||||
recurse,
|
||||
false,
|
||||
strict,
|
||||
import_paths,
|
||||
cache.clone(),
|
||||
®istry,
|
||||
) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
@ -297,6 +323,7 @@ fn build_command(
|
||||
|
||||
fn test_command(
|
||||
matches: &clap::ArgMatches,
|
||||
import_paths: &Vec<PathBuf>,
|
||||
cache: Rc<RefCell<Cache>>,
|
||||
registry: &ConverterRegistry,
|
||||
strict: bool,
|
||||
@ -310,6 +337,7 @@ fn test_command(
|
||||
recurse,
|
||||
true,
|
||||
strict,
|
||||
import_paths,
|
||||
cache.clone(),
|
||||
®istry,
|
||||
);
|
||||
@ -326,6 +354,7 @@ fn test_command(
|
||||
recurse,
|
||||
true,
|
||||
strict,
|
||||
import_paths,
|
||||
cache.clone(),
|
||||
®istry,
|
||||
) {
|
||||
@ -355,17 +384,23 @@ fn main() {
|
||||
let app_matches = app.clone().get_matches();
|
||||
let cache: Rc<RefCell<Cache>> = Rc::new(RefCell::new(MemoryCache::new()));
|
||||
let registry = ConverterRegistry::make_registry();
|
||||
let mut import_paths = Vec::new();
|
||||
if let Ok(path_list_str) = std::env::var("UCG_IMPORT_PATH") {
|
||||
for p in std::env::split_paths(&path_list_str) {
|
||||
import_paths.push(p);
|
||||
}
|
||||
}
|
||||
let strict = if app_matches.is_present("nostrict") {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
};
|
||||
if let Some(matches) = app_matches.subcommand_matches("inspect") {
|
||||
inspect_command(matches, cache, ®istry, strict);
|
||||
inspect_command(matches, &import_paths, cache, ®istry, strict);
|
||||
} else if let Some(matches) = app_matches.subcommand_matches("build") {
|
||||
build_command(matches, cache, ®istry, strict);
|
||||
build_command(matches, &import_paths, cache, ®istry, strict);
|
||||
} else if let Some(matches) = app_matches.subcommand_matches("test") {
|
||||
test_command(matches, cache, ®istry, strict);
|
||||
test_command(matches, &import_paths, cache, ®istry, strict);
|
||||
} else if let Some(_) = app_matches.subcommand_matches("converters") {
|
||||
converters_command(®istry)
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user