diff --git a/src/ast/helpers.rs b/src/ast/helpers.rs index e38887a..a19fadd 100644 --- a/src/ast/helpers.rs +++ b/src/ast/helpers.rs @@ -25,7 +25,7 @@ pub fn record_expr(rec: Vec<(&str, Expr)>) -> Expr { } pub fn assign(name: &str, expr: Expr) -> Statement { - Statement::Assign(define_expr(name, expr)) + Statement::Let(define_expr(name, expr)) } pub fn stmt_expr(expr: Expr) -> Statement { diff --git a/src/ast/types.rs b/src/ast/types.rs index 09aebbe..293b6cd 100644 --- a/src/ast/types.rs +++ b/src/ast/types.rs @@ -5,6 +5,11 @@ use std::collections::BTreeMap; /// An expression. #[derive(PartialEq, PartialOrd, Debug, Clone)] pub enum Expr { + Op { + lhs: Box, + op: Op, + rhs: Box, + }, Value(Value), Var(Name), Func(Box), @@ -32,11 +37,17 @@ pub enum Expr { */ } +#[derive(PartialEq, PartialOrd, Debug, Clone)] +pub enum Op { + Assign, + // Equals, +} + /// A statement. #[derive(PartialEq, PartialOrd, Debug, Clone)] pub enum Statement { Expr(Expr), - Assign(Definition), + Let(Definition), } #[derive(PartialEq, PartialOrd, Debug, Clone)] diff --git a/src/interpret/interpret.rs b/src/interpret/interpret.rs index a1bf58e..9facf9f 100644 --- a/src/interpret/interpret.rs +++ b/src/interpret/interpret.rs @@ -34,7 +34,7 @@ fn eval_statement( ) -> Result { match statement { ast::Statement::Expr(expr) => eval_expr(expr_env, state, expr), - ast::Statement::Assign(ast::Definition { name, expr }) => { + ast::Statement::Let(ast::Definition { name, expr }) => { let result = eval_expr(expr_env, state, expr)?; expr_env.insert(name.clone(), result.clone()); Ok(result) @@ -115,6 +115,7 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result Ok(v.clone()), }, + ast::Expr::Op { .. } => todo!("Implement bin op"), } } diff --git a/src/parser/parser.rs b/src/parser/parser.rs index d4de401..5f4b090 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -18,25 +18,33 @@ fn parse_definitions(tokens: &mut Tokens) -> ParseResult> { tokens.many(parse_definition) } +fn parse_set(tokens: &mut Tokens) -> ParseResult { + if let Some(_eq) = tokens.next_if(&Token::Equals) { + if let Some(expr) = parse_expr(tokens)? { + if let Some(_) = tokens.next_if(&Token::Semicolon) { + Ok(Some(expr)) + } else { + Err(Error::UnexpectedToken { + expected: Token::Semicolon, + got: tokens.next(), + }) + } + } else { + Err(Error::UnexpectedTokenForParser( + "expr".into(), + tokens.next(), + )) + } + } else { + Ok(None) + } +} + fn parse_definition(tokens: &mut Tokens) -> ParseResult { if let Some(_) = tokens.next_if(&Token::Let) { if let Some(name) = parse_identifier_name(tokens)? { - if let Some(_eq) = tokens.next_if(&Token::Equals) { - if let Some(expr) = parse_expr(tokens)? { - if let Some(_) = tokens.next_if(&Token::Semicolon) { - Ok(Some(ast::Definition { name, expr })) - } else { - Err(Error::UnexpectedToken { - expected: Token::Semicolon, - got: tokens.next(), - }) - } - } else { - Err(Error::UnexpectedTokenForParser( - "expr".into(), - tokens.next(), - )) - } + if let Some(expr) = parse_set(tokens)? { + Ok(Some(ast::Definition { name, expr })) } else { Err(Error::UnexpectedToken { expected: Token::Equals, @@ -64,7 +72,13 @@ fn parse_expr(tokens: &mut Tokens) -> ParseResult { args: args, })) } else { - Ok(Some(expr1)) + Ok(parse_set(tokens)? + .map(|expr2| ast::Expr::Op { + op: ast::Op::Assign, + lhs: Box::new(expr1.clone()), + rhs: Box::new(expr2), + }) + .or(Some(expr1))) } } else { Ok(None) @@ -79,6 +93,7 @@ fn parse_simple_expr(tokens: &mut Tokens) -> ParseResult { parse_bool, parse_fn, parse_record, + parse_vector, |t| t.between(&Token::OpenParen, &Token::CloseParen, parse_expr), ]) } @@ -123,6 +138,18 @@ fn parse_record(tokens: &mut Tokens) -> ParseResult { } } +fn parse_vector(tokens: &mut Tokens) -> ParseResult { + if let Some(vect) = tokens.between(&Token::OpenBracket, &Token::CloseBracket, |tokens| { + tokens.many_sep_by(&Token::Comma, parse_expr) + })? { + Ok(Some(ast::Expr::Value(ast::Value::Vector(ast::Vector( + vect, + ))))) + } else { + Ok(None) + } +} + fn parse_record_field_expr(tokens: &mut Tokens) -> ParseResult<(ast::Label, ast::Expr)> { if let Some(label) = parse_identifier_label(tokens)? { if let Some(_) = tokens.next_if(&Token::Colon) { @@ -244,6 +271,24 @@ mod tests { insta::assert_debug_snapshot!(result); } #[test] + fn vector_empty() { + let program = "[]".to_string(); + let result = parse(&mut scan(program), parse_expr); + insta::assert_debug_snapshot!(result); + } + #[test] + fn vector() { + let program = "[x, 1, 2 ,3]".to_string(); + let result = parse(&mut scan(program), parse_expr); + insta::assert_debug_snapshot!(result); + } + #[test] + fn assign() { + let program = "x = [2, { hello: 7 }];".to_string(); + let result = parse(&mut scan(program), parse_expr); + insta::assert_debug_snapshot!(result); + } + #[test] fn fn_def() { let program = "fn(a1, boco, c_c) { 108 }".to_string(); let result = parse(&mut scan(program), parse_expr); diff --git a/src/parser/snapshots/ayin__parser__parser__tests__assign.snap b/src/parser/snapshots/ayin__parser__parser__tests__assign.snap new file mode 100644 index 0000000..6085047 --- /dev/null +++ b/src/parser/snapshots/ayin__parser__parser__tests__assign.snap @@ -0,0 +1,42 @@ +--- +source: src/parser/parser.rs +expression: result +--- +Ok( + Op { + lhs: Var( + Name( + "x", + ), + ), + op: Assign, + rhs: Value( + Vector( + Vector( + [ + Value( + Int( + 2, + ), + ), + Value( + Record( + Record( + { + Label( + "hello", + ): Value( + Int( + 7, + ), + ), + }, + ), + ), + ), + ], + ), + ), + ), + }, +) diff --git a/src/parser/snapshots/ayin__parser__parser__tests__vector.snap b/src/parser/snapshots/ayin__parser__parser__tests__vector.snap new file mode 100644 index 0000000..c248ed9 --- /dev/null +++ b/src/parser/snapshots/ayin__parser__parser__tests__vector.snap @@ -0,0 +1,34 @@ +--- +source: src/parser/parser.rs +expression: result +--- +Ok( + Value( + Vector( + Vector( + [ + Var( + Name( + "x", + ), + ), + Value( + Int( + 1, + ), + ), + Value( + Int( + 2, + ), + ), + Value( + Int( + 3, + ), + ), + ], + ), + ), + ), +) diff --git a/src/parser/snapshots/ayin__parser__parser__tests__vector_empty.snap b/src/parser/snapshots/ayin__parser__parser__tests__vector_empty.snap new file mode 100644 index 0000000..fe4ff38 --- /dev/null +++ b/src/parser/snapshots/ayin__parser__parser__tests__vector_empty.snap @@ -0,0 +1,13 @@ +--- +source: src/parser/parser.rs +expression: result +--- +Ok( + Value( + Vector( + Vector( + [], + ), + ), + ), +)