From 0be692c57d2d01f6022d5d567dac3cc306929af0 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Wed, 30 Aug 2023 17:10:12 +0100 Subject: [PATCH 01/10] add extra data to OpenList and ParsingList --- src/compiler/sexp.rs | 48 ++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index 58d01ad5b..ffcb30590 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -204,14 +204,15 @@ enum SExpParseState { Bareword(Srcloc, Vec), //srcloc contains the file, line, column and length for the captured form QuotedText(Srcloc, u8, Vec), QuotedEscaped(Srcloc, u8, Vec), - OpenList(Srcloc), - ParsingList(Srcloc, Rc, Vec>), + OpenList(Srcloc, bool), + ParsingList(Srcloc, Rc, Vec>, bool), // Rc is for the inner state of the list, bool is is_structured TermList( Srcloc, Option>, // this is the second value in the dot expression Rc, // used for inner parsing Vec>, // list content ), + StartStructuredList(Srcloc), } #[derive(Debug, PartialEq, Eq)] @@ -540,12 +541,13 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - match current_state { SExpParseState::Empty => match this_char as char { // we are not currently in a list - '(' => resume(SExpParseState::OpenList(loc)), // move to OpenList state + '(' => resume(SExpParseState::OpenList(loc, false)), // move to OpenList state '\n' => resume(SExpParseState::Empty), // new line, same state ';' => resume(SExpParseState::CommentText), ')' => error(loc, "Too many close parens"), '"' => resume(SExpParseState::QuotedText(loc, b'"', Vec::new())), // match on " '\'' => resume(SExpParseState::QuotedText(loc, b'\'', Vec::new())), // match on ' + '#' => resume(SExpParseState::StartStructuredList(loc)), // initiating a structured list ch => { if char::is_whitespace(ch) { resume(SExpParseState::Empty) @@ -601,7 +603,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - tcopy.push(this_char); resume(SExpParseState::QuotedText(srcloc.clone(), *term, tcopy)) } - SExpParseState::OpenList(srcloc) => match this_char as char { + SExpParseState::OpenList(srcloc, is_structured) => match this_char as char { // we are beginning a new list ')' => emit(Rc::new(SExp::Nil(srcloc.ext(&loc))), SExpParseState::Empty), // create a Nil object '.' => error(loc, "Dot can't appear directly after begin paren"), @@ -612,33 +614,36 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - srcloc.ext(&loc), Rc::new(current_state), // captured state from our pretend empty state vec![o], + *is_structured, )), SExpParseResult::Resume(current_state) => resume(SExpParseState::ParsingList( // we're still reading the object, resume processing srcloc.ext(&loc), Rc::new(current_state), // captured state from our pretend empty state Vec::new(), + *is_structured, )), SExpParseResult::Error(l, e) => SExpParseResult::Error(l, e), // propagate error }, }, // We are in the middle of a list currently - SExpParseState::ParsingList(srcloc, pp, list_content) => { + SExpParseState::ParsingList(srcloc, pp, list_content, is_structured) => { // pp is the captured inside-list state we received from OpenList - match (this_char as char, pp.borrow()) { - ('.', SExpParseState::Empty) => resume(SExpParseState::TermList( + match (this_char as char, pp.borrow(), is_structured) { + ('.', SExpParseState::Empty, false) => resume(SExpParseState::TermList( // dot notation showing cons cell srcloc.ext(&loc), None, Rc::new(SExpParseState::Empty), // nested state is empty list_content.to_vec(), )), - (')', SExpParseState::Empty) => emit( + ('.', SExpParseState::Empty, true) => error(loc, "Dot expressions disallowed in structured lists"), + (')', SExpParseState::Empty, _) => emit( // close list and emit it upwards as a complete entity Rc::new(enlist(srcloc.clone(), list_content)), SExpParseState::Empty, ), - (')', SExpParseState::Bareword(l, t)) => { + (')', SExpParseState::Bareword(l, t), _) => { // you've reached the end of the word AND the end of the list, close list and emit upwards let parsed_atom = make_atom(l.clone(), t.to_vec()); let mut updated_list = list_content.to_vec(); @@ -649,7 +654,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - ) } // analyze this character using the mock "inner state" stored in pp - (_, _) => match parse_sexp_step(loc.clone(), pp.borrow(), this_char) { + (_, _, _) => match parse_sexp_step(loc.clone(), pp.borrow(), this_char) { // SExpParseResult::Emit(o, current_state) => { // add result of parse_sexp_step to our list @@ -659,6 +664,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - srcloc.ext(&loc), Rc::new(current_state), list_copy, + *is_structured, ); resume(result) } @@ -667,6 +673,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - srcloc.ext(&loc), Rc::new(rp), // store the returned state from parse_sexp_step in pp list_content.to_vec(), + *is_structured, )), SExpParseResult::Error(l, e) => SExpParseResult::Error(l, e), // propagate error upwards }, @@ -778,7 +785,21 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - SExpParseResult::Error(l, e) => SExpParseResult::Error(l, e), }, } - } + }, + SExpParseState::StartStructuredList(l) => { + let new_srcloc = l.ext(&loc); + match this_char as char { + '(' => resume(SExpParseState::ParsingList( + // we aren't finished reading in our nested state + new_srcloc, + Rc::new(SExpParseState::Empty), // store the returned state from parse_sexp_step in pp + Vec::new(), + true, + )), + _ => error(loc, "Expected '(' after '#'."), + } + }, + // SExpParseState::StartStructuredList(_) => error(loc, "Missing srcloc"), } } @@ -837,9 +858,10 @@ impl ParsePartialResult { SExpParseState::QuotedEscaped(l, _, _) => { Err((l, "unterminated quoted string with escape".to_string())) } - SExpParseState::OpenList(l) => Err((l, "Unterminated list (empty)".to_string())), - SExpParseState::ParsingList(l, _, _) => Err((l, "Unterminated mid list".to_string())), + SExpParseState::OpenList(l, _) => Err((l, "Unterminated list (empty)".to_string())), + SExpParseState::ParsingList(l, _, _, _) => Err((l, "Unterminated mid list".to_string())), SExpParseState::TermList(l, _, _, _) => Err((l, "Unterminated tail list".to_string())), + SExpParseState::StartStructuredList(l) => Err((l, "Unclosed structured list".to_string())), } } } From 3ec63c85543cd5df669c48f34460510678fd0626 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Wed, 30 Aug 2023 18:10:37 +0100 Subject: [PATCH 02/10] re-parse other characters as bareword if you see a # --- src/compiler/sexp.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index ffcb30590..901406a81 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -205,7 +205,7 @@ enum SExpParseState { QuotedText(Srcloc, u8, Vec), QuotedEscaped(Srcloc, u8, Vec), OpenList(Srcloc, bool), - ParsingList(Srcloc, Rc, Vec>, bool), // Rc is for the inner state of the list, bool is is_structured + ParsingList(Srcloc, Rc, Vec>, bool), // Rc is for the inner state of the list, bool is is_structured TermList( Srcloc, Option>, // this is the second value in the dot expression @@ -542,12 +542,12 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - SExpParseState::Empty => match this_char as char { // we are not currently in a list '(' => resume(SExpParseState::OpenList(loc, false)), // move to OpenList state - '\n' => resume(SExpParseState::Empty), // new line, same state + '\n' => resume(SExpParseState::Empty), // new line, same state ';' => resume(SExpParseState::CommentText), ')' => error(loc, "Too many close parens"), '"' => resume(SExpParseState::QuotedText(loc, b'"', Vec::new())), // match on " '\'' => resume(SExpParseState::QuotedText(loc, b'\'', Vec::new())), // match on ' - '#' => resume(SExpParseState::StartStructuredList(loc)), // initiating a structured list + '#' => resume(SExpParseState::StartStructuredList(loc)), // initiating a structured list ch => { if char::is_whitespace(ch) { resume(SExpParseState::Empty) @@ -637,7 +637,9 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - Rc::new(SExpParseState::Empty), // nested state is empty list_content.to_vec(), )), - ('.', SExpParseState::Empty, true) => error(loc, "Dot expressions disallowed in structured lists"), + ('.', SExpParseState::Empty, true) => { + error(loc, "Dot expressions disallowed in structured lists") + } (')', SExpParseState::Empty, _) => emit( // close list and emit it upwards as a complete entity Rc::new(enlist(srcloc.clone(), list_content)), @@ -785,7 +787,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - SExpParseResult::Error(l, e) => SExpParseResult::Error(l, e), }, } - }, + } SExpParseState::StartStructuredList(l) => { let new_srcloc = l.ext(&loc); match this_char as char { @@ -796,9 +798,13 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - Vec::new(), true, )), - _ => error(loc, "Expected '(' after '#'."), + _ => parse_sexp_step( + loc.clone(), + &SExpParseState::Bareword(loc, vec![b'#']), + this_char, + ), } - }, + } // SExpParseState::StartStructuredList(_) => error(loc, "Missing srcloc"), } } @@ -859,9 +865,13 @@ impl ParsePartialResult { Err((l, "unterminated quoted string with escape".to_string())) } SExpParseState::OpenList(l, _) => Err((l, "Unterminated list (empty)".to_string())), - SExpParseState::ParsingList(l, _, _, _) => Err((l, "Unterminated mid list".to_string())), + SExpParseState::ParsingList(l, _, _, _) => { + Err((l, "Unterminated mid list".to_string())) + } SExpParseState::TermList(l, _, _, _) => Err((l, "Unterminated tail list".to_string())), - SExpParseState::StartStructuredList(l) => Err((l, "Unclosed structured list".to_string())), + SExpParseState::StartStructuredList(l) => { + Err((l, "Unclosed structured list".to_string())) + } } } } From 2368ed4eac65c706b251c7035c37c5e66a727dc9 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Wed, 30 Aug 2023 18:52:56 +0100 Subject: [PATCH 03/10] fix incorrect comments --- src/compiler/sexp.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index 901406a81..3c420280d 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -792,20 +792,20 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - let new_srcloc = l.ext(&loc); match this_char as char { '(' => resume(SExpParseState::ParsingList( - // we aren't finished reading in our nested state + // go into a ParsingList new_srcloc, - Rc::new(SExpParseState::Empty), // store the returned state from parse_sexp_step in pp + Rc::new(SExpParseState::Empty), // we have no inner state Vec::new(), - true, + true, // note that this is a special StructuredList to be processed later )), _ => parse_sexp_step( + // if we don't see a '(' then process it as if the preceding '#' was part of a bareword loc.clone(), &SExpParseState::Bareword(loc, vec![b'#']), this_char, ), } - } - // SExpParseState::StartStructuredList(_) => error(loc, "Missing srcloc"), + } // SExpParseState::StartStructuredList(_) => error(loc, "Missing srcloc"), } } From 06ec158c3f0493f510e3f42fa56050d3964d423c Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Fri, 1 Sep 2023 15:11:21 +0100 Subject: [PATCH 04/10] added structured list creation and a test --- src/compiler/sexp.rs | 61 +++++++++++++++++++++++++++++----- src/tests/compiler/compiler.rs | 9 +++++ src/tests/compiler/srcloc.rs | 1 + 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index 3c420280d..9dabe9904 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -536,6 +536,28 @@ impl SExp { } } +fn restructure_list(mut this_list: Vec>, srcloc: Srcloc) -> Rc { + // Check if the vector is empty + if this_list.len() == 3 { + return Rc::new(make_cons(Rc::clone(&this_list[0]), Rc::new(make_cons(Rc::clone(&this_list[1]), Rc::clone(&this_list[2]))))); + } + if this_list.len() == 2 { + return Rc::new(make_cons(Rc::clone(&this_list[0]), Rc::clone(&this_list[1]))); + } + if this_list.len() == 1 { + return Rc::clone(&this_list[0]); + } + if this_list.len() == 0 { + return Rc::new(SExp::Nil(srcloc.clone())); + } + // Remove and get the middle element as the root + let mid_index = this_list.len() / 2; + let left_subtree = restructure_list(this_list.drain(..mid_index).collect(), srcloc.clone()); + let right_subtree = restructure_list(this_list, srcloc.clone()); + + Rc::new(make_cons(left_subtree, right_subtree)) +} + fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) -> SExpParseResult { // switch on our state match current_state { @@ -640,20 +662,41 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - ('.', SExpParseState::Empty, true) => { error(loc, "Dot expressions disallowed in structured lists") } - (')', SExpParseState::Empty, _) => emit( - // close list and emit it upwards as a complete entity - Rc::new(enlist(srcloc.clone(), list_content)), - SExpParseState::Empty, - ), + (')', SExpParseState::Empty, _) => { + if *is_structured { + emit( + // close list and emit it upwards as a complete entity + restructure_list(list_content.to_vec(), srcloc.clone()), + SExpParseState::Empty, + ) + } else { + emit( + // close list and emit it upwards as a complete entity + Rc::new(enlist(srcloc.clone(), list_content)), + SExpParseState::Empty, + ) + } + + }, (')', SExpParseState::Bareword(l, t), _) => { // you've reached the end of the word AND the end of the list, close list and emit upwards + // TODO: check bool and rearrange here let parsed_atom = make_atom(l.clone(), t.to_vec()); let mut updated_list = list_content.to_vec(); updated_list.push(Rc::new(parsed_atom)); - emit( - Rc::new(enlist(srcloc.clone(), &updated_list)), - SExpParseState::Empty, - ) + if *is_structured { + emit( + // close list and emit it upwards as a complete entity + restructure_list(updated_list, srcloc.clone()), + SExpParseState::Empty, + ) + } else { + emit( + // close list and emit it upwards as a complete entity + Rc::new(enlist(srcloc.clone(), &updated_list)), + SExpParseState::Empty, + ) + } } // analyze this character using the mock "inner state" stored in pp (_, _, _) => match parse_sexp_step(loc.clone(), pp.borrow(), this_char) { diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index 9a38cfb34..fc646120d 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -157,6 +157,15 @@ fn compile_test_6() { ); } +#[test] +fn compile_test_8() { + let result = compile_string(&"(mod (S) (c S (q . #(2000 3000 4000 5000 6000 7000 8000))))".to_string()).unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1 (2000 3000 . 4000) (5000 . 6000) 7000 . 8000)) (4 (1) 1))".to_string() + ); +} + fn run_test_1_maybe_opt(opt: bool) { let result = run_string_maybe_opt( &"(mod () (defun f (a b) (+ (* a a) b)) (f 3 1))".to_string(), diff --git a/src/tests/compiler/srcloc.rs b/src/tests/compiler/srcloc.rs index cbaa42594..040a6fd31 100644 --- a/src/tests/compiler/srcloc.rs +++ b/src/tests/compiler/srcloc.rs @@ -3,6 +3,7 @@ use crate::compiler::srcloc::Srcloc; // _ is the start to end range. // . is the target range. // X is an overlap. + // no _. #[test] fn test_overlap_1() { From 74955be07140ed3a4cf2147c4e0ba301e8edf5d2 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Fri, 1 Sep 2023 15:41:29 +0100 Subject: [PATCH 05/10] add more tests and remove redundant code --- src/compiler/sexp.rs | 6 ---- src/tests/compiler/compiler.rs | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index 9dabe9904..c21381b49 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -538,12 +538,6 @@ impl SExp { fn restructure_list(mut this_list: Vec>, srcloc: Srcloc) -> Rc { // Check if the vector is empty - if this_list.len() == 3 { - return Rc::new(make_cons(Rc::clone(&this_list[0]), Rc::new(make_cons(Rc::clone(&this_list[1]), Rc::clone(&this_list[2]))))); - } - if this_list.len() == 2 { - return Rc::new(make_cons(Rc::clone(&this_list[0]), Rc::clone(&this_list[1]))); - } if this_list.len() == 1 { return Rc::clone(&this_list[0]); } diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index fc646120d..1dbb75c0d 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -157,6 +157,7 @@ fn compile_test_6() { ); } +// odd numbered list #[test] fn compile_test_8() { let result = compile_string(&"(mod (S) (c S (q . #(2000 3000 4000 5000 6000 7000 8000))))".to_string()).unwrap(); @@ -166,6 +167,67 @@ fn compile_test_8() { ); } + +// even numbered list +#[test] +fn compile_test_9() { + let result = compile_string(&"(mod (S) (c S (q . #(a b c d))))".to_string()).unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1 (a . b) c . d)) (4 (1) 1))".to_string() + ); +} + +// word +#[test] +fn compile_test_10() { + let result = compile_string(&"(mod (S) (c S #fake))".to_string()).unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1 . fake)) (4 (1) 1))".to_string() + ); +} + +// op letter +#[test] +fn compile_test_11() { + let result = compile_string(&"(mod (S) (c S #a))".to_string()).unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1 . 2)) (4 (1) 1))".to_string() + ); +} + +// length 1 list +#[test] +fn compile_test_12() { + let result = compile_string(&"(mod (S) (c S (q . #(100))))".to_string()).unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1 . 100)) (4 (1) 1))".to_string() + ); +} + +// length 0 list +#[test] +fn compile_test_13() { + let result = compile_string(&"(mod (S) (c S (q . #())))".to_string()).unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1)) (4 (1) 1))".to_string() + ); +} + +// length 2 list +#[test] +fn compile_test_14() { + let result = compile_string(&"(mod (S) (c S (q . #(a b))))".to_string()).unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1 a . b)) (4 (1) 1))".to_string() + ); +} + fn run_test_1_maybe_opt(opt: bool) { let result = run_string_maybe_opt( &"(mod () (defun f (a b) (+ (* a a) b)) (f 3 1))".to_string(), From 3e09921b4859705ef737f44542c4557558fb1a6f Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Fri, 1 Sep 2023 16:52:16 +0100 Subject: [PATCH 06/10] add another test --- src/tests/compiler/compiler.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index 1dbb75c0d..3c27289b3 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -228,6 +228,21 @@ fn compile_test_14() { ); } +// use structured list in solution +#[test] +fn compile_test_15() { + let result = run_string_maybe_opt( + &"(mod #(a b c) (- (+ a c) b))".to_string(), + &"(100 20 . 10)".to_string(), + true, + ) + .unwrap(); + assert_eq!( + result.to_string(), + "90".to_string() + ); +} + fn run_test_1_maybe_opt(opt: bool) { let result = run_string_maybe_opt( &"(mod () (defun f (a b) (+ (* a a) b)) (f 3 1))".to_string(), From 7a4629ef46f59bfecc2543731a595ebfc3b7a4d5 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Fri, 1 Sep 2023 16:56:18 +0100 Subject: [PATCH 07/10] cargo fmt --- src/compiler/sexp.rs | 3 +-- src/tests/compiler/compiler.rs | 35 +++++++++------------------------- 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index c21381b49..0754b2c86 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -670,8 +670,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - SExpParseState::Empty, ) } - - }, + } (')', SExpParseState::Bareword(l, t), _) => { // you've reached the end of the word AND the end of the list, close list and emit upwards // TODO: check bool and rearrange here diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index 3c27289b3..9628bfbd8 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -160,14 +160,15 @@ fn compile_test_6() { // odd numbered list #[test] fn compile_test_8() { - let result = compile_string(&"(mod (S) (c S (q . #(2000 3000 4000 5000 6000 7000 8000))))".to_string()).unwrap(); + let result = + compile_string(&"(mod (S) (c S (q . #(2000 3000 4000 5000 6000 7000 8000))))".to_string()) + .unwrap(); assert_eq!( result, "(2 (1 4 5 (1 (2000 3000 . 4000) (5000 . 6000) 7000 . 8000)) (4 (1) 1))".to_string() ); } - // even numbered list #[test] fn compile_test_9() { @@ -182,50 +183,35 @@ fn compile_test_9() { #[test] fn compile_test_10() { let result = compile_string(&"(mod (S) (c S #fake))".to_string()).unwrap(); - assert_eq!( - result, - "(2 (1 4 5 (1 . fake)) (4 (1) 1))".to_string() - ); + assert_eq!(result, "(2 (1 4 5 (1 . fake)) (4 (1) 1))".to_string()); } // op letter #[test] fn compile_test_11() { let result = compile_string(&"(mod (S) (c S #a))".to_string()).unwrap(); - assert_eq!( - result, - "(2 (1 4 5 (1 . 2)) (4 (1) 1))".to_string() - ); + assert_eq!(result, "(2 (1 4 5 (1 . 2)) (4 (1) 1))".to_string()); } // length 1 list #[test] fn compile_test_12() { let result = compile_string(&"(mod (S) (c S (q . #(100))))".to_string()).unwrap(); - assert_eq!( - result, - "(2 (1 4 5 (1 . 100)) (4 (1) 1))".to_string() - ); + assert_eq!(result, "(2 (1 4 5 (1 . 100)) (4 (1) 1))".to_string()); } // length 0 list #[test] fn compile_test_13() { let result = compile_string(&"(mod (S) (c S (q . #())))".to_string()).unwrap(); - assert_eq!( - result, - "(2 (1 4 5 (1)) (4 (1) 1))".to_string() - ); + assert_eq!(result, "(2 (1 4 5 (1)) (4 (1) 1))".to_string()); } // length 2 list #[test] fn compile_test_14() { let result = compile_string(&"(mod (S) (c S (q . #(a b))))".to_string()).unwrap(); - assert_eq!( - result, - "(2 (1 4 5 (1 a . b)) (4 (1) 1))".to_string() - ); + assert_eq!(result, "(2 (1 4 5 (1 a . b)) (4 (1) 1))".to_string()); } // use structured list in solution @@ -237,10 +223,7 @@ fn compile_test_15() { true, ) .unwrap(); - assert_eq!( - result.to_string(), - "90".to_string() - ); + assert_eq!(result.to_string(), "90".to_string()); } fn run_test_1_maybe_opt(opt: bool) { From 5dd8894dc1b81e73884a96e80034f60d8b869d84 Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Fri, 1 Sep 2023 17:00:45 +0100 Subject: [PATCH 08/10] add one more test --- src/tests/compiler/compiler.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index 9628bfbd8..0315ffeda 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -226,6 +226,18 @@ fn compile_test_15() { assert_eq!(result.to_string(), "90".to_string()); } +// use structured list in solution +#[test] +fn compile_test_16() { + let result = run_string_maybe_opt( + &"(mod #(a b c) (- (+ a c) b))".to_string(), + &"#(100 20 10)".to_string(), + true, + ) + .unwrap(); + assert_eq!(result.to_string(), "90".to_string()); +} + fn run_test_1_maybe_opt(opt: bool) { let result = run_string_maybe_opt( &"(mod () (defun f (a b) (+ (* a a) b)) (f 3 1))".to_string(), From bfce61a044a6c2a91905a193d6fb01824bbddebf Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Tue, 5 Sep 2023 13:39:53 +0100 Subject: [PATCH 09/10] clippy fix --- src/compiler/sexp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index 0754b2c86..4fa4c6444 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -541,7 +541,7 @@ fn restructure_list(mut this_list: Vec>, srcloc: Srcloc) -> Rc { if this_list.len() == 1 { return Rc::clone(&this_list[0]); } - if this_list.len() == 0 { + if this_list.is_empty() { return Rc::new(SExp::Nil(srcloc.clone())); } // Remove and get the middle element as the root From 5869463c21893acc592572276db1dc1572f03552 Mon Sep 17 00:00:00 2001 From: arty Date: Wed, 25 Oct 2023 14:25:53 -0700 Subject: [PATCH 10/10] Fix drift --- src/tests/compiler/compiler.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index e7ac47991..232c4c70c 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -236,6 +236,7 @@ fn compile_test_15() { &"(mod #(a b c) (- (+ a c) b))".to_string(), &"(100 20 . 10)".to_string(), true, + false, ) .unwrap(); assert_eq!(result.to_string(), "90".to_string()); @@ -248,6 +249,7 @@ fn compile_test_16() { &"(mod #(a b c) (- (+ a c) b))".to_string(), &"#(100 20 10)".to_string(), true, + false, ) .unwrap(); assert_eq!(result.to_string(), "90".to_string());