From: Cassie Jones Date: Tue, 11 Feb 2020 01:42:07 +0000 (-0500) Subject: Change List to use Cow<[Sexp]> instead of Vec X-Git-Url: https://git.witchoflight.com/ess/commitdiff_plain Change List to use Cow<[Sexp]> instead of Vec We would like to use Cow<[Sexp]> since this enables storing slices inside the lists, and therefore allows you to calculate "cdr" efficiently. It doesn't improve "cons" at all, however, so this might not be the right option. --- diff --git a/src/parser.rs b/src/parser.rs index 6039a0d..0470fab 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -14,6 +14,7 @@ use sexp::Sexp; use span::{ByteSpan, Span}; +use std::borrow::Cow; // Parsing Types /////////////////////////////////////////////////////////////// @@ -206,7 +207,7 @@ pub fn parse_expression(input: &str, start_loc: usize) -> ParseResult parse_number(input, start_loc), + Some('0'..='9') => parse_number(input, start_loc), Some('(') | Some('{') | Some('[') => parse_list(input, start_loc), Some('#') => parse_character(input, start_loc), Some('"') => parse_string(input, start_loc), @@ -217,7 +218,7 @@ pub fn parse_expression(input: &str, start_loc: usize) -> ParseResult ParseResult ParseResult ParseResult ParseResult match (first_char, c) { ('(', ')') | ('{', '}') | ('[', ']') => { - return Done(&input[1..], Sexp::List(members, (start_loc, loc + 1))) + return Done(&input[1..], Sexp::List(Cow::from(members), (start_loc, loc + 1))) } _ => { return Error(ParseError::List( @@ -424,7 +425,7 @@ pub fn parse_symbol(input: &str, start_loc: usize) -> ParseResult { + Some(c @ '#') | Some(c @ ':') | Some(c @ '0'..='9') => { return Error(ParseError::Symbol( Box::new(ParseError::Unexpected(c, start_loc)), (0, 0).offset(start_loc), @@ -534,7 +535,6 @@ pub fn parse_character(input: &str, start_loc: usize) -> ParseResult where - Loc: Span, + Loc: Span + Clone, { /// A value representing a symbol. Sym(Cow<'a, str>, Loc), @@ -26,12 +26,12 @@ where /// decimal point will be parsed as a `Float`. Float(f64, Loc), /// A list of subexpressions. - List(Vec>, Loc), + List(Cow<'a, [Sexp<'a, Loc>]>, Loc), } impl<'a, Loc> Sexp<'a, Loc> where - Loc: Span, + Loc: Span + Clone, { /// Gives a reference to the source location contained in the `Sexp`. pub fn get_loc(&self) -> &Loc { @@ -67,19 +67,21 @@ where impl<'a, Loc> Sexp<'a, Loc> where - Loc: Span + Clone, + Loc: Span + ToOwned + Clone, + Loc::Owned: Span + Clone, { /// Take ownership of an s-expression's contents. - pub fn to_owned(&self) -> Sexp<'static, Loc> { - match *self { - Sexp::Sym(ref s, ref l) => Sexp::Sym(extend_cow(s), l.clone()), - Sexp::Str(ref s, ref l) => Sexp::Str(extend_cow(s), l.clone()), - Sexp::Char(c, ref l) => Sexp::Char(c, l.clone()), - Sexp::Int(i, ref l) => Sexp::Int(i, l.clone()), - Sexp::Float(f, ref l) => Sexp::Float(f, l.clone()), - Sexp::List(ref xs, ref l) => { - Sexp::List(xs.iter().map(Sexp::to_owned).collect(), l.clone()) - } + pub fn to_owned(&self) -> Sexp<'static, Loc::Owned> { + match self { + Sexp::Sym(s, l) => Sexp::Sym(extend_cow(s), l.to_owned()), + Sexp::Str(s, l) => Sexp::Str(extend_cow(s), l.to_owned()), + Sexp::Char(c, l) => Sexp::Char(*c, l.to_owned()), + Sexp::Int(i, l) => Sexp::Int(*i, l.to_owned()), + Sexp::Float(f, l) => Sexp::Float(*f, l.to_owned()), + Sexp::List(xs, l) => Sexp::List( + xs.iter().map(Sexp::to_owned).collect(), + l.to_owned(), + ), } } }