Structs implemented
albeit very inefficiently
This commit is contained in:
parent
f0de3c3d12
commit
5d15d60ab6
@ -16,6 +16,7 @@ type Reduction<T> = (T, Option<SideEffect>);
|
|||||||
enum ReducedValue {
|
enum ReducedValue {
|
||||||
StringLiteral(Rc<String>),
|
StringLiteral(Rc<String>),
|
||||||
ListLiteral(VecDeque<Expression>),
|
ListLiteral(VecDeque<Expression>),
|
||||||
|
StructLiteral(VecDeque<(Rc<String>, Expression)>),
|
||||||
Number(f64),
|
Number(f64),
|
||||||
Lambda(Function),
|
Lambda(Function),
|
||||||
}
|
}
|
||||||
@ -27,6 +28,7 @@ impl From<ReducedValue> for Expression {
|
|||||||
ReducedValue::StringLiteral(n) => Expression::StringLiteral(n),
|
ReducedValue::StringLiteral(n) => Expression::StringLiteral(n),
|
||||||
ReducedValue::Lambda(f) => Expression::Lambda(f),
|
ReducedValue::Lambda(f) => Expression::Lambda(f),
|
||||||
ReducedValue::ListLiteral(items) => Expression::ListLiteral(items),
|
ReducedValue::ListLiteral(items) => Expression::ListLiteral(items),
|
||||||
|
ReducedValue::StructLiteral(items) => Expression::StructLiteral(items),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,6 +40,7 @@ impl From<Expression> for ReducedValue {
|
|||||||
Expression::StringLiteral(n) => ReducedValue::StringLiteral(n),
|
Expression::StringLiteral(n) => ReducedValue::StringLiteral(n),
|
||||||
Expression::Lambda(f) => ReducedValue::Lambda(f),
|
Expression::Lambda(f) => ReducedValue::Lambda(f),
|
||||||
Expression::ListLiteral(items) => ReducedValue::ListLiteral(items),
|
Expression::ListLiteral(items) => ReducedValue::ListLiteral(items),
|
||||||
|
Expression::StructLiteral(items) => ReducedValue::StructLiteral(items),
|
||||||
_ => panic!("trying to store a non-fully-reduced variable"),
|
_ => panic!("trying to store a non-fully-reduced variable"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,6 +123,9 @@ impl Evaluable for Expression {
|
|||||||
ListLiteral(ref items) => {
|
ListLiteral(ref items) => {
|
||||||
items.iter().any(|x| x.is_reducible())
|
items.iter().any(|x| x.is_reducible())
|
||||||
}
|
}
|
||||||
|
StructLiteral(ref items) => {
|
||||||
|
items.iter().any(|pair| pair.1.is_reducible())
|
||||||
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,6 +220,7 @@ impl<'a> Evaluator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO I probably want another Expression variant that holds a ReducedValue
|
||||||
fn reduce_expr(&mut self, expression: Expression) -> Reduction<Expression> {
|
fn reduce_expr(&mut self, expression: Expression) -> Reduction<Expression> {
|
||||||
match expression {
|
match expression {
|
||||||
Null => (Null, None),
|
Null => (Null, None),
|
||||||
@ -348,6 +355,14 @@ impl<'a> Evaluator<'a> {
|
|||||||
(Null, None)
|
(Null, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(StructLiteral(items), StringLiteral(s)) => {
|
||||||
|
for item in items {
|
||||||
|
if s == item.0 {
|
||||||
|
return (item.1.clone(), None); //TODO this is hella inefficient
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Null, None)
|
||||||
|
},
|
||||||
_ => (Null, None)
|
_ => (Null, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,6 +380,23 @@ impl<'a> Evaluator<'a> {
|
|||||||
}
|
}
|
||||||
(ListLiteral(exprs), side_effect)
|
(ListLiteral(exprs), side_effect)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
StructLiteral(mut items) => {
|
||||||
|
let mut side_effect = None;
|
||||||
|
for pair in items.iter_mut() {
|
||||||
|
if pair.1.is_reducible() {
|
||||||
|
take_mut::take(pair, |pair| {
|
||||||
|
let (name, expr) = pair;
|
||||||
|
let (a, b) = self.reduce_expr(expr);
|
||||||
|
side_effect = b;
|
||||||
|
(name, a)
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(StructLiteral(items), side_effect)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,15 +12,17 @@ use std::convert::From;
|
|||||||
// statement := declaration | expression
|
// statement := declaration | expression
|
||||||
// declaration := FN prototype LCurlyBrace (statement)* RCurlyBrace
|
// declaration := FN prototype LCurlyBrace (statement)* RCurlyBrace
|
||||||
// prototype := identifier LParen identlist RParen
|
// prototype := identifier LParen identlist RParen
|
||||||
// identlist := Ident (Comma Ident)* | e
|
// identlist := Ident (Comma Ident)* | ε
|
||||||
// exprlist := Expression (Comma Expression)* | e
|
// exprlist := Expression (Comma Expression)* | ε
|
||||||
|
// itemlist := Ident COLON Expression (Comma Ident COLON Expression)* | ε
|
||||||
//
|
//
|
||||||
// expression := postop_expression (op postop_expression)*
|
// expression := postop_expression (op postop_expression)*
|
||||||
// postop_expression := primary_expression postop
|
// postop_expression := primary_expression postop
|
||||||
// primary_expression := number_expr | String | identifier_expr | paren_expr | conditional_expr | while_expr | lambda_expr | list_expr
|
// primary_expression := number_expr | String | identifier_expr | paren_expr | conditional_expr | while_expr | lambda_expr | list_expr | struct_expr
|
||||||
// number_expr := (PLUS | MINUS ) number_expr | Number
|
// number_expr := (PLUS | MINUS ) number_expr | Number
|
||||||
// identifier_expr := call_expression | Variable
|
// identifier_expr := call_expression | Variable
|
||||||
// list_expr := LSquareBracket exprlist RSquareBracket
|
// list_expr := LSquareBracket exprlist RSquareBracket
|
||||||
|
// struct_expr := LCurlyBrace itemlist RCurlyBrace
|
||||||
// call_expression := Identifier LParen exprlist RParen
|
// call_expression := Identifier LParen exprlist RParen
|
||||||
// while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace
|
// while_expr := WHILE primary_expression LCurlyBrace (expression delimiter)* RCurlyBrace
|
||||||
// paren_expr := LParen expression RParen
|
// paren_expr := LParen expression RParen
|
||||||
@ -75,6 +77,7 @@ pub enum Expression {
|
|||||||
While(Box<Expression>, Vec<Expression>),
|
While(Box<Expression>, Vec<Expression>),
|
||||||
Index(Box<Expression>, Box<Expression>),
|
Index(Box<Expression>, Box<Expression>),
|
||||||
ListLiteral(VecDeque<Expression>),
|
ListLiteral(VecDeque<Expression>),
|
||||||
|
StructLiteral(VecDeque<(Rc<String>, Expression)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -83,6 +86,7 @@ pub enum Callable {
|
|||||||
Lambda(Function),
|
Lambda(Function),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO this ought to be ReducedExpression
|
||||||
impl fmt::Display for Expression {
|
impl fmt::Display for Expression {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use self::Expression::*;
|
use self::Expression::*;
|
||||||
@ -104,6 +108,17 @@ impl fmt::Display for Expression {
|
|||||||
}
|
}
|
||||||
write!(f, " ]")
|
write!(f, " ]")
|
||||||
}
|
}
|
||||||
|
StructLiteral(ref items) => {
|
||||||
|
write!(f, "{} ", "{")?;
|
||||||
|
let mut iter = items.iter().peekable();
|
||||||
|
while let Some(pair) = iter.next() {
|
||||||
|
write!(f, "{}: {}", pair.0, pair.1)?;
|
||||||
|
if let Some(_) = iter.peek() {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(f, "{} ", "}")
|
||||||
|
}
|
||||||
_ => write!(f, "UNIMPLEMENTED"),
|
_ => write!(f, "UNIMPLEMENTED"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,6 +376,24 @@ impl Parser {
|
|||||||
Ok(exprs)
|
Ok(exprs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn itemlist(&mut self) -> ParseResult<VecDeque<(Rc<String>, Expression)>> {
|
||||||
|
let mut items = VecDeque::new();
|
||||||
|
loop {
|
||||||
|
if let Some(RCurlyBrace) = self.peek() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let name = expect_identifier!(self);
|
||||||
|
expect!(self, Colon);
|
||||||
|
let expr = self.expression()?;
|
||||||
|
items.push_back((name, expr));
|
||||||
|
match self.peek() {
|
||||||
|
Some(Comma) => {self.next();},
|
||||||
|
_ => break,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(items)
|
||||||
|
}
|
||||||
|
|
||||||
fn body(&mut self) -> ParseResult<Vec<Statement>> {
|
fn body(&mut self) -> ParseResult<Vec<Statement>> {
|
||||||
let statements = delimiter_block!(
|
let statements = delimiter_block!(
|
||||||
self,
|
self,
|
||||||
@ -446,6 +479,7 @@ impl Parser {
|
|||||||
Some(Token::LParen) => self.paren_expr()?,
|
Some(Token::LParen) => self.paren_expr()?,
|
||||||
Some(Keyword(Kw::Fn)) => self.lambda_expr()?,
|
Some(Keyword(Kw::Fn)) => self.lambda_expr()?,
|
||||||
Some(Token::LSquareBracket) => self.list_expr()?,
|
Some(Token::LSquareBracket) => self.list_expr()?,
|
||||||
|
Some(Token::LCurlyBrace) => self.struct_expr()?,
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
return ParseError::result_from_str(&format!("Expected primary expression, got \
|
return ParseError::result_from_str(&format!("Expected primary expression, got \
|
||||||
{:?}",
|
{:?}",
|
||||||
@ -463,6 +497,13 @@ impl Parser {
|
|||||||
Ok(Expression::ListLiteral(VecDeque::from(exprlist)))
|
Ok(Expression::ListLiteral(VecDeque::from(exprlist)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn struct_expr(&mut self) -> ParseResult<Expression> {
|
||||||
|
expect!(self, LCurlyBrace);
|
||||||
|
let struct_items = self.itemlist()?;
|
||||||
|
expect!(self, RCurlyBrace);
|
||||||
|
Ok(Expression::StructLiteral(struct_items))
|
||||||
|
}
|
||||||
|
|
||||||
fn number_expression(&mut self) -> ParseResult<Expression> {
|
fn number_expression(&mut self) -> ParseResult<Expression> {
|
||||||
let mut multiplier = 1;
|
let mut multiplier = 1;
|
||||||
loop {
|
loop {
|
||||||
|
Loading…
Reference in New Issue
Block a user