From 328ec4ba870e9c24e6414a0fc99a6a02a6b67f5a Mon Sep 17 00:00:00 2001 From: greg Date: Wed, 4 Jan 2017 04:18:55 -0800 Subject: [PATCH] Convertd like half the Strings to RC -still need to eliminate some clones in eval, parse + fix all the tests --- src/compilation.rs | 8 ++++---- src/eval.rs | 21 +++++++++++---------- src/parser.rs | 23 ++++++++++++----------- src/tokenizer.rs | 15 ++++++++------- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/compilation.rs b/src/compilation.rs index 10d72ea..e775dcd 100644 --- a/src/compilation.rs +++ b/src/compilation.rs @@ -123,11 +123,11 @@ impl CodeGen for Expression { let int_type = LLVMWrap::Int64TypeInContext(data.context); match self { - &Variable(ref name) => *data.variables.get(name).unwrap(), - &BinExp(ref op, ref left, ref right) if op == "=" => { + &Variable(ref name) => *data.variables.get(&**name).unwrap(), + &BinExp(ref op, ref left, ref right) if **op == "=" => { if let Variable(ref name) = **left { let new_value = right.codegen(data); - data.variables.insert(name.clone(), new_value); + data.variables.insert((**name).clone(), new_value); new_value } else { panic!("Bad variable assignment") @@ -136,7 +136,7 @@ impl CodeGen for Expression { &BinExp(ref op, ref left, ref right) => { let lhs = left.codegen(data); let rhs = right.codegen(data); - let generator = match op.as_ref() { + let generator = match op.as_ref().as_ref() { "+" => LLVMWrap::BuildAdd, "-" => LLVMWrap::BuildSub, "*" => LLVMWrap::BuildMul, diff --git a/src/eval.rs b/src/eval.rs index 123b901..89b5075 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -2,6 +2,7 @@ extern crate take_mut; use std::collections::HashMap; use parser::{AST, Statement, Expression, Function}; +use std::rc::Rc; type Reduction = (T, Option); @@ -94,7 +95,7 @@ impl Expression { use parser::Expression::*; match *self { Null => false, - StringLiteral(ref s) if s == "" => false, + StringLiteral(ref s) if **s == "" => false, Number(0.0) => false, _ => true, } @@ -128,7 +129,7 @@ impl<'a> Evaluator<'a> { self.add_binding(var, value); }, AddFunctionBinding(function) => { - self.add_function(function.prototype.name.clone(), function); + self.add_function((*function.prototype.name).clone(), function); } } } @@ -171,10 +172,10 @@ impl<'a> Evaluator<'a> { } // special case for variable assignment - if op == "=" { + if *op == "=" { match left { Variable(var) => { - let binding = SideEffect::AddBinding(var, right); + let binding = SideEffect::AddBinding((*var).clone(), right); return (Null, Some(binding)); } _ => return (Null, None), @@ -243,13 +244,13 @@ impl<'a> Evaluator<'a> { } } - fn reduce_binop(&mut self, op: String, left: Expression, right: Expression) -> Expression { + fn reduce_binop(&mut self, op: Rc, left: Expression, right: Expression) -> Expression { use parser::Expression::*; let truthy = Number(1.0); let falsy = Null; match (&op[..], left, right) { ("+", Number(l), Number(r)) => Number(l + r), - ("+", StringLiteral(s1), StringLiteral(s2)) => StringLiteral(format!("{}{}", s1, s2)), + ("+", StringLiteral(s1), StringLiteral(s2)) => StringLiteral(Rc::new(format!("{}{}", *s1, *s2))), ("-", Number(l), Number(r)) => Number(l - r), ("*", Number(l), Number(r)) => Number(l * r), ("/", Number(l), Number(r)) if r != 0.0 => Number(l / r), @@ -266,12 +267,12 @@ impl<'a> Evaluator<'a> { } } - fn reduce_call(&mut self, name: String, arguments: Vec) -> Reduction { + fn reduce_call(&mut self, name: Rc, arguments: Vec) -> Reduction { use parser::Expression::*; use parser::Statement::*; // ugly hack for now - if name == "print" { + if *name == "print" { let mut s = String::new(); for arg in arguments { s.push_str(&format!("{}\n", arg)); @@ -279,7 +280,7 @@ impl<'a> Evaluator<'a> { return (Null, Some(SideEffect::Print(s))); } - let function = match self.lookup_function(name) { + let function = match self.lookup_function((*name).clone()) { Some(func) => func, None => return (Null, None), }; @@ -290,7 +291,7 @@ impl<'a> Evaluator<'a> { let mut evaluator = Evaluator::new(Some(self)); for (binding, expr) in function.prototype.parameters.iter().zip(arguments.iter()) { - evaluator.add_binding(binding.clone(), expr.clone()); + evaluator.add_binding((**binding).clone(), expr.clone()); } let nodes = function.body.iter().map(|node| node.clone()); diff --git a/src/parser.rs b/src/parser.rs index de90b7d..b9f0eec 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,7 @@ use std::fmt; use tokenizer::{Token, Kw, Op}; use std::collections::VecDeque; +use std::rc::Rc; // Grammar // program := (statement delimiter ?)* @@ -46,18 +47,18 @@ pub struct Function { #[derive(Debug, Clone, PartialEq)] pub struct Prototype { - pub name: String, - pub parameters: Vec, + pub name: Rc, + pub parameters: Vec>, } #[derive(Debug, Clone)] pub enum Expression { Null, - StringLiteral(String), + StringLiteral(Rc), Number(f64), - Variable(String), - BinExp(String, Box, Box), - Call(String, Vec), + Variable(Rc), + BinExp(Rc, Box, Box), + Call(Rc, Vec), Conditional(Box, Box, Option>), Lambda(Function), Block(VecDeque), @@ -218,9 +219,9 @@ impl Parser { fn prototype(&mut self) -> ParseResult { use tokenizer::Token::*; - let name: String = expect_identifier!(self); + let name: Rc = expect_identifier!(self); expect!(self, LParen); - let parameters: Vec = try!(self.identlist()); + let parameters: Vec> = try!(self.identlist()); expect!(self, RParen); Ok(Prototype { name: name, @@ -228,11 +229,11 @@ impl Parser { }) } - fn identlist(&mut self) -> ParseResult> { + fn identlist(&mut self) -> ParseResult>> { use tokenizer::Token::*; - let mut args: Vec = Vec::new(); + let mut args: Vec> = Vec::new(); while let Some(Identifier(name)) = self.peek() { - args.push(name); + args.push(name.clone()); self.next(); if let Some(Comma) = self.peek() { self.next(); diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 4eec754..fcbb793 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -3,6 +3,7 @@ extern crate itertools; use std::iter::Peekable; use std::str::Chars; use self::itertools::Itertools; +use std::rc::Rc; #[derive(Debug, Clone, PartialEq)] pub enum Token { @@ -14,14 +15,14 @@ pub enum Token { Period, Colon, NumLiteral(f64), - StrLiteral(String), - Identifier(String), + StrLiteral(Rc), + Identifier(Rc), Operator(Op), Keyword(Kw), } #[derive(Debug, Clone, PartialEq)] -pub struct Op(pub String); +pub struct Op(pub Rc); #[derive(Debug, Clone, PartialEq)] pub enum Kw { @@ -92,14 +93,14 @@ fn tokenize_str(iter: &mut Peekable) -> Result { None => return Err(TokenizeError::new("Unclosed quote")), } } - Ok(Token::StrLiteral(buffer)) + Ok(Token::StrLiteral(Rc::new(buffer))) } fn tokenize_operator(c: char, iter: &mut Peekable) -> Result { let mut buffer = String::new(); buffer.push(c); buffer.extend(iter.peeking_take_while(|x| !char::is_alphanumeric(*x) && !char::is_whitespace(*x))); - Ok(Token::Operator(Op(buffer))) + Ok(Token::Operator(Op(Rc::new(buffer)))) } fn tokenize_number_or_period(c: char, iter: &mut Peekable) -> Result { @@ -138,7 +139,7 @@ fn tokenize_identifier(c: char, iter: &mut Peekable) -> Result Keyword(Kw::Let), "fn" => Keyword(Kw::Fn), "null" => Keyword(Kw::Null), - b => Identifier(b.to_string()), + b => Identifier(Rc::new(b.to_string())), }) } @@ -181,7 +182,7 @@ mod tests { #[test] fn string_test() { token_test!("null + \"a string\"", - [Keyword(Kw::Null), Operator(Op(ref a)), StrLiteral(ref b)], + [Keyword(Kw::Null), Operator(Op(ref a)), StrgLiteral(ref b)], a == "+" && b == "a string"); }