Convertd like half the Strings to RC
-still need to eliminate some clones in eval, parse + fix all the tests
This commit is contained in:
parent
4a7b570603
commit
328ec4ba87
@ -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,
|
||||
|
21
src/eval.rs
21
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> = (T, Option<SideEffect>);
|
||||
|
||||
@ -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<String>, 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<Expression>) -> Reduction<Expression> {
|
||||
fn reduce_call(&mut self, name: Rc<String>, arguments: Vec<Expression>) -> Reduction<Expression> {
|
||||
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());
|
||||
|
@ -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<String>,
|
||||
pub name: Rc<String>,
|
||||
pub parameters: Vec<Rc<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Expression {
|
||||
Null,
|
||||
StringLiteral(String),
|
||||
StringLiteral(Rc<String>),
|
||||
Number(f64),
|
||||
Variable(String),
|
||||
BinExp(String, Box<Expression>, Box<Expression>),
|
||||
Call(String, Vec<Expression>),
|
||||
Variable(Rc<String>),
|
||||
BinExp(Rc<String>, Box<Expression>, Box<Expression>),
|
||||
Call(Rc<String>, Vec<Expression>),
|
||||
Conditional(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
|
||||
Lambda(Function),
|
||||
Block(VecDeque<Expression>),
|
||||
@ -218,9 +219,9 @@ impl Parser {
|
||||
|
||||
fn prototype(&mut self) -> ParseResult<Prototype> {
|
||||
use tokenizer::Token::*;
|
||||
let name: String = expect_identifier!(self);
|
||||
let name: Rc<String> = expect_identifier!(self);
|
||||
expect!(self, LParen);
|
||||
let parameters: Vec<String> = try!(self.identlist());
|
||||
let parameters: Vec<Rc<String>> = try!(self.identlist());
|
||||
expect!(self, RParen);
|
||||
Ok(Prototype {
|
||||
name: name,
|
||||
@ -228,11 +229,11 @@ impl Parser {
|
||||
})
|
||||
}
|
||||
|
||||
fn identlist(&mut self) -> ParseResult<Vec<String>> {
|
||||
fn identlist(&mut self) -> ParseResult<Vec<Rc<String>>> {
|
||||
use tokenizer::Token::*;
|
||||
let mut args: Vec<String> = Vec::new();
|
||||
let mut args: Vec<Rc<String>> = 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();
|
||||
|
@ -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<String>),
|
||||
Identifier(Rc<String>),
|
||||
Operator(Op),
|
||||
Keyword(Kw),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Op(pub String);
|
||||
pub struct Op(pub Rc<String>);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Kw {
|
||||
@ -92,14 +93,14 @@ fn tokenize_str(iter: &mut Peekable<Chars>) -> Result<Token, TokenizeError> {
|
||||
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<Chars>) -> Result<Token, TokenizeError> {
|
||||
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<Chars>) -> Result<Token, TokenizeError> {
|
||||
@ -138,7 +139,7 @@ fn tokenize_identifier(c: char, iter: &mut Peekable<Chars>) -> Result<Token, Tok
|
||||
"let" => 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");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user