refactor: Use Rc<str> instead of string

This commit is contained in:
Jeremy Wall 2023-09-02 13:00:29 -04:00
parent b5f86657c4
commit bd9686128a
31 changed files with 299 additions and 286 deletions

View File

@ -125,18 +125,18 @@ pub enum TokenType {
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
pub struct Token {
pub typ: TokenType,
pub fragment: String,
pub fragment: Rc<str>,
pub pos: Position,
}
impl Token {
/// Constructs a new Token with a type and line and column information.
pub fn new<S: Into<String>, P: Into<Position>>(f: S, typ: TokenType, p: P) -> Self {
pub fn new<S: Into<Rc<str>>, P: Into<Position>>(f: S, typ: TokenType, p: P) -> Self {
Self::new_with_pos(f, typ, p.into())
}
// Constructs a new Token with a type and a Position.
pub fn new_with_pos<S: Into<String>>(f: S, typ: TokenType, pos: Position) -> Self {
pub fn new_with_pos<S: Into<Rc<str>>>(f: S, typ: TokenType, pos: Position) -> Self {
Token {
typ,
fragment: f.into(),
@ -241,8 +241,8 @@ pub enum Value {
Boolean(PositionedItem<bool>),
Int(PositionedItem<i64>),
Float(PositionedItem<f64>),
Str(PositionedItem<String>),
Symbol(PositionedItem<String>),
Str(PositionedItem<Rc<str>>),
Symbol(PositionedItem<Rc<str>>),
Tuple(PositionedItem<FieldList>),
List(ListDef),
}
@ -250,7 +250,7 @@ pub enum Value {
#[derive(PartialEq, Debug, Clone)]
pub enum ImportShape {
Resolved(Position, TupleShape),
Unresolved(PositionedItem<String>),
Unresolved(PositionedItem<Rc<str>>),
}
#[derive(PartialEq, Debug, Clone)]
@ -281,15 +281,15 @@ pub enum Shape {
Boolean(PositionedItem<bool>),
Int(PositionedItem<i64>),
Float(PositionedItem<f64>),
Str(PositionedItem<String>),
Str(PositionedItem<Rc<str>>),
Tuple(PositionedItem<TupleShape>),
List(NarrowedShape),
Func(FuncShapeDef),
Module(ModuleShape),
Hole(PositionedItem<String>), // A type hole We don't know what this type is yet.
Narrowed(NarrowedShape), // A narrowed type. We know *some* of the possible options.
Import(ImportShape), // A type hole We don't know what this type is yet.
TypeErr(Position, String), // A type hole We don't know what this type is yet.
Hole(PositionedItem<Rc<str>>), // A type hole We don't know what this type is yet.
Narrowed(NarrowedShape), // A narrowed type. We know *some* of the possible options.
Import(ImportShape), // A type hole We don't know what this type is yet.
TypeErr(Position, String), // A type hole We don't know what this type is yet.
}
impl Shape {
@ -327,7 +327,12 @@ impl Shape {
}
}
fn narrow_tuple_shapes(&self, left_slist: &PositionedItem<Vec<(Token, Shape)>>, right_slist: &PositionedItem<Vec<(Token, Shape)>>, right: &Shape) -> Shape {
fn narrow_tuple_shapes(
&self,
left_slist: &PositionedItem<Vec<(Token, Shape)>>,
right_slist: &PositionedItem<Vec<(Token, Shape)>>,
right: &Shape,
) -> Shape {
let left_iter = left_slist.val.iter();
let right_iter = right_slist.val.iter();
if is_tuple_subset(left_iter, right_slist) {
@ -542,7 +547,7 @@ impl Value {
)
}
fn derive_shape(&self, symbol_table: &mut BTreeMap<String, Shape>) -> Shape {
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
let shape = match self {
Value::Empty(p) => Shape::Empty(p.clone()),
Value::Boolean(p) => Shape::Boolean(p.clone()),
@ -690,8 +695,8 @@ impl<'a> From<&'a Token> for PositionedItem<String> {
}
}
impl<'a> From<&'a PositionedItem<String>> for PositionedItem<String> {
fn from(t: &PositionedItem<String>) -> PositionedItem<String> {
impl<'a> From<&'a PositionedItem<Rc<str>>> for PositionedItem<Rc<str>> {
fn from(t: &PositionedItem<Rc<str>>) -> PositionedItem<Rc<str>> {
PositionedItem {
pos: t.pos.clone(),
val: t.val.clone(),
@ -705,7 +710,7 @@ impl<'a> From<&'a PositionedItem<String>> for PositionedItem<String> {
#[derive(PartialEq, Debug, Clone)]
pub struct FuncDef {
pub scope: Option<Scope>,
pub argdefs: Vec<PositionedItem<String>>,
pub argdefs: Vec<PositionedItem<Rc<str>>>,
pub fields: Box<Expression>,
pub pos: Position,
}
@ -713,7 +718,11 @@ pub struct FuncDef {
impl FuncDef {
fn derive_shape(&self) -> Shape {
// 1. First set up our symbols.
let _table = self.argdefs.iter().map(|sym| (sym.val.clone(), Shape::Hole(sym.clone()))).collect::<BTreeMap<String, Shape>>();
let _table = self
.argdefs
.iter()
.map(|sym| (sym.val.clone(), Shape::Hole(sym.clone())))
.collect::<BTreeMap<Rc<str>, Shape>>();
// 2.Then determine the shapes of those symbols in our expression.
// 3. Finally determine what the return shape can be.
todo!();
@ -983,11 +992,11 @@ impl Expression {
}
}
fn derive_shape(&self, symbol_table: &mut BTreeMap<String, Shape>) -> Shape {
fn derive_shape(&self, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
let shape = match self {
Expression::Simple(v) => v.derive_shape(symbol_table),
Expression::Format(def) => {
Shape::Str(PositionedItem::new("".to_owned(), def.pos.clone()))
Shape::Str(PositionedItem::new("".into(), def.pos.clone()))
}
Expression::Not(def) => derive_not_shape(def, symbol_table),
Expression::Grouped(v, _pos) => v.as_ref().derive_shape(symbol_table),
@ -997,7 +1006,7 @@ impl Expression {
)),
Expression::Cast(def) => match def.cast_type {
CastType::Int => Shape::Int(PositionedItem::new(0, def.pos.clone())),
CastType::Str => Shape::Str(PositionedItem::new("".to_owned(), def.pos.clone())),
CastType::Str => Shape::Str(PositionedItem::new("".into(), def.pos.clone())),
CastType::Float => Shape::Float(PositionedItem::new(0.0, def.pos.clone())),
CastType::Bool => Shape::Boolean(PositionedItem::new(true, def.pos.clone())),
},
@ -1040,7 +1049,7 @@ fn derive_include_shape(
))
}
fn derive_not_shape(def: &NotDef, symbol_table: &mut BTreeMap<String, Shape>) -> Shape {
fn derive_not_shape(def: &NotDef, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
let shape = def.expr.as_ref().derive_shape(symbol_table);
if let Shape::Boolean(b) = shape {
Shape::Boolean(PositionedItem::new(!b.val, def.pos.clone()))
@ -1056,7 +1065,7 @@ fn derive_not_shape(def: &NotDef, symbol_table: &mut BTreeMap<String, Shape>) ->
}
}
fn derive_copy_shape(def: &CopyDef, symbol_table: &mut BTreeMap<String, Shape>) -> Shape {
fn derive_copy_shape(def: &CopyDef, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Shape {
let base_shape = def.selector.derive_shape(symbol_table);
match &base_shape {
// TODO(jwall): Should we allow a stack of these?
@ -1113,7 +1122,7 @@ fn derive_copy_shape(def: &CopyDef, symbol_table: &mut BTreeMap<String, Shape>)
.fields
.iter()
.map(|(tok, expr)| (tok.fragment.clone(), expr.derive_shape(symbol_table)))
.collect::<BTreeMap<String, Shape>>();
.collect::<BTreeMap<Rc<str>, Shape>>();
// 1. Do our copyable fields have the right names and shapes based on mdef.items.
for (tok, shape) in mdef.items.iter() {
if let Some(s) = arg_fields.get(&tok.fragment) {

View File

@ -31,9 +31,9 @@ impl Visitor for Rewriter {
// 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);
let path = PathBuf::from(def.path.fragment.as_ref());
if path.is_relative() {
def.path.fragment = self.base.join(path).to_string_lossy().to_string();
def.path.fragment = self.base.join(path).to_string_lossy().to_string().into();
}
}
if let Expression::Import(ref mut def) = expr {
@ -48,7 +48,7 @@ impl Visitor for Rewriter {
return;
}
if path.is_relative() {
def.path.fragment = self.base.join(path).to_string_lossy().to_string();
def.path.fragment = self.base.join(path).to_string_lossy().to_string().into();
}
}
}

View File

@ -46,11 +46,11 @@ fn derive_shape_values() {
),
(
Value::Str(PositionedItem::new(
"foo".to_owned(),
"foo".into(),
Position::new(0, 1, 2),
)),
Shape::Str(PositionedItem::new(
"foo".to_owned(),
"foo".into(),
Position::new(0, 1, 2),
)),
),
@ -103,7 +103,7 @@ fn derive_shape_expressions() {
),
(
"\"foo {}\" % (1);",
Shape::Str(PositionedItem::new("".to_owned(), Position::new(0, 0, 0))),
Shape::Str(PositionedItem::new("".into(), Position::new(0, 0, 0))),
),
(
"not true;",
@ -112,8 +112,8 @@ fn derive_shape_expressions() {
(
"0:1;",
Shape::List(NarrowedShape::new_with_pos(
vec![Shape::Int(PositionedItem::new(0, Position::new(0, 0, 0)))],
Position::new(0, 0, 0),
vec![Shape::Int(PositionedItem::new(0, Position::new(1, 1, 0)))],
Position::new(1, 1, 0),
)),
),
(
@ -126,7 +126,7 @@ fn derive_shape_expressions() {
),
(
"str(1);",
Shape::Str(PositionedItem::new("".to_owned(), Position::new(0, 0, 0))),
Shape::Str(PositionedItem::new("".into(), Position::new(0, 0, 0))),
),
(
"bool(\"true\");",

View File

@ -15,6 +15,7 @@
//! Implements typechecking for the parsed ucg AST.
// FIXME(jwall): This probably just needs to disappear now.
use std::collections::BTreeMap;
use std::rc::Rc;
use crate::ast::walk::Visitor;
use crate::ast::{Expression, FailDef, ImportDef, IncludeDef, Position, Shape, Statement, Value};
@ -28,7 +29,7 @@ use Statement::Let;
use Value::{Boolean, Empty, Float, Int, List, Str, Symbol, Tuple};
pub struct Checker {
symbol_table: BTreeMap<String, Shape>,
symbol_table: BTreeMap<Rc<str>, Shape>,
err_stack: Vec<BuildError>,
shape_stack: Vec<Shape>,
}
@ -46,7 +47,7 @@ impl Checker {
self.shape_stack.pop()
}
pub fn result(mut self) -> Result<BTreeMap<String, Shape>, BuildError> {
pub fn result(mut self) -> Result<BTreeMap<Rc<str>, Shape>, BuildError> {
if let Some(err) = self.err_stack.pop() {
Err(err)
} else {

View File

@ -45,7 +45,7 @@ fn simple_binary_typecheck() {
);
assert_type_success!(
"\"\" + \"\";",
Shape::Str(PositionedItem::new(String::new(), Position::new(1, 1, 0)))
Shape::Str(PositionedItem::new("".into(), Position::new(1, 1, 0)))
);
assert_type_success!(
"1.0 + 1.0;",
@ -64,7 +64,7 @@ fn simple_binary_typecheck() {
"{foo = 1} + {foo = 1};",
Shape::Tuple(PositionedItem::new(
vec![
(Token { typ: TokenType::BAREWORD, fragment: "foo".to_owned(), pos: Position::new(1, 2, 1)},
(Token { typ: TokenType::BAREWORD, fragment: "foo".into(), pos: Position::new(1, 2, 1)},
Shape::Int(PositionedItem::new_with_pos(1, Position::new(1, 8, 7)))),
],
Position::new(1, 1, 0)

View File

@ -26,7 +26,7 @@ fn assert_build(input: &str) {
let out_buffer: Vec<u8> = Vec::new();
let err_buffer: Vec<u8> = Vec::new();
let mut env_vars = BTreeMap::new();
env_vars.insert("FOO".to_owned(), "bar".to_owned());
env_vars.insert("FOO".into(), "bar".into());
let env = RefCell::new(Environment::new_with_vars(out_buffer, err_buffer, env_vars));
let mut b = FileBuilder::new("<Eval>", &i_paths, &env);
b.enable_validate_mode();

View File

@ -15,10 +15,10 @@ pub enum Val {
Boolean(bool),
Int(i64),
Float(f64),
Str(String),
Str(Rc<str>),
List(Vec<Rc<Val>>),
Tuple(Vec<(String, Rc<Val>)>),
Env(Vec<(String, String)>),
Tuple(Vec<(Rc<str>, Rc<Val>)>),
Env(Vec<(Rc<str>, Rc<str>)>),
}
impl Val {
@ -103,7 +103,7 @@ impl Val {
}
/// Returns the fields if this Val is a tuple. None otherwise.
pub fn get_fields(&self) -> Option<&Vec<(String, Rc<Val>)>> {
pub fn get_fields(&self) -> Option<&Vec<(Rc<str>, Rc<Val>)>> {
if let &Val::Tuple(ref fs) = self {
Some(fs)
} else {
@ -208,8 +208,8 @@ impl Display for Val {
}
}
impl From<Val> for String {
fn from(v: Val) -> String {
impl From<Val> for Rc<str> {
fn from(v: Val) -> Self {
match v {
Val::Int(ref i) => format!("{}", i),
Val::Float(ref f) => format!("{}", f),
@ -217,12 +217,12 @@ impl From<Val> for String {
Val::Boolean(ref b) => format!("{}", b),
Val::Empty => "NULL".to_string(),
val => format!("{}", val),
}
}.into()
}
}
impl From<String> for Val {
fn from(s: String) -> Val {
impl From<Rc<str>> for Val {
fn from(s: Rc<str>) -> Val {
Val::Str(s)
}
}

View File

@ -181,7 +181,7 @@ where
if found.contains(&link) {
continue;
}
let ops = match self.environment.borrow_mut().get_ops_for_path(link.clone()) {
let ops = match self.environment.borrow_mut().get_ops_for_path(link.as_ref()) {
Ok(ops) => ops,
Err(e) => return Err(Box::new(e.with_pos(path_pos))),
};
@ -343,7 +343,7 @@ where
if let Some(val) = self.out.clone() {
if let &Val::Tuple(ref flds) = val.as_ref() {
for (k, v) in flds.iter() {
if k == name {
if k.as_ref() == name {
return Some(v.clone());
}
}

View File

@ -19,14 +19,14 @@ impl Error {
}
}
impl From<&Primitive> for String {
impl From<&Primitive> for Rc<str> {
fn from(p: &Primitive) -> Self {
match p {
Primitive::Int(i) => format!("{}", i),
Primitive::Float(f) => format!("{}", f),
Primitive::Str(s) => format!("{}", s),
Primitive::Bool(b) => format!("{}", b),
Primitive::Empty => "NULL".to_owned(),
Primitive::Int(i) => format!("{}", i).into(),
Primitive::Float(f) => format!("{}", f).into(),
Primitive::Str(s) => format!("{}", s).into(),
Primitive::Bool(b) => format!("{}", b).into(),
Primitive::Empty => "NULL".into(),
}
}
}
@ -85,7 +85,7 @@ impl TryFrom<&Primitive> for bool {
cast_type: CastType::Int,
}),
Primitive::Bool(b) => Ok(*b),
Primitive::Str(s) => match s.as_str() {
Primitive::Str(s) => match s.as_ref() {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(Error {
@ -192,15 +192,15 @@ impl From<&Val> for Value {
}
}
impl From<&Composite> for String {
impl From<&Composite> for Rc<str> {
fn from(c: &Composite) -> Self {
let mut buf = String::new();
match c {
&List(ref elems, _) => {
buf.push_str("[");
for e in elems.iter() {
let val: String = e.as_ref().into();
buf.push_str(&val);
let val: Rc<str> = e.as_ref().into();
buf.push_str(val.as_ref());
buf.push_str(",");
}
buf.push_str("]");
@ -210,26 +210,26 @@ impl From<&Composite> for String {
for &(ref k, ref v) in flds.iter() {
buf.push_str(&k);
buf.push_str(" = ");
let val: String = v.as_ref().into();
let val: Rc<str> = v.as_ref().into();
buf.push_str(&val);
buf.push_str(",");
}
buf.push_str("}");
}
}
buf
buf.into()
}
}
impl From<&Value> for String {
impl From<&Value> for Rc<str> {
fn from(v: &Value) -> Self {
match v {
&S(ref s) => s.clone(),
&P(ref p) => p.into(),
&C(ref c) => c.into(),
&T(_) => "<Thunk>".to_owned(),
&F(_) => "<Func>".to_owned(),
&M(_) => "<Module>".to_owned(),
&T(_) => "<Thunk>".into(),
&F(_) => "<Func>".into(),
&M(_) => "<Module>".into(),
}
}
}

View File

@ -34,7 +34,7 @@ where
Stdout: Write + Clone,
Stderr: Write + Clone,
{
pub val_cache: BTreeMap<String, Rc<Value>>,
pub val_cache: BTreeMap<Rc<str>, Rc<Value>>,
// TODO implement a shape cache here.
pub op_cache: cache::Ops,
pub converter_registry: ConverterRegistry,
@ -42,7 +42,7 @@ where
pub assert_results: AssertCollector,
pub stdout: Stdout,
pub stderr: Stderr,
pub env_vars: BTreeMap<String, String>, // Environment Variables
pub env_vars: BTreeMap<Rc<str>, Rc<str>>, // Environment Variables
pub out_lock: BTreeSet<PathBuf>,
}
@ -52,7 +52,7 @@ impl<Stdout: Write + Clone, Stderr: Write + Clone> Environment<Stdout, Stderr> {
Self::new_with_vars(out, err, BTreeMap::new())
}
pub fn new_with_vars(out: Stdout, err: Stderr, vars: BTreeMap<String, String>) -> Self {
pub fn new_with_vars(out: Stdout, err: Stderr, vars: BTreeMap<Rc<str>, Rc<str>>) -> Self {
let mut me = Self {
val_cache: BTreeMap::new(),
env_vars: vars,
@ -78,11 +78,11 @@ impl<Stdout: Write + Clone, Stderr: Write + Clone> Environment<Stdout, Stderr> {
Value::C(Composite::Tuple(fields, positions))
}
pub fn get_cached_path_val(&self, path: &String) -> Option<Rc<Value>> {
self.val_cache.get(path).cloned()
pub fn get_cached_path_val(&self, path: Rc<str>) -> Option<Rc<Value>> {
self.val_cache.get(&path).cloned()
}
pub fn update_path_val(&mut self, path: &String, val: Rc<Value>) {
pub fn update_path_val(&mut self, path: Rc<str>, val: Rc<Value>) {
self.val_cache.insert(path.clone(), val);
}

View File

@ -15,19 +15,20 @@ use std::convert::From;
use std::fmt;
use std::fmt::Display;
use std::io;
use std::rc::Rc;
use crate::ast::Position;
use crate::build::opcode::convert;
#[derive(Debug)]
pub struct Error {
message: String,
message: Rc<str>,
pos: Option<Position>,
call_stack: Vec<Position>,
}
impl Error {
pub fn new(msg: String, pos: Position) -> Self {
pub fn new(msg: Rc<str>, pos: Position) -> Self {
Self {
message: msg,
pos: Some(pos),
@ -69,7 +70,7 @@ macro_rules! decorate_call {
impl From<regex::Error> for Error {
fn from(e: regex::Error) -> Self {
Error {
message: format!("{}", e),
message: format!("{}", e).into(),
pos: None,
call_stack: Vec::new(),
}
@ -83,7 +84,7 @@ impl From<std::io::Error> for Error {
format!("OSError: Path not found: {}", e)
}
_ => format!("{}", e),
};
}.into();
Error {
message: msg,
pos: None,
@ -95,7 +96,7 @@ impl From<std::io::Error> for Error {
impl From<convert::Error> for Error {
fn from(e: convert::Error) -> Self {
Error {
message: e.message(),
message: e.message().into(),
pos: None,
call_stack: Vec::new(),
}

View File

@ -39,7 +39,7 @@ pub enum Primitive {
// Primitive Types
Int(i64),
Float(f64),
Str(String),
Str(Rc<str>),
Bool(bool),
Empty,
}
@ -67,7 +67,7 @@ impl Value {
#[derive(Debug, PartialEq, Clone)]
pub enum Composite {
List(Vec<Rc<Value>>, Vec<Position>),
Tuple(Vec<(String, Rc<Value>)>, Vec<(Position, Position)>),
Tuple(Vec<(Rc<str>, Rc<Value>)>, Vec<(Position, Position)>),
}
use Composite::{List, Tuple};
@ -75,7 +75,7 @@ use Composite::{List, Tuple};
#[derive(Debug, PartialEq, Clone)]
pub struct Func {
ptr: OpPointer,
bindings: Vec<String>,
bindings: Vec<Rc<str>>,
snapshot: Stack,
}
@ -83,7 +83,7 @@ pub struct Func {
pub struct Module {
ptr: OpPointer,
result_ptr: Option<usize>,
flds: Vec<(String, Rc<Value>)>,
flds: Vec<(Rc<str>, Rc<Value>)>,
flds_pos_list: Vec<(Position, Position)>,
pkg_ptr: Option<OpPointer>,
}
@ -91,7 +91,7 @@ pub struct Module {
#[derive(Clone)]
pub enum Value {
// Binding names.
S(String),
S(Rc<str>),
// Primitive Types
P(Primitive),
// Composite Types.
@ -147,9 +147,9 @@ pub enum Op {
// Primitive casts
Cast(CastType),
// A bareword for use in bindings or lookups
Sym(String),
Sym(Rc<str>),
// Reference a binding on the heap
DeRef(String),
DeRef(Rc<str>),
// Complex Type ops
InitTuple,
Field,

View File

@ -60,7 +60,7 @@ impl OpPointer {
return Ok(());
}
Err(Error::new(
format!("FAULT!!! Invalid Jump!"),
"FAULT!!! Invalid Jump!".into(),
match self.pos() {
Some(pos) => pos.clone(),
None => Position::new(0, 0, 0),
@ -86,7 +86,7 @@ impl OpPointer {
match self.ptr {
Some(ptr) => Ok(ptr),
None => Err(Error::new(
format!("FAULT!!! Position Check failure!"),
"FAULT!!! Position Check failure!".into(),
Position::new(0, 0, 0),
)),
}

View File

@ -63,7 +63,7 @@ impl Builtins {
h: Hook,
stack: &mut Vec<(Rc<Value>, Position)>,
env: &'a RefCell<Environment<O, E>>,
import_stack: &mut Vec<String>,
import_stack: &mut Vec<Rc<str>>,
pos: Position,
) -> Result<(), Error>
where
@ -86,19 +86,19 @@ impl Builtins {
}
}
fn get_file_as_string(&self, path: &str) -> Result<String, Error> {
fn get_file_as_string(&self, path: &str) -> Result<Rc<str>, Error> {
let mut f = File::open(path)?;
let mut contents = String::new();
// TODO(jwall): Proper error here
f.read_to_string(&mut contents)?;
Ok(contents)
Ok(contents.into())
}
fn import<'a, O, E>(
&mut self,
stack: &mut Vec<(Rc<Value>, Position)>,
env: &'a RefCell<Environment<O, E>>,
import_stack: &mut Vec<String>,
import_stack: &mut Vec<Rc<str>>,
pos: Position,
) -> Result<(), Error>
where
@ -110,39 +110,39 @@ impl Builtins {
if let &Value::P(Str(ref path)) = val.as_ref() {
// TODO(jwall): A bit hacky we should probably change import stacks to be pathbufs.
// first we chack the cache
if let Some(val) = env.borrow().get_cached_path_val(&path) {
if let Some(val) = env.borrow().get_cached_path_val(path.clone()) {
stack.push((val, path_pos));
return Ok(());
}
if import_stack.iter().find(|p| *p == path).is_some() {
if import_stack.iter().find(|p| p.as_ref() == path.as_ref()).is_some() {
return Err(Error::new(
format!("Import cycle detected: {} in {:?}", path, import_stack),
format!("Import cycle detected: {} in {:?}", path, import_stack).into(),
pos,
));
}
let val = { env.borrow_mut().get_cached_path_val(&path) };
let val = { env.borrow_mut().get_cached_path_val(path.clone()) };
match val {
Some(v) => {
stack.push((v, path_pos));
}
None => {
let path_buf = PathBuf::from(path);
let path_buf = PathBuf::from(path.as_ref());
let op_pointer =
decorate_error!(path_pos => env.borrow_mut().get_ops_for_path(&path))?;
decorate_error!(path_pos => env.borrow_mut().get_ops_for_path(path.as_ref()))?;
// TODO(jwall): What if we don't have a base path?
let mut vm =
VM::with_pointer(self.strict, op_pointer, path_buf.parent().unwrap())
.with_import_stack(import_stack.clone());
vm.run(env)?;
let result = Rc::new(vm.symbols_to_tuple(true));
env.borrow_mut().update_path_val(&path, result.clone());
env.borrow_mut().update_path_val(path.clone(), result.clone());
stack.push((result, pos));
}
}
import_stack.push(path.clone());
return Ok(());
}
return Err(Error::new(format!("Invalid Path {:?}", val), pos));
return Err(Error::new(format!("Invalid Path {:?}", val).into(), pos));
}
unreachable!();
}
@ -163,7 +163,7 @@ impl Builtins {
if let &Value::P(Str(ref path)) = val.as_ref() {
path.clone()
} else {
return Err(Error::new(format!("Invalid Path {:?}", val), path_pos));
return Err(Error::new(format!("Invalid Path {:?}", val).into(), path_pos));
}
} else {
unreachable!();
@ -173,14 +173,14 @@ impl Builtins {
typ.clone()
} else {
return Err(Error::new(
format!("Expected conversion type but got {:?}", val),
format!("Expected conversion type but got {:?}", val).into(),
typ_pos,
));
}
} else {
unreachable!();
};
if typ == "str" {
if typ.as_ref() == "str" {
stack.push((
Rc::new(P(Str(self.get_file_as_string(&path)?))),
pos.clone(),
@ -196,12 +196,12 @@ impl Builtins {
} else {
match importer.import(contents.as_bytes()) {
Ok(v) => v.into(),
Err(e) => return Err(Error::new(format!("{}", e), pos)),
Err(e) => return Err(Error::new(format!("{}", e).into(), pos)),
}
}
}
None => {
return Err(Error::new(format!("No such conversion type {}", &typ), pos))
return Err(Error::new(format!("No such conversion type {}", &typ).into(), pos))
}
}),
pos,
@ -226,10 +226,10 @@ impl Builtins {
// look for the ok field.
let mut ok = None;
for &(ref name, ref val) in tuple_flds.iter() {
if name == "desc" {
if name.as_ref() == "desc" {
desc = Some(val.as_ref());
}
if name == "ok" {
if name.as_ref() == "ok" {
ok = Some(val.as_ref());
}
}
@ -284,7 +284,7 @@ impl Builtins {
let write_path = path.as_ref().to_path_buf();
if env.borrow().get_out_lock_for_path(&path) {
return Err(Error::new(
format!("You can only have one output per file"),
"You can only have one output per file".into(),
pos,
));
}
@ -293,7 +293,7 @@ impl Builtins {
} else {
if env.borrow().get_out_lock_for_path("/dev/stdout") {
return Err(Error::new(
format!("You can only have one output per file"),
"You can only have one output per file".into(),
pos,
));
}
@ -316,18 +316,18 @@ impl Builtins {
None => Box::new(stdout),
};
if let Err(e) = c.convert(Rc::new(val), &mut writer) {
return Err(Error::new(format!("{}", e), pos.clone()));
return Err(Error::new(format!("{}", e).into(), pos.clone()));
}
return Ok(());
} else {
return Err(Error::new(
format!("No such conversion type {:?}", c_type),
format!("No such conversion type {:?}", c_type).into(),
c_type_pos,
));
}
}
return Err(Error::new(
format!("Not a conversion type {:?}", c_type_val),
format!("Not a conversion type {:?}", c_type_val).into(),
val_pos,
));
}
@ -356,14 +356,14 @@ impl Builtins {
Ok(_) => {
stack.push((
Rc::new(P(Str(
String::from_utf8_lossy(buf.as_slice()).to_string()
String::from_utf8_lossy(buf.as_slice()).into()
))),
pos,
));
}
Err(_e) => {
return Err(Error::new(
format!("No such conversion type {:?}", c_type),
format!("No such conversion type {:?}", c_type).into(),
c_typ_pos,
));
}
@ -373,7 +373,7 @@ impl Builtins {
}
}
return Err(Error::new(
format!("Not a conversion type {:?}", val),
format!("Not a conversion type {:?}", val).into(),
val_pos,
));
}
@ -384,7 +384,7 @@ impl Builtins {
&self,
stack: &mut Vec<(Rc<Value>, Position)>,
env: &'a RefCell<Environment<O, E>>,
import_stack: &Vec<String>,
import_stack: &Vec<Rc<str>>,
pos: Position,
) -> Result<(), Error>
where
@ -407,7 +407,7 @@ impl Builtins {
let f = if let &F(ref f) = fptr.as_ref() {
f
} else {
return Err(Error::new(format!("Not a function!!"), fptr_pos));
return Err(Error::new(format!("Not a function!!").into(), fptr_pos));
};
match list.as_ref() {
@ -443,16 +443,14 @@ impl Builtins {
// we expect them to be a list of exactly 2 items.
if fval.len() != 2 {
return Err(Error::new(
format!(
"Map Functions over tuples must return a list of two items"
),
"Map Functions over tuples must return a list of two items".into(),
result_pos,
));
}
let name = match fval[0].as_ref() {
&P(Str(ref name)) => name.clone(),
_ => return Err(Error::new(
format!("Map functions over tuples must return a String as the first list item"),
"Map functions over tuples must return a String as the first list item".into(),
result_pos,
)),
};
@ -467,7 +465,7 @@ impl Builtins {
&P(Str(ref s)) => {
let mut buf = String::new();
for c in s.chars() {
stack.push((Rc::new(P(Str(c.to_string()))), list_pos.clone()));
stack.push((Rc::new(P(Str(c.to_string().into()))), list_pos.clone()));
// call function and push it's result on the stack.
let (result, result_pos) = decorate_call!(pos =>
VM::fcall_impl(f, self.strict, stack, env.clone(), import_stack))?;
@ -475,16 +473,16 @@ impl Builtins {
buf.push_str(s);
} else {
return Err(Error::new(
format!("Map functions over string should return strings"),
"Map functions over string should return strings".into(),
result_pos,
));
}
}
stack.push((Rc::new(P(Str(buf))), pos));
stack.push((Rc::new(P(Str(buf.into()))), pos));
}
_ => {
return Err(Error::new(
format!("You can only map over lists, tuples, or strings"),
"You can only map over lists, tuples, or strings".into(),
pos,
))
}
@ -496,7 +494,7 @@ impl Builtins {
&self,
stack: &mut Vec<(Rc<Value>, Position)>,
env: &'a RefCell<Environment<O, E>>,
import_stack: &Vec<String>,
import_stack: &Vec<Rc<str>>,
pos: Position,
) -> Result<(), Error>
where
@ -519,7 +517,7 @@ impl Builtins {
let f = if let &F(ref f) = fptr.as_ref() {
f
} else {
return Err(Error::new(format!("Not a function!!"), fptr_pos));
return Err(Error::new("Not a function!!".into(), fptr_pos));
};
match list.as_ref() {
@ -578,7 +576,7 @@ impl Builtins {
&P(Str(ref s)) => {
let mut buf = String::new();
for c in s.chars() {
stack.push((Rc::new(P(Str(c.to_string()))), list_pos.clone()));
stack.push((Rc::new(P(Str(c.to_string().into()))), list_pos.clone()));
// call function and push it's result on the stack.
let (condition, _) = decorate_call!(pos =>
VM::fcall_impl(f, self.strict, stack, env.clone(), import_stack))?;
@ -591,11 +589,11 @@ impl Builtins {
_ => buf.push(c),
}
}
stack.push((Rc::new(P(Str(buf))), pos));
stack.push((Rc::new(P(Str(buf.into()))), pos));
}
_ => {
return Err(Error::new(
format!("You can only filter over lists, tuples, or strings"),
"You can only filter over lists, tuples, or strings".into(),
pos,
))
}
@ -610,7 +608,7 @@ impl Builtins {
s.clone()
} else {
return Err(Error::new(
format!("Expected string bug got {:?}", val),
format!("Expected string bug got {:?}", val).into(),
val_pos,
));
}
@ -624,7 +622,7 @@ impl Builtins {
s.clone()
} else {
return Err(Error::new(
format!("Expected string bug got {:?}", val),
format!("Expected string bug got {:?}", val).into(),
val_pos,
));
}
@ -642,7 +640,7 @@ impl Builtins {
&self,
stack: &mut Vec<(Rc<Value>, Position)>,
env: &'a RefCell<Environment<O, E>>,
import_stack: &Vec<String>,
import_stack: &Vec<Rc<str>>,
pos: Position,
) -> Result<(), Error>
where
@ -671,7 +669,7 @@ impl Builtins {
let f = if let &F(ref f) = fptr.as_ref() {
f
} else {
return Err(Error::new(format!("Not a function!"), fptr_pos));
return Err(Error::new("Noe a function!".into(), fptr_pos));
};
match list.as_ref() {
@ -711,7 +709,7 @@ impl Builtins {
for c in s.chars() {
// push function arguments on the stack.
stack.push((acc.clone(), acc_pos.clone()));
stack.push((Rc::new(P(Str(c.to_string()))), list_pos.clone()));
stack.push((Rc::new(P(Str(c.to_string().into()))), list_pos.clone()));
// call function and push it's result on the stack.
let (new_acc, new_acc_pos) = decorate_call!(pos =>
VM::fcall_impl(f, self.strict, stack, env.clone(), import_stack))?;
@ -721,7 +719,7 @@ impl Builtins {
}
_ => {
return Err(Error::new(
format!("You can only reduce over lists, tuples, or strings"),
"You can only reduce over lists, tuples, or strings".into(),
pos.clone(),
))
}
@ -769,7 +767,7 @@ impl Builtins {
}
_ => {
return Err(Error::new(
format!("Ranges can only be created with Ints"),
format!("Ranges can only be created with Ints").into(),
pos,
));
}
@ -809,7 +807,7 @@ impl Builtins {
writable_val,
&val_pos
) {
return Err(Error::new(format!("{}", e), pos));
return Err(Error::new(format!("{}", e).into(), pos));
};
stack.push((val, val_pos));
Ok(())

View File

@ -19,7 +19,7 @@ use crate::ast::Position;
#[derive(Clone, PartialEq, Debug)]
pub struct Stack {
curr: BTreeMap<String, (Rc<Value>, Position)>,
curr: BTreeMap<Rc<str>, (Rc<Value>, Position)>,
}
impl Stack {
@ -41,12 +41,12 @@ impl Stack {
self.curr.get(name).is_some()
}
pub fn add(&mut self, name: String, val: Rc<Value>, pos: Position) {
pub fn add(&mut self, name: Rc<str>, val: Rc<Value>, pos: Position) {
self.curr.insert(name, (val, pos));
}
pub fn symbol_list(&self) -> Vec<&String> {
self.curr.keys().collect()
pub fn symbol_list(&self) -> Vec<Rc<str>> {
self.curr.keys().cloned().collect()
}
pub fn snapshot(&self) -> Self {

View File

@ -13,6 +13,7 @@
// limitations under the License.
use std::collections::BTreeMap;
use std::path::Path;
use std::rc::Rc;
use crate::ast::rewrite::Rewriter;
use crate::ast::walk::Walker;
@ -30,8 +31,8 @@ pub struct AST();
pub struct OpsMap {
pub ops: Vec<Op>,
pub pos: Vec<Position>,
pub shape_map: BTreeMap<String, Shape>,
pub links: BTreeMap<String, Position>,
pub shape_map: BTreeMap<Rc<str>, Shape>,
pub links: BTreeMap<Rc<str>, Position>,
}
impl OpsMap {
@ -51,7 +52,7 @@ impl OpsMap {
self
}
pub fn add_link(&mut self, path: String, pos: Position) {
pub fn add_link(&mut self, path: Rc<str>, pos: Position) {
self.links.insert(path, pos);
}
@ -227,7 +228,7 @@ impl AST {
kind: BinaryExprType::IS,
right: Box::new(Expression::Simple(Value::Str(
PositionedItem::new(
"tuple".to_owned(),
"tuple".into(),
def.left.pos().clone(),
),
))),
@ -321,7 +322,7 @@ impl AST {
Expression::Fail(def) => {
let msg_pos = def.message.pos().clone();
Self::translate_expr(*def.message, &mut ops, root);
ops.push(Op::Val(Primitive::Str("UserDefined: ".to_owned())), msg_pos);
ops.push(Op::Val(Primitive::Str("UserDefined: ".into())), msg_pos);
ops.push(Op::Add, def.pos.clone());
ops.push(Op::Bang, def.pos);
}
@ -373,7 +374,7 @@ impl AST {
// Add our item binding shadowing any binding that already
// existed.
let expr_pos = expr.pos().clone();
ops.push(Op::Sym("item".to_owned()), expr.pos().clone());
ops.push(Op::Sym("item".into()), expr.pos().clone());
Self::translate_expr(*expr, &mut ops, root);
ops.push(Op::BindOver, expr_pos.clone());
let mut elems = Vec::new();
@ -531,7 +532,7 @@ impl AST {
} else {
ops.push(
Op::Val(Primitive::Str(
"Unhandled select case with no default".to_owned(),
"Unhandled select case with no default".into(),
)),
default_pos,
);
@ -569,7 +570,7 @@ impl AST {
let _ = printer.render_expr(&def.expr);
}
let expr_pretty = String::from_utf8(buffer).unwrap();
ops.push(Op::Val(Primitive::Str(expr_pretty)), def.pos.clone());
ops.push(Op::Val(Primitive::Str(expr_pretty.into())), def.pos.clone());
Self::translate_expr(*def.expr, &mut ops, root);
ops.push(Op::Runtime(Hook::Trace(def.pos.clone())), def.pos);
}
@ -586,7 +587,8 @@ impl AST {
) {
match part {
TemplatePart::Str(s) => {
ops.push(Op::Val(Primitive::Str(s.into_iter().collect())), pos);
let part: String = s.into_iter().map(|c| c.to_string()).collect();
ops.push(Op::Val(Primitive::Str(part.into())), pos);
}
TemplatePart::PlaceHolder(_idx) => {
if !place_holder {

View File

@ -46,7 +46,7 @@ pub struct VM {
working_dir: PathBuf,
stack: Vec<(Rc<Value>, Position)>,
symbols: Stack,
import_stack: Vec<String>,
import_stack: Vec<Rc<str>>,
runtime: runtime::Builtins,
ops: OpPointer,
pub last: Option<(Rc<Value>, Position)>,
@ -82,7 +82,7 @@ impl VM {
self
}
pub fn with_import_stack(mut self, imports: Vec<String>) -> Self {
pub fn with_import_stack(mut self, imports: Vec<Rc<str>>) -> Self {
self.import_stack = imports;
self
}
@ -114,8 +114,8 @@ impl VM {
let mut flds = Vec::new();
let mut pos_list = Vec::new();
for sym in self.symbols.symbol_list() {
if include_mod || sym != "mod" {
let (val, pos) = self.symbols.get(sym).unwrap().clone();
if include_mod || sym.as_ref() != "mod" {
let (val, pos) = self.symbols.get(sym.as_ref()).unwrap().clone();
pos_list.push((pos.clone(), pos.clone()));
flds.push((sym.clone(), val));
}
@ -198,7 +198,7 @@ impl VM {
};
}
if let Some(p) = self.ops.path.as_ref() {
self.import_stack.push(p.to_string_lossy().to_string());
self.import_stack.push(p.to_string_lossy().into());
}
Ok(())
}
@ -207,7 +207,7 @@ impl VM {
if let Value::P(ref p) = val {
self.push(
Rc::new(match t {
CastType::Str => Value::P(Primitive::Str(format!("{}", p))),
CastType::Str => Value::P(Primitive::Str(format!("{}", p).into())),
CastType::Int => Value::P(Primitive::Int(p.try_into()?)),
CastType::Float => Value::P(Primitive::Float(p.try_into()?)),
CastType::Bool => Value::P(Primitive::Bool(p.try_into()?)),
@ -236,15 +236,14 @@ impl VM {
M(_) => "module",
S(_) => "sym",
T(_) => "thunk",
}
.to_owned();
self.push(Rc::new(P(Str(typ_name))), pos)?;
};
self.push(Rc::new(P(Str(typ_name.into()))), pos)?;
Ok(())
}
fn op_deref<O, E>(
&mut self,
name: String,
name: Rc<str>,
env: &RefCell<Environment<O, E>>,
pos: &Position,
) -> Result<(), Error>
@ -279,7 +278,7 @@ impl VM {
format!(
"Not a boolean condition {:?} in && expression at {}",
cond, pos
),
).into(),
cond_pos.clone(),
));
}
@ -299,7 +298,7 @@ impl VM {
format!(
"Not a boolean condition {:?} in || expression at {}!",
cond, pos
),
).into(),
cond_pos.clone(),
));
}
@ -314,7 +313,7 @@ impl VM {
}
} else {
return Err(Error::new(
format!("Expected boolean but got {:?}!", cond),
format!("Expected boolean but got {:?}!", cond).into(),
cond_pos.clone(),
));
}
@ -329,7 +328,7 @@ impl VM {
}
} else {
return Err(Error::new(
format!("Expected boolean but got {:?}!", cond),
format!("Expected boolean but got {:?}!", cond).into(),
pos.clone(),
));
}
@ -345,9 +344,9 @@ impl VM {
let matched = match (field_name.as_ref(), search.as_ref()) {
(&S(ref fname), &P(Str(ref sname))) | (&S(ref fname), &S(ref sname)) => fname == sname,
(&S(ref fname), &P(Bool(b))) => {
if fname == "true" && b {
if fname.as_ref() == "true" && b {
true
} else if fname == "false" && !b {
} else if fname.as_ref() == "false" && !b {
true
} else {
false
@ -373,14 +372,14 @@ impl VM {
(Some(ptr), flds.clone(), pos_list.clone())
} else {
return Err(Error::new(
format!("Expected tuple but got {:?}", tpl_val),
format!("Expected tuple but got {:?}", tpl_val).into(),
tpl_val_pos,
));
}
}
_ => {
return Err(Error::new(
format!("Expected tuple but got {:?}", mod_val),
format!("Expected tuple but got {:?}", mod_val).into(),
mod_val_pos,
));
}
@ -392,7 +391,7 @@ impl VM {
let pkg_ops = vec![
Op::InitList,
Op::Func(3),
Op::Val(Str(path.to_string_lossy().to_string())),
Op::Val(Str(path.to_string_lossy().into())),
Op::Runtime(Hook::Import),
Op::Return,
];
@ -434,13 +433,13 @@ impl VM {
bindings.push(sym.clone());
} else {
return Err(Error::new(
format!("Not an argument name {:?}", e),
format!("Not an argument name {:?}", e).into(),
args_pos,
));
}
}
} else {
return Err(Error::new(format!("Fault!!! Bad Argument List"), args_pos));
return Err(Error::new("Fault!!! Bad Argument List".into(), args_pos));
}
let mut ops = self.ops.clone();
ops.jump(idx)?;
@ -462,7 +461,7 @@ impl VM {
strict: bool,
stack: &mut Vec<(Rc<Value>, Position)>,
env: &'a RefCell<Environment<O, E>>,
import_stack: &Vec<String>,
import_stack: &Vec<Rc<str>>,
) -> Result<(Rc<Value>, Position), Error>
where
O: std::io::Write + Clone,
@ -531,7 +530,7 @@ impl VM {
format!(
"Func called with too many args expected {} args but got {}",
arity, arg_length
),
).into(),
pos,
));
}
@ -540,7 +539,7 @@ impl VM {
format!(
"Func called with too few args expected {} args but got {}",
arity, arg_length
),
).into(),
pos,
));
}
@ -549,7 +548,7 @@ impl VM {
Self::fcall_impl(f, self.runtime.strict, &mut self.stack, env.clone(), &self.import_stack))?;
self.push(val, pos.clone())?;
} else {
return Err(Error::new(format!("Not a function! {:?}", f,), pos));
return Err(Error::new(format!("Not a function! {:?}", f,).into(), pos));
}
Ok(())
}
@ -569,7 +568,7 @@ impl VM {
format!(
"Expected Boolean but got {:?} in expression at {}",
operand, pos
),
).into(),
operand_pos,
));
}
@ -584,7 +583,7 @@ impl VM {
format!(
"Expected values of the same type but got {:?} at {} and {:?} at {} for expression",
left, left_pos, right, right_pos,
),
).into(),
pos,
));
}
@ -607,7 +606,7 @@ impl VM {
format!(
"Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
left, left_pos, right, right_pos,
),
).into(),
pos.clone(),
));
}
@ -630,7 +629,7 @@ impl VM {
format!(
"Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
left, left_pos, right, right_pos,
),
).into(),
pos.clone(),
));
}
@ -653,7 +652,7 @@ impl VM {
format!(
"Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
left, left_pos, right, right_pos,
),
).into(),
pos,
));
}
@ -676,7 +675,7 @@ impl VM {
format!(
"Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
left, left_pos, right, right_pos,
),
).into(),
pos,
));
}
@ -850,7 +849,7 @@ impl VM {
return Ok(());
}
return Err(Error::new(
format!("Invalid selector index: {:?} target: {:?}", right, left),
format!("Invalid selector index: {:?} target: {:?}", right, left).into(),
pos,
));
}
@ -869,7 +868,7 @@ impl VM {
}
} else {
return Err(Error::new(
format!("Expected String or Symbol got: {}", right.type_name()),
format!("Expected String or Symbol got: {}", right.type_name()).into(),
right_pos,
));
}
@ -884,13 +883,13 @@ impl VM {
}
&P(Str(ref s)) => {
if let &P(Str(ref part)) = right.as_ref() {
self.push(Rc::new(P(Bool(s.contains(part)))), pos)?;
self.push(Rc::new(P(Bool(s.contains(part.as_ref())))), pos)?;
return Ok(());
}
}
_ => {
return Err(Error::new(
format!("Expected String, Tuple, or List got: {}", left.type_name()),
format!("Expected String, Tuple, or List got: {}", left.type_name()).into(),
left_pos,
));
}
@ -974,7 +973,7 @@ impl VM {
self.merge_field_into_tuple(
&mut flds,
&mut flds_pos_list,
"this".to_owned(),
"this".into(),
&pos,
Rc::new(this),
&val_pos,
@ -989,7 +988,7 @@ impl VM {
self.merge_field_into_tuple(
&mut flds,
&mut flds_pos_list,
"pkg".to_owned(),
"pkg".into(),
&pos,
pkg_func,
&val_pos,
@ -1000,7 +999,7 @@ impl VM {
.clean_copy()
.to_new_pointer(ptr.clone())
.with_import_stack(self.import_stack.clone());
vm.push(Rc::new(S("mod".to_owned())), pos.clone())?;
vm.push(Rc::new(S("mod".into())), pos.clone())?;
vm.push(Rc::new(C(Tuple(flds, flds_pos_list))), pos.clone())?;
decorate_call!(pos => vm.run(env))?;
if let Some(ptr) = result_ptr {
@ -1014,7 +1013,7 @@ impl VM {
}
_ => {
return Err(Error::new(
format!("Expected a Tuple or Module but got {:?}", tgt),
format!("Expected a Tuple or Module but got {:?}", tgt).into(),
pos,
));
}
@ -1024,9 +1023,9 @@ impl VM {
fn merge_field_into_tuple(
&self,
src_fields: &mut Vec<(String, Rc<Value>)>,
src_fields: &mut Vec<(Rc<str>, Rc<Value>)>,
pos_fields: &mut Vec<(Position, Position)>,
name: String,
name: Rc<str>,
name_pos: &Position,
value: Rc<Value>,
val_pos: &Position,
@ -1043,7 +1042,7 @@ impl VM {
fld.1.type_name(),
name,
value.type_name(),
),
).into(),
val_pos.clone(),
));
}
@ -1065,21 +1064,21 @@ impl VM {
pub fn binding_push(
&mut self,
name: String,
name: Rc<str>,
val: Rc<Value>,
strict: bool,
pos: &Position,
name_pos: &Position,
) -> Result<(), Error> {
if self.reserved_words.contains(name.as_str()) {
if self.reserved_words.contains(name.as_ref()) {
return Err(Error::new(
format!("{} is a reserved word.", name),
format!("{} is a reserved word.", name).into(),
name_pos.clone(),
));
}
if self.symbols.is_bound(&name) && strict {
return Err(Error::new(
format!("Binding {} already exists", name),
format!("Binding {} already exists", name).into(),
pos.clone(),
));
}
@ -1116,7 +1115,7 @@ impl VM {
match tpl {
Some((v, pos)) => Ok((v, pos)),
None => {
return Err(Error::new(format!("No such binding {}", name), pos.clone()));
return Err(Error::new(format!("No such binding {}", name).into(), pos.clone()));
}
}
}
@ -1137,7 +1136,7 @@ impl VM {
(P(Float(f)), P(Float(ff))) => Float(f * ff),
_ => {
return Err(Error::new(
format!("Expected {} but got {:?}", left.type_name(), right),
format!("Expected {} but got {:?}", left.type_name(), right).into(),
pos.clone(),
))
}
@ -1150,7 +1149,7 @@ impl VM {
(P(Float(f)), P(Float(ff))) => Float(f / ff),
_ => {
return Err(Error::new(
format!("Expected {} but got {:?}", left.type_name(), right),
format!("Expected {} but got {:?}", left.type_name(), right).into(),
pos.clone(),
))
}
@ -1163,7 +1162,7 @@ impl VM {
(P(Float(f)), Value::P(Float(ff))) => Float(f - ff),
_ => {
return Err(Error::new(
format!("Expected {} but got {:?}", left.type_name(), right),
format!("Expected {} but got {:?}", left.type_name(), right).into(),
pos.clone(),
))
}
@ -1176,7 +1175,7 @@ impl VM {
(P(Float(f)), Value::P(Float(ff))) => Float(f % ff),
_ => {
return Err(Error::new(
format!("Expected {} but got {:?}", left.type_name(), right),
format!("Expected {} but got {:?}", left.type_name(), right).into(),
pos.clone(),
))
}
@ -1191,7 +1190,7 @@ impl VM {
let mut ns = String::new();
ns.push_str(&s);
ns.push_str(&ss);
P(Str(ns))
P(Str(ns.into()))
}
(
C(List(ref left_list, ref left_pos_list)),
@ -1216,7 +1215,7 @@ impl VM {
}
_ => {
return Err(Error::new(
format!("Expected {} but got {:?}", left.type_name(), right),
format!("Expected {} but got {:?}", left.type_name(), right).into(),
pos.clone(),
))
}

View File

@ -10,9 +10,9 @@ use crate::ast::PositionedItem;
use crate::build::ir::Val;
use crate::error;
pub fn find_in_fieldlist(target: &str, fs: &Vec<(String, Rc<Val>)>) -> Option<Rc<Val>> {
pub fn find_in_fieldlist(target: &str, fs: &Vec<(Rc<str>, Rc<Val>)>) -> Option<Rc<Val>> {
for (key, val) in fs.iter().cloned() {
if target == &key {
if target == key.as_ref() {
return Some(val.clone());
}
}
@ -20,7 +20,7 @@ pub fn find_in_fieldlist(target: &str, fs: &Vec<(String, Rc<Val>)>) -> Option<Rc
}
/// Defines a set of values in a parsed file.
pub type ValueMap = HashMap<PositionedItem<String>, Rc<Val>>;
pub type ValueMap = HashMap<PositionedItem<Rc<str>>, Rc<Val>>;
/// Defines a scope for execution in ucg.
///
@ -132,11 +132,11 @@ impl Scope {
/// valid when the current value is a tuple.
/// * everything else is looked up in the currently accumulated build output
/// for this execution context.
pub fn lookup_sym(&self, sym: &PositionedItem<String>, is_symbol: bool) -> Option<Rc<Val>> {
if &sym.val == "env" && is_symbol {
pub fn lookup_sym(&self, sym: &PositionedItem<Rc<str>>, is_symbol: bool) -> Option<Rc<Val>> {
if sym.val.as_ref() == "env" && is_symbol {
return Some(self.env.clone());
}
if &sym.val == "self" && is_symbol {
if sym.val.as_ref() == "self" && is_symbol {
return self.curr_val.clone();
}
if self.search_curr_val && self.curr_val.is_some() {
@ -179,7 +179,7 @@ impl Scope {
fn lookup_in_tuple(
pos: &Position,
field: &str,
fs: &Vec<(String, Rc<Val>)>,
fs: &Vec<(Rc<str>, Rc<Val>)>,
) -> Result<Rc<Val>, Box<dyn Error>> {
if let Some(vv) = find_in_fieldlist(&field, fs) {
Ok(vv)

View File

@ -153,7 +153,7 @@ fn test_expr_copy_no_such_tuple() {
vec![(
Expression::Copy(CopyDef {
selector: Value::Symbol(PositionedItem::new(
"tpl1".to_string(),
"tpl1".into(),
Position::new(1, 1, 1),
)),
fields: Vec::new(),

View File

@ -15,9 +15,9 @@ pub struct Base64Importer {
impl Importer for Base64Importer {
fn import(&self, bytes: &[u8]) -> Result<Rc<Val>, Box<dyn Error>> {
return if self.url_safe {
Ok(Rc::new(Val::Str(STANDARD.encode(bytes))))
Ok(Rc::new(Val::Str(STANDARD.encode(bytes).into())))
} else {
Ok(Rc::new(Val::Str(URL_SAFE.encode(bytes))))
Ok(Rc::new(Val::Str(URL_SAFE.encode(bytes).into())))
};
}
}

View File

@ -28,7 +28,7 @@ impl EnvConverter {
EnvConverter {}
}
fn convert_tuple(&self, flds: &Vec<(String, Rc<Val>)>, w: &mut dyn IOWrite) -> ConvertResult {
fn convert_tuple(&self, flds: &Vec<(Rc<str>, Rc<Val>)>, w: &mut dyn IOWrite) -> ConvertResult {
for &(ref name, ref val) in flds.iter() {
if val.is_tuple() {
eprintln!("Skipping embedded tuple...");

View File

@ -48,12 +48,12 @@ impl ExecConverter {
)
.to_boxed());
}
let mut env: Option<&Vec<(String, Rc<Val>)>> = None;
let mut env: Option<&Vec<(Rc<str>, Rc<Val>)>> = None;
let mut command: Option<&str> = None;
let mut args: Option<&Vec<Rc<Val>>> = None;
for &(ref name, ref val) in fields.iter() {
// We require a command field in our exec tuple.
if name == "command" {
if name.as_ref() == "command" {
if command.is_some() {
return Err(BuildError::new(
"There can only be one command field in an exec tuple",
@ -72,7 +72,7 @@ impl ExecConverter {
.to_boxed());
}
// We optionally allow an env field in our exec tuple.
if name == "env" {
if name.as_ref() == "env" {
if let &Val::Tuple(ref l) = val.as_ref() {
if env.is_some() {
return Err(BuildError::new(
@ -91,7 +91,7 @@ impl ExecConverter {
.to_boxed());
}
// We optionally allow an args field in our exec tuple.
if name == "args" {
if name.as_ref() == "args" {
if let &Val::List(ref l) = val.as_ref() {
if args.is_some() {
return Err(BuildError::new(

View File

@ -94,7 +94,7 @@ impl FlagConverter {
Ok(())
}
fn write(&self, pfx: &str, flds: &Vec<(String, Rc<Val>)>, w: &mut dyn Write) -> ConvertResult {
fn write(&self, pfx: &str, flds: &Vec<(Rc<str>, Rc<Val>)>, w: &mut dyn Write) -> ConvertResult {
for &(ref name, ref val) in flds.iter() {
if let &Val::Empty = val.as_ref() {
self.write_flag_name(pfx, name, w)?;

View File

@ -34,19 +34,19 @@ impl JsonConverter {
Ok(serde_json::Value::Array(v))
}
fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> std::io::Result<serde_json::Value> {
fn convert_tuple(&self, items: &Vec<(Rc<str>, Rc<Val>)>) -> std::io::Result<serde_json::Value> {
let mut mp = serde_json::Map::new();
for &(ref k, ref v) in items.iter() {
mp.entry(k.clone()).or_insert(self.convert_value(v)?);
mp.entry(k.as_ref()).or_insert(self.convert_value(v)?);
}
Ok(serde_json::Value::Object(mp))
}
fn convert_env(&self, items: &Vec<(String, String)>) -> std::io::Result<serde_json::Value> {
fn convert_env(&self, items: &Vec<(Rc<str>, Rc<str>)>) -> std::io::Result<serde_json::Value> {
let mut mp = serde_json::Map::new();
for &(ref k, ref v) in items.iter() {
mp.entry(k.clone())
.or_insert(serde_json::Value::String(v.clone()));
mp.entry(k.as_ref())
.or_insert(serde_json::Value::String(v.to_string()));
}
Ok(serde_json::Value::Object(mp))
}
@ -71,7 +71,7 @@ impl JsonConverter {
};
serde_json::Value::Number(n)
}
&Val::Str(ref s) => serde_json::Value::String(s.clone()),
&Val::Str(ref s) => serde_json::Value::String(s.to_string()),
&Val::Env(ref fs) => self.convert_env(fs)?,
&Val::List(ref l) => self.convert_list(l)?,
&Val::Tuple(ref t) => self.convert_tuple(t)?,
@ -81,7 +81,7 @@ impl JsonConverter {
fn convert_json_val(&self, v: &serde_json::Value) -> std::result::Result<Val, Box<dyn Error>> {
Ok(match v {
serde_json::Value::String(s) => Val::Str(s.clone()),
serde_json::Value::String(s) => Val::Str(s.clone().into()),
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
Val::Int(i)
@ -101,7 +101,7 @@ impl JsonConverter {
serde_json::Value::Object(m) => {
let mut fs = Vec::with_capacity(m.len());
for (key, value) in m {
fs.push((key.to_string(), Rc::new(self.convert_json_val(value)?)));
fs.push((key.clone().into(), Rc::new(self.convert_json_val(value)?)));
}
Val::Tuple(fs)
}

View File

@ -41,19 +41,19 @@ impl TomlConverter {
Ok(toml::Value::Array(v))
}
fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> Result {
fn convert_tuple(&self, items: &Vec<(Rc<str>, Rc<Val>)>) -> Result {
let mut mp = toml::value::Table::new();
for &(ref k, ref v) in items.iter() {
mp.entry(k.clone()).or_insert(self.convert_value(v)?);
mp.entry(k.to_string()).or_insert(self.convert_value(v)?);
}
Ok(toml::Value::Table(mp))
}
fn convert_env(&self, items: &Vec<(String, String)>) -> Result {
fn convert_env(&self, items: &Vec<(Rc<str>, Rc<str>)>) -> Result {
let mut mp = toml::value::Table::new();
for &(ref k, ref v) in items.iter() {
mp.entry(k.clone())
.or_insert(toml::Value::String(v.clone()));
mp.entry(k.to_string())
.or_insert(toml::Value::String(v.to_string()));
}
Ok(toml::Value::Table(mp))
}
@ -67,7 +67,7 @@ impl TomlConverter {
}
&Val::Float(f) => toml::Value::Float(f),
&Val::Int(i) => toml::Value::Integer(i),
&Val::Str(ref s) => toml::Value::String(s.clone()),
&Val::Str(ref s) => toml::Value::String(s.to_string()),
&Val::Env(ref fs) => self.convert_env(fs)?,
&Val::List(ref l) => self.convert_list(l)?,
&Val::Tuple(ref t) => self.convert_tuple(t)?,
@ -77,7 +77,7 @@ impl TomlConverter {
fn convert_toml_val(&self, v: &toml::Value) -> std::result::Result<Val, Box<dyn Error>> {
Ok(match v {
toml::Value::String(s) => Val::Str(s.clone()),
toml::Value::String(s) => Val::Str(s.clone().into()),
toml::Value::Integer(i) => Val::Int(*i),
toml::Value::Float(f) => Val::Float(*f),
toml::Value::Boolean(b) => Val::Boolean(*b),
@ -91,11 +91,11 @@ impl TomlConverter {
toml::Value::Table(m) => {
let mut fs = Vec::with_capacity(m.len());
for (key, value) in m {
fs.push((key.to_string(), Rc::new(self.convert_toml_val(value)?)));
fs.push((key.clone().into(), Rc::new(self.convert_toml_val(value)?)));
}
Val::Tuple(fs)
}
toml::Value::Datetime(d) => Val::Str(format!("{}", d)),
toml::Value::Datetime(d) => Val::Str(format!("{}", d).into()),
})
}

View File

@ -38,7 +38,7 @@ impl XmlConverter {
}
}
fn get_tuple_val(v: &Val) -> std::result::Result<&Vec<(String, Rc<Val>)>, Box<dyn Error>> {
fn get_tuple_val(v: &Val) -> std::result::Result<&Vec<(Rc<str>, Rc<Val>)>, Box<dyn Error>> {
if let Val::Tuple(ref fs) = v {
Ok(fs)
} else {
@ -58,15 +58,15 @@ impl XmlConverter {
// First we determine if this is a tag or text node
if let Val::Tuple(ref fs) = v {
let mut name: Option<&str> = None;
let mut attrs: Option<&Vec<(String, Rc<Val>)>> = None;
let mut attrs: Option<&Vec<(Rc<str>, Rc<Val>)>> = None;
let mut children: Option<&Vec<Rc<Val>>> = None;
let mut text: Option<&str> = None;
let mut ns: Option<(&str, &str)> = None;
for (ref field, ref val) in fs.iter() {
if field == "name" {
if field.as_ref() == "name" {
name = Some(Self::get_str_val(val.as_ref())?);
}
if field == "ns" {
if field.as_ref() == "ns" {
if let Val::Tuple(ref fs) = val.as_ref() {
let mut prefix = "";
let mut uri = "";
@ -74,10 +74,10 @@ impl XmlConverter {
if val.is_empty() {
continue;
}
if name == "uri" {
if name.as_ref() == "uri" {
uri = Self::get_str_val(val.as_ref())?;
}
if name == "prefix" {
if name.as_ref() == "prefix" {
prefix = Self::get_str_val(val.as_ref())?;
}
}
@ -88,19 +88,19 @@ impl XmlConverter {
ns = Some(("", s));
}
}
if field == "attrs" {
if field.as_ref() == "attrs" {
// This should be a tuple.
if !val.is_empty() {
attrs = Some(Self::get_tuple_val(val.as_ref())?);
}
}
if field == "children" {
if field.as_ref() == "children" {
// This should be a list of tuples.
if !val.is_empty() {
children = Some(Self::get_list_val(val.as_ref())?);
}
}
if field == "text" {
if field.as_ref() == "text" {
if !val.is_empty() {
text = Some(Self::get_str_val(val.as_ref())?);
}
@ -160,19 +160,19 @@ impl XmlConverter {
let mut standalone: Option<bool> = None;
let mut root: Option<Rc<Val>> = None;
for &(ref name, ref val) in fs.iter() {
if name == "version" {
if name.as_ref() == "version" {
version = Some(Self::get_str_val(val)?);
}
if name == "encoding" {
if name.as_ref() == "encoding" {
encoding = Some(Self::get_str_val(val)?);
}
if name == "standalone" {
if name.as_ref() == "standalone" {
standalone = match val.as_ref() {
Val::Boolean(b) => Some(*b),
_ => None,
};
}
if name == "root" {
if name.as_ref() == "root" {
root = Some(val.clone());
}
}

View File

@ -25,21 +25,21 @@ impl YamlConverter {
Ok(serde_yaml::Value::Sequence(v))
}
fn convert_env(&self, items: &Vec<(String, String)>) -> std::io::Result<serde_yaml::Value> {
fn convert_env(&self, items: &Vec<(Rc<str>, Rc<str>)>) -> std::io::Result<serde_yaml::Value> {
let mut mp = serde_yaml::Mapping::new();
for &(ref k, ref v) in items.iter() {
mp.insert(
serde_yaml::Value::String(k.clone()),
serde_yaml::Value::String(v.clone()),
serde_yaml::Value::String(k.to_string()),
serde_yaml::Value::String(v.to_string()),
);
}
Ok(serde_yaml::Value::Mapping(mp))
}
fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> std::io::Result<serde_yaml::Value> {
fn convert_tuple(&self, items: &Vec<(Rc<str>, Rc<Val>)>) -> std::io::Result<serde_yaml::Value> {
let mut mapping = serde_yaml::Mapping::new();
for &(ref k, ref v) in items.iter() {
mapping.insert(serde_yaml::Value::String(k.clone()), self.convert_value(v)?);
mapping.insert(serde_yaml::Value::String(k.to_string()), self.convert_value(v)?);
}
Ok(serde_yaml::Value::Mapping(mapping))
}
@ -56,7 +56,7 @@ impl YamlConverter {
Ok(v) => v,
_ => panic!("Int is too large or not a Number {}", i),
},
&Val::Str(ref s) => serde_yaml::Value::String(s.clone()),
&Val::Str(ref s) => serde_yaml::Value::String(s.to_string()),
&Val::Env(ref fs) => self.convert_env(fs)?,
&Val::List(ref l) => self.convert_list(l)?,
&Val::Tuple(ref t) => self.convert_tuple(t)?,
@ -97,7 +97,7 @@ impl YamlConverter {
fn convert_yaml_val(&self, v: &serde_yaml::Value) -> Result<Val, Box<dyn Error>> {
Ok(match v {
serde_yaml::Value::String(s) => Val::Str(s.clone()),
serde_yaml::Value::String(s) => Val::Str(s.clone().into()),
serde_yaml::Value::Number(n) => {
if let Some(i) = n.as_i64() {
Val::Int(i)
@ -122,7 +122,7 @@ impl YamlConverter {
let mut collapsed = Vec::with_capacity(fs.len());
for (k, val) in fs {
if !seen_keys.contains(&k) {
collapsed.push((k.clone(), val));
collapsed.push((k.clone().into(), val));
seen_keys.insert(k);
}
}

View File

@ -489,7 +489,7 @@ fn main() {
let mut import_paths = Vec::new();
let mut env_vars = BTreeMap::new();
for (var, val) in std::env::vars() {
env_vars.insert(var, val);
env_vars.insert(var.into(), val.into());
}
let env = RefCell::new(Environment::new_with_vars(
StdoutWrapper::new(),

View File

@ -71,7 +71,7 @@ macro_rules! trace_parse {
fn symbol_to_value(s: &Token) -> ConvertResult<Value> {
Ok(Value::Symbol(value_node!(
s.fragment.to_string(),
s.fragment.clone(),
s.pos.clone()
)))
}
@ -84,7 +84,7 @@ make_fn!(
fn str_to_value(s: &Token) -> ConvertResult<Value> {
Ok(Value::Str(value_node!(
s.fragment.to_string(),
s.fragment.clone(),
s.pos.clone()
)))
}
@ -125,7 +125,7 @@ fn triple_to_number<'a>(
}
let suf = match v.2 {
None => "".to_string(),
None => "".into(),
Some(bs) => bs.fragment,
};
@ -205,7 +205,7 @@ make_fn!(
do_each!(
b => match_type!(BOOLEAN),
(Value::Boolean(PositionedItem{
val: b.fragment == "true",
val: b.fragment.as_ref() == "true",
pos: b.pos,
}))
)
@ -367,7 +367,7 @@ fn tuple_to_func<'a>(
.drain(0..)
.map(|s| PositionedItem {
pos: s.pos().clone(),
val: s.to_string(),
val: s.to_string().into(),
})
.collect();
Ok(Expression::Func(FuncDef {
@ -567,7 +567,7 @@ make_fn!(
expr => expression,
_ => punct!(")"),
(Expression::Cast(CastDef{
cast_type: match typ.fragment.as_str() {
cast_type: match typ.fragment.as_ref() {
"int" => CastType::Int,
"float" => CastType::Float,
"str" => CastType::Str,
@ -812,7 +812,7 @@ macro_rules! match_binding_name {
let mut _i = $i.clone();
match match_type!(_i, BAREWORD) {
Result::Complete(i, t) => {
if t.fragment == "env" {
if t.fragment.as_ref() == "env" {
return Result::Abort(Error::new(
format!("Cannot use binding {}. It is a reserved word.", t.fragment),
Box::new($i.clone()),

View File

@ -14,6 +14,7 @@
//! The tokenization stage of the ucg compiler.
use std;
use std::rc::Rc;
use abortable_parser::combinators::*;
use abortable_parser::iter::SliceIter;
@ -104,7 +105,7 @@ make_fn!(strtok<OffsetStrIter, Token>,
(Token{
typ: TokenType::QUOTED,
pos: Position::from(&span),
fragment: frag.to_string(),
fragment: frag.into(),
})
)
);
@ -117,7 +118,7 @@ make_fn!(barewordtok<OffsetStrIter, Token>,
(Token{
typ: TokenType::BAREWORD,
pos: Position::from(&span),
fragment: frag.to_string(),
fragment: frag.into(),
})
)
);
@ -130,7 +131,7 @@ make_fn!(digittok<OffsetStrIter, Token>,
(Token{
typ: TokenType::DIGIT,
pos: Position::from(&span),
fragment: digits.to_string(),
fragment: digits.into(),
})
)
);
@ -145,7 +146,7 @@ make_fn!(booleantok<OffsetStrIter, Token>,
(Token{
typ: TokenType::BOOLEAN,
pos: Position::from(&span),
fragment: token.to_string(),
fragment: token.into(),
})
)
);
@ -161,7 +162,7 @@ macro_rules! do_text_token_tok {
(Token {
typ: $type,
pos: Position::from(&span),
fragment: frag.to_string(),
fragment: frag.into(),
})
)
};
@ -173,7 +174,7 @@ macro_rules! do_text_token_tok {
(Token {
typ: $type,
pos: Position::from(&span),
fragment: frag.to_string(),
fragment: frag.into(),
})
)
};
@ -414,7 +415,7 @@ make_fn!(whitespace<OffsetStrIter, Token>,
(Token{
typ: TokenType::WS,
pos: Position::from(&span),
fragment: String::new(),
fragment: "".into(),
})
)
);
@ -426,7 +427,7 @@ make_fn!(end_of_input<OffsetStrIter, Token>,
(Token{
typ: TokenType::END,
pos: Position::from(&span),
fragment: String::new(),
fragment: "".into(),
})
)
);
@ -557,7 +558,7 @@ pub fn tokenize<'a>(
}
// ensure that we always have an END token to go off of.
out.push(Token {
fragment: String::new(),
fragment: "".into(),
typ: TokenType::END,
pos: Position::from(&i),
});
@ -688,10 +689,12 @@ macro_rules! match_token {
($i:expr, $t:expr, $f:expr, $msg:expr, $h:expr) => {{
use abortable_parser::Result;
use std;
use std::rc::Rc;
let f: Rc<str> = $f.into();
let mut i_ = $i.clone();
let tok = i_.next();
if let Some(tok) = tok {
if tok.typ == $t && &tok.fragment == $f {
if tok.typ == $t && tok.fragment.as_ref() == f.as_ref() {
match $h(tok) {
std::result::Result::Ok(v) => Result::Complete(i_.clone(), v),
std::result::Result::Err(e) => {

View File

@ -11,7 +11,7 @@ fn test_empty_token() {
let result = emptytok(OffsetStrIter::new("NULL "));
assert!(result.is_complete(), "result {:?} is not done", result);
if let Result::Complete(_, tok) = result {
assert_eq!(tok.fragment, "NULL");
assert_eq!(tok.fragment.as_ref(), "NULL");
assert_eq!(tok.typ, TokenType::EMPTY);
}
}
@ -21,7 +21,7 @@ fn test_assert_token() {
let result = asserttok(OffsetStrIter::new("assert "));
assert!(result.is_complete(), "result {:?} is not done", result);
if let Result::Complete(_, tok) = result {
assert_eq!(tok.fragment, "assert");
assert_eq!(tok.fragment.as_ref(), "assert");
assert_eq!(tok.typ, TokenType::BAREWORD);
}
}
@ -31,7 +31,7 @@ fn test_out_token() {
let result = outtok(OffsetStrIter::new("out "));
assert!(result.is_complete(), "result {:?} is not done", result);
if let Result::Complete(_, tok) = result {
assert_eq!(tok.fragment, "out");
assert_eq!(tok.fragment.as_ref(), "out");
assert_eq!(tok.typ, TokenType::BAREWORD);
}
}
@ -41,7 +41,7 @@ fn test_out_token_with_comment() {
let result = outtok(OffsetStrIter::new("out//comment"));
assert!(result.is_complete(), "result {:?} is not done", result);
if let Result::Complete(_, tok) = result {
assert_eq!(tok.fragment, "out");
assert_eq!(tok.fragment.as_ref(), "out");
assert_eq!(tok.typ, TokenType::BAREWORD);
}
}
@ -66,7 +66,7 @@ fn test_string_with_escaping() {
let result = strtok(OffsetStrIter::new("\"foo \\\\ \\\"bar\""));
assert!(result.is_complete(), "result {:?} is not ok", result);
if let Result::Complete(_, tok) = result {
assert_eq!(tok.fragment, "foo \\ \"bar".to_string());
assert_eq!(tok.fragment.as_ref(), "foo \\ \"bar".to_string());
}
}
@ -77,7 +77,7 @@ fn test_tokenize_bareword_with_dash() {
assert!(result.is_ok(), "result {:?} is not ok", result);
if let Ok(toks) = result {
assert_eq!(toks.len(), 2);
assert_eq!(toks[0].fragment, "foo-bar");
assert_eq!(toks[0].fragment.as_ref(), "foo-bar");
}
}
@ -92,7 +92,7 @@ macro_rules! assert_token {
);
if let Result::Complete(_, tok) = result {
assert_eq!(tok.typ, $typ);
assert_eq!(tok.fragment, $input);
assert_eq!(tok.fragment.as_ref(), $input);
}
};
}
@ -204,7 +204,7 @@ fn test_parse_comment() {
cmt,
Token {
typ: TokenType::COMMENT,
fragment: " comment".to_string(),
fragment: " comment".into(),
pos: Position {
file: None,
line: 1,
@ -221,7 +221,7 @@ fn test_parse_comment() {
cmt,
Token {
typ: TokenType::COMMENT,
fragment: " comment".to_string(),
fragment: " comment".into(),
pos: Position {
file: None,
column: 1,
@ -238,7 +238,7 @@ fn test_parse_comment() {
cmt,
Token {
typ: TokenType::COMMENT,
fragment: " comment".to_string(),
fragment: " comment".into(),
pos: Position {
file: None,
column: 1,
@ -254,7 +254,7 @@ fn test_parse_comment() {
#[test]
fn test_match_word() {
let input = vec![Token {
fragment: "foo".to_string(),
fragment: "foo".into(),
typ: TokenType::BAREWORD,
pos: Position {
file: None,
@ -273,7 +273,7 @@ fn test_match_word() {
#[test]
fn test_match_word_empty_input() {
let input = vec![Token {
fragment: "".to_string(),
fragment: "".into(),
typ: TokenType::END,
pos: Position {
file: None,
@ -296,7 +296,7 @@ fn test_match_word_empty_input() {
#[test]
fn test_match_punct() {
let input = vec![Token {
fragment: "!".to_string(),
fragment: "!".into(),
typ: TokenType::PUNCT,
pos: Position {
file: None,
@ -315,7 +315,7 @@ fn test_match_punct() {
#[test]
fn test_match_type() {
let input = vec![Token {
fragment: "foo".to_string(),
fragment: "foo".into(),
typ: TokenType::BAREWORD,
pos: Position {
file: None,