mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-21 18:10:42 -04:00
DEV: Unify the path rewriting
This commit is contained in:
parent
3052f7d7a8
commit
159af40e7c
114
src/ast/mod.rs
114
src/ast/mod.rs
@ -605,64 +605,72 @@ impl ModuleDef {
|
||||
pub fn set_out_expr(&mut self, expr: Expression) {
|
||||
self.out_expr = Some(Box::new(expr));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn imports_to_absolute(&mut self, base: PathBuf) {
|
||||
&base;
|
||||
let rewrite_import = |e: &mut Expression| {
|
||||
let main_separator = format!("{}", std::path::MAIN_SEPARATOR);
|
||||
if let Expression::Include(ref mut def) = e {
|
||||
let path = PathBuf::from(&def.path.fragment);
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
if path.is_relative() {
|
||||
def.path.fragment = base
|
||||
.join(path)
|
||||
.canonicalize()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if path.is_relative() {
|
||||
def.path.fragment = base.join(path).to_string_lossy().to_string();
|
||||
}
|
||||
pub struct Rewriter {
|
||||
base: PathBuf,
|
||||
}
|
||||
|
||||
impl Rewriter {
|
||||
pub fn new<P: Into<PathBuf>>(base: P) -> Self {
|
||||
Self { base: base.into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl walk::Walker for Rewriter {
|
||||
fn visit_expression(&mut self, expr: &mut Expression) {
|
||||
// Rewrite all paths except for stdlib paths to absolute.
|
||||
let main_separator = format!("{}", std::path::MAIN_SEPARATOR);
|
||||
if let Expression::Include(ref mut def) = expr {
|
||||
let path = PathBuf::from(&def.path.fragment);
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
if path.is_relative() {
|
||||
def.path.fragment = self
|
||||
.base
|
||||
.join(path)
|
||||
.canonicalize()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
}
|
||||
}
|
||||
if let Expression::Import(ref mut def) = e {
|
||||
let path = PathBuf::from(
|
||||
&def.path
|
||||
.fragment
|
||||
.replace("/", &main_separator)
|
||||
.replace("\\", &main_separator),
|
||||
);
|
||||
// std/ paths are special and do not get made into absolute paths.
|
||||
if path.starts_with(format!("std{}", main_separator)) {
|
||||
return;
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
if path.is_relative() {
|
||||
def.path.fragment = base
|
||||
.join(path)
|
||||
.canonicalize()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if path.is_relative() {
|
||||
def.path.fragment = base.join(path).to_string_lossy().to_string();
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if path.is_relative() {
|
||||
def.path.fragment = self.base.join(path).to_string_lossy().to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Expression::Import(ref mut def) = expr {
|
||||
let path = PathBuf::from(
|
||||
&def.path
|
||||
.fragment
|
||||
.replace("/", &main_separator)
|
||||
.replace("\\", &main_separator),
|
||||
);
|
||||
// std/ paths are special and do not get made into absolute paths.
|
||||
if path.starts_with(format!("std{}", main_separator)) {
|
||||
return;
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
if path.is_relative() {
|
||||
def.path.fragment = self
|
||||
.base
|
||||
.join(path)
|
||||
.canonicalize()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if path.is_relative() {
|
||||
def.path.fragment = self.base.join(path).to_string_lossy().to_string();
|
||||
}
|
||||
}
|
||||
};
|
||||
let mut walker = walk::AstWalker::new().with_expr_handler(&rewrite_import);
|
||||
for stmt in self.statements.iter_mut() {
|
||||
walker.walk_statement(stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,23 +142,30 @@ pub trait Walker {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_import(&mut self, i: &mut ImportDef) {
|
||||
// TODO(jwall): Should this have exit versions as well?
|
||||
fn visit_import(&mut self, _i: &mut ImportDef) {
|
||||
// noop by default;
|
||||
}
|
||||
|
||||
fn visit_include(&mut self, i: &mut IncludeDef) {
|
||||
fn visit_include(&mut self, _i: &mut IncludeDef) {
|
||||
// noop by default;
|
||||
}
|
||||
|
||||
fn visit_fail(&mut self, f: &mut FailDef) {
|
||||
fn visit_fail(&mut self, _f: &mut FailDef) {
|
||||
// noop by default;
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, val: &mut Value);
|
||||
fn visit_value(&mut self, _val: &mut Value) {
|
||||
// noop by default
|
||||
}
|
||||
|
||||
fn visit_expression(&mut self, expr: &mut Expression);
|
||||
fn visit_expression(&mut self, _expr: &mut Expression) {
|
||||
// noop by default
|
||||
}
|
||||
|
||||
fn visit_statement(&mut self, stmt: &mut Statement);
|
||||
fn visit_statement(&mut self, _stmt: &mut Statement) {
|
||||
// noop by default
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this would be better implemented as a Trait I think.
|
||||
|
@ -90,8 +90,6 @@ where
|
||||
pub environment: &'a RefCell<Environment<Stdout, Stderr>>,
|
||||
working_dir: PathBuf,
|
||||
strict: bool,
|
||||
// FIXME(jwall): These need to be compiled and added to the op cache.
|
||||
// specifically in the environment.
|
||||
std: Rc<HashMap<String, &'static str>>,
|
||||
import_path: &'a Vec<PathBuf>,
|
||||
pub last: Option<Rc<Val>>,
|
||||
@ -303,12 +301,8 @@ where
|
||||
}
|
||||
|
||||
pub fn eval_expr(&mut self, expr: Expression) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||
let mut ops_map = translate::OpsMap::new();
|
||||
translate::AST::translate_stmt(
|
||||
Statement::Expression(expr),
|
||||
&mut ops_map,
|
||||
&self.working_dir,
|
||||
);
|
||||
let ops_map =
|
||||
translate::AST::translate(vec![Statement::Expression(expr)], &self.working_dir);
|
||||
let mut vm = VM::new(self.strict, Rc::new(ops_map), &self.working_dir);
|
||||
if self.validate_mode {
|
||||
vm.enable_validate_mode();
|
||||
|
@ -14,11 +14,11 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::ast::walk::Walker;
|
||||
use crate::ast::{
|
||||
BinaryExprType, BinaryOpDef, Expression, FormatArgs, Position, PositionedItem, SelectDef,
|
||||
Statement, Token, TokenType, Value,
|
||||
BinaryExprType, BinaryOpDef, Expression, FormatArgs, FuncOpDef, Position, PositionedItem,
|
||||
Rewriter, SelectDef, Statement, TemplatePart, Token, TokenType, Value,
|
||||
};
|
||||
use crate::ast::{FuncOpDef, TemplatePart};
|
||||
use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser};
|
||||
use crate::build::opcode::Primitive;
|
||||
use crate::build::opcode::{Hook, Op};
|
||||
@ -66,13 +66,16 @@ impl OpsMap {
|
||||
}
|
||||
|
||||
impl AST {
|
||||
pub fn translate<P: AsRef<Path>>(stmts: Vec<Statement>, root: &P) -> OpsMap {
|
||||
pub fn translate<P: AsRef<Path>>(mut stmts: Vec<Statement>, root: &P) -> OpsMap {
|
||||
let mut rewriter = Rewriter::new(root.as_ref());
|
||||
let mut_stmts = stmts.iter_mut().collect();
|
||||
rewriter.walk_statement_list(mut_stmts);
|
||||
let mut ops = OpsMap::new();
|
||||
Self::translate_stmts(stmts, &mut ops, root.as_ref());
|
||||
return ops;
|
||||
}
|
||||
|
||||
pub fn translate_stmt(stmt: Statement, mut ops: &mut OpsMap, root: &Path) {
|
||||
fn translate_stmt(stmt: Statement, mut ops: &mut OpsMap, root: &Path) {
|
||||
match stmt {
|
||||
Statement::Expression(expr) => {
|
||||
let expr_pos = expr.pos().clone();
|
||||
@ -210,7 +213,6 @@ impl AST {
|
||||
Self::translate_expr(*def.right.clone(), &mut ops, root);
|
||||
// Symbols on the left side should be converted to strings to satisfy
|
||||
// the Index operation contract.
|
||||
// FIXME(jwall): List checks should not use symbol translation.
|
||||
match *def.left.clone() {
|
||||
Expression::Simple(Value::Symbol(name)) => {
|
||||
// We really just want an expression that turns a symbol
|
||||
@ -451,8 +453,7 @@ impl AST {
|
||||
ops.push(Op::Val(Primitive::Str(def.path.fragment)), def.path.pos);
|
||||
ops.push(Op::Runtime(Hook::Include), def.pos);
|
||||
}
|
||||
Expression::Module(mut def) => {
|
||||
def.imports_to_absolute(root.to_path_buf());
|
||||
Expression::Module(def) => {
|
||||
let argset = def.arg_set;
|
||||
let out_expr = def.out_expr;
|
||||
let stmts = def.statements;
|
||||
|
Loading…
x
Reference in New Issue
Block a user