mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -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) {
|
pub fn set_out_expr(&mut self, expr: Expression) {
|
||||||
self.out_expr = Some(Box::new(expr));
|
self.out_expr = Some(Box::new(expr));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn imports_to_absolute(&mut self, base: PathBuf) {
|
pub struct Rewriter {
|
||||||
&base;
|
base: PathBuf,
|
||||||
let rewrite_import = |e: &mut Expression| {
|
}
|
||||||
let main_separator = format!("{}", std::path::MAIN_SEPARATOR);
|
|
||||||
if let Expression::Include(ref mut def) = e {
|
impl Rewriter {
|
||||||
let path = PathBuf::from(&def.path.fragment);
|
pub fn new<P: Into<PathBuf>>(base: P) -> Self {
|
||||||
#[cfg(not(windows))]
|
Self { base: base.into() }
|
||||||
{
|
}
|
||||||
if path.is_relative() {
|
}
|
||||||
def.path.fragment = base
|
|
||||||
.join(path)
|
impl walk::Walker for Rewriter {
|
||||||
.canonicalize()
|
fn visit_expression(&mut self, expr: &mut Expression) {
|
||||||
.unwrap()
|
// Rewrite all paths except for stdlib paths to absolute.
|
||||||
.to_string_lossy()
|
let main_separator = format!("{}", std::path::MAIN_SEPARATOR);
|
||||||
.to_string();
|
if let Expression::Include(ref mut def) = expr {
|
||||||
}
|
let path = PathBuf::from(&def.path.fragment);
|
||||||
}
|
#[cfg(not(windows))]
|
||||||
#[cfg(windows)]
|
{
|
||||||
{
|
if path.is_relative() {
|
||||||
if path.is_relative() {
|
def.path.fragment = self
|
||||||
def.path.fragment = base.join(path).to_string_lossy().to_string();
|
.base
|
||||||
}
|
.join(path)
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap()
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Expression::Import(ref mut def) = e {
|
#[cfg(windows)]
|
||||||
let path = PathBuf::from(
|
{
|
||||||
&def.path
|
if path.is_relative() {
|
||||||
.fragment
|
def.path.fragment = self.base.join(path).to_string_lossy().to_string();
|
||||||
.replace("/", &main_separator)
|
}
|
||||||
.replace("\\", &main_separator),
|
}
|
||||||
);
|
}
|
||||||
// std/ paths are special and do not get made into absolute paths.
|
if let Expression::Import(ref mut def) = expr {
|
||||||
if path.starts_with(format!("std{}", main_separator)) {
|
let path = PathBuf::from(
|
||||||
return;
|
&def.path
|
||||||
}
|
.fragment
|
||||||
#[cfg(not(windows))]
|
.replace("/", &main_separator)
|
||||||
{
|
.replace("\\", &main_separator),
|
||||||
if path.is_relative() {
|
);
|
||||||
def.path.fragment = base
|
// std/ paths are special and do not get made into absolute paths.
|
||||||
.join(path)
|
if path.starts_with(format!("std{}", main_separator)) {
|
||||||
.canonicalize()
|
return;
|
||||||
.unwrap()
|
}
|
||||||
.to_string_lossy()
|
#[cfg(not(windows))]
|
||||||
.to_string();
|
{
|
||||||
}
|
if path.is_relative() {
|
||||||
}
|
def.path.fragment = self
|
||||||
#[cfg(windows)]
|
.base
|
||||||
{
|
.join(path)
|
||||||
if path.is_relative() {
|
.canonicalize()
|
||||||
def.path.fragment = base.join(path).to_string_lossy().to_string();
|
.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;
|
// noop by default;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_include(&mut self, i: &mut IncludeDef) {
|
fn visit_include(&mut self, _i: &mut IncludeDef) {
|
||||||
// noop by default;
|
// noop by default;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_fail(&mut self, f: &mut FailDef) {
|
fn visit_fail(&mut self, _f: &mut FailDef) {
|
||||||
// noop by default;
|
// 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.
|
// TODO this would be better implemented as a Trait I think.
|
||||||
|
@ -90,8 +90,6 @@ where
|
|||||||
pub environment: &'a RefCell<Environment<Stdout, Stderr>>,
|
pub environment: &'a RefCell<Environment<Stdout, Stderr>>,
|
||||||
working_dir: PathBuf,
|
working_dir: PathBuf,
|
||||||
strict: bool,
|
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>>,
|
std: Rc<HashMap<String, &'static str>>,
|
||||||
import_path: &'a Vec<PathBuf>,
|
import_path: &'a Vec<PathBuf>,
|
||||||
pub last: Option<Rc<Val>>,
|
pub last: Option<Rc<Val>>,
|
||||||
@ -303,12 +301,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_expr(&mut self, expr: Expression) -> Result<Rc<Val>, Box<dyn Error>> {
|
pub fn eval_expr(&mut self, expr: Expression) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let mut ops_map = translate::OpsMap::new();
|
let ops_map =
|
||||||
translate::AST::translate_stmt(
|
translate::AST::translate(vec![Statement::Expression(expr)], &self.working_dir);
|
||||||
Statement::Expression(expr),
|
|
||||||
&mut ops_map,
|
|
||||||
&self.working_dir,
|
|
||||||
);
|
|
||||||
let mut vm = VM::new(self.strict, Rc::new(ops_map), &self.working_dir);
|
let mut vm = VM::new(self.strict, Rc::new(ops_map), &self.working_dir);
|
||||||
if self.validate_mode {
|
if self.validate_mode {
|
||||||
vm.enable_validate_mode();
|
vm.enable_validate_mode();
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::ast::walk::Walker;
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
BinaryExprType, BinaryOpDef, Expression, FormatArgs, Position, PositionedItem, SelectDef,
|
BinaryExprType, BinaryOpDef, Expression, FormatArgs, FuncOpDef, Position, PositionedItem,
|
||||||
Statement, Token, TokenType, Value,
|
Rewriter, SelectDef, Statement, TemplatePart, Token, TokenType, Value,
|
||||||
};
|
};
|
||||||
use crate::ast::{FuncOpDef, TemplatePart};
|
|
||||||
use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser};
|
use crate::build::format::{ExpressionTemplate, SimpleTemplate, TemplateParser};
|
||||||
use crate::build::opcode::Primitive;
|
use crate::build::opcode::Primitive;
|
||||||
use crate::build::opcode::{Hook, Op};
|
use crate::build::opcode::{Hook, Op};
|
||||||
@ -66,13 +66,16 @@ impl OpsMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AST {
|
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();
|
let mut ops = OpsMap::new();
|
||||||
Self::translate_stmts(stmts, &mut ops, root.as_ref());
|
Self::translate_stmts(stmts, &mut ops, root.as_ref());
|
||||||
return ops;
|
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 {
|
match stmt {
|
||||||
Statement::Expression(expr) => {
|
Statement::Expression(expr) => {
|
||||||
let expr_pos = expr.pos().clone();
|
let expr_pos = expr.pos().clone();
|
||||||
@ -210,7 +213,6 @@ impl AST {
|
|||||||
Self::translate_expr(*def.right.clone(), &mut ops, root);
|
Self::translate_expr(*def.right.clone(), &mut ops, root);
|
||||||
// Symbols on the left side should be converted to strings to satisfy
|
// Symbols on the left side should be converted to strings to satisfy
|
||||||
// the Index operation contract.
|
// the Index operation contract.
|
||||||
// FIXME(jwall): List checks should not use symbol translation.
|
|
||||||
match *def.left.clone() {
|
match *def.left.clone() {
|
||||||
Expression::Simple(Value::Symbol(name)) => {
|
Expression::Simple(Value::Symbol(name)) => {
|
||||||
// We really just want an expression that turns a symbol
|
// 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::Val(Primitive::Str(def.path.fragment)), def.path.pos);
|
||||||
ops.push(Op::Runtime(Hook::Include), def.pos);
|
ops.push(Op::Runtime(Hook::Include), def.pos);
|
||||||
}
|
}
|
||||||
Expression::Module(mut def) => {
|
Expression::Module(def) => {
|
||||||
def.imports_to_absolute(root.to_path_buf());
|
|
||||||
let argset = def.arg_set;
|
let argset = def.arg_set;
|
||||||
let out_expr = def.out_expr;
|
let out_expr = def.out_expr;
|
||||||
let stmts = def.statements;
|
let stmts = def.statements;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user