Fix some implementation bugs found while testing REPL
This commit is contained in:
parent
cb256f0ce4
commit
c11b681d56
7 changed files with 49 additions and 14 deletions
|
@ -68,6 +68,7 @@ impl<Op: MpsOp + 'static, F: MpsFunctionFactory<Op> + 'static> BoxedMpsOpFactory
|
|||
assert_token_raw(MpsToken::OpenBracket, tokens)?;
|
||||
assert_token_raw_back(MpsToken::CloseBracket, tokens)?;
|
||||
let func = self.op_factory.build_function_params(name, tokens, dict)?;
|
||||
#[cfg(debug_assertions)]
|
||||
assert_empty(tokens)?;
|
||||
Ok(Box::new(func))
|
||||
}
|
||||
|
|
|
@ -133,12 +133,20 @@ impl MpsFunctionFactory<RepeatStatement> for RepeatFunctionFactory {
|
|||
let inner_statement = dict.try_build_statement(tokens)?;
|
||||
tokens.extend(end_tokens);
|
||||
let mut count: Option<usize> = None;
|
||||
let mut inner_done = false;
|
||||
if tokens.len() != 0 {
|
||||
// repititions specified
|
||||
assert_token_raw(MpsToken::Comma, tokens)?;
|
||||
count = Some(assert_token(
|
||||
|t| match t {
|
||||
MpsToken::Name(n) => n.parse::<usize>().map(|d| d - 1).ok(),
|
||||
MpsToken::Name(n) => n.parse::<usize>().map(
|
||||
|d| if d == 0 {
|
||||
inner_done = true;
|
||||
0
|
||||
} else {
|
||||
d-1
|
||||
}
|
||||
).ok(),
|
||||
_ => None,
|
||||
},
|
||||
MpsToken::Name("usize".into()),
|
||||
|
@ -147,7 +155,7 @@ impl MpsFunctionFactory<RepeatStatement> for RepeatFunctionFactory {
|
|||
}
|
||||
Ok(RepeatStatement {
|
||||
inner_statement: inner_statement.into(),
|
||||
inner_done: false,
|
||||
inner_done: inner_done,
|
||||
context: None,
|
||||
cache: Vec::new(),
|
||||
cache_position: 0,
|
||||
|
|
|
@ -85,7 +85,10 @@ impl Iterator for SqlStatement {
|
|||
match ctx.database.raw(&self.query, &mut move || {
|
||||
(Box::new(self_clone.clone()) as Box<dyn MpsOp>).into()
|
||||
}) {
|
||||
Err(e) => return Some(Err(e)),
|
||||
Err(e) => {
|
||||
self.rows = Some(Vec::with_capacity(0));
|
||||
return Some(Err(e));
|
||||
},
|
||||
Ok(rows) => {
|
||||
self.rows = Some(rows);
|
||||
self.get_item(false)
|
||||
|
|
|
@ -147,7 +147,10 @@ impl Iterator for SimpleSqlStatement {
|
|||
}),
|
||||
};
|
||||
match query_result {
|
||||
Err(e) => return Some(Err(e)),
|
||||
Err(e) => {
|
||||
self.rows = Some(Vec::with_capacity(0));
|
||||
return Some(Err(e));
|
||||
},
|
||||
Ok(rows) => {
|
||||
self.rows = Some(rows);
|
||||
self.get_item(false)
|
||||
|
|
|
@ -114,7 +114,13 @@ where
|
|||
}
|
||||
ReaderStateMachine::Invalid { .. } => {
|
||||
let invalid_char = bigger_buf.pop().unwrap(); // invalid single char
|
||||
Err(self.error(format!("Unexpected character {}", invalid_char)))?;
|
||||
// clear everything, to avoid further errors
|
||||
bigger_buf.clear();
|
||||
buf.clear();
|
||||
return match invalid_char {
|
||||
0 => Err(self.error(format!("EOF"))),
|
||||
_ => Err(self.error(format!("character {:?} ({})", invalid_char as char, invalid_char)))
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -137,7 +143,7 @@ where
|
|||
.map_err(|e| self.error(format!("UTF-8 encoding error: {}", e)))?;
|
||||
buf.push_back(
|
||||
MpsToken::parse_from_string(token)
|
||||
.map_err(|e| self.error(format!("Invalid token {}", e)))?,
|
||||
.map_err(|e| self.error(format!("invalid token {}", e)))?,
|
||||
);
|
||||
bigger_buf.clear();
|
||||
}
|
||||
|
@ -148,9 +154,11 @@ where
|
|||
fn do_tracking(&mut self, input: u8) {
|
||||
if input as char == '\n' {
|
||||
self.line += 1;
|
||||
}
|
||||
self.column = 0;
|
||||
} else {
|
||||
self.column += 1; // TODO correctly track columns with utf-8 characters longer than one byte
|
||||
}
|
||||
}
|
||||
|
||||
/// error factory (for ergonomics/DRY)
|
||||
fn error(&self, item: String) -> ParseError {
|
||||
|
@ -247,7 +255,7 @@ impl ReaderStateMachine {
|
|||
'`' => Self::StartTickLiteral {},
|
||||
'"' => Self::StartQuoteLiteral {},
|
||||
' ' => Self::EndToken {},
|
||||
'\n' | '\r' | ';' => Self::EndStatement {},
|
||||
'\n' | ';' => Self::EndStatement {},
|
||||
'\0' => Self::EndOfFile {},
|
||||
'(' | ')' | ',' | '=' | '<' | '>' | '.' => Self::SingleCharToken { out: input },
|
||||
_ => Self::Regular { out: input },
|
||||
|
@ -273,7 +281,7 @@ impl ReaderStateMachine {
|
|||
'/' => Self::Comment { out: input },
|
||||
' ' => Self::EndToken {},
|
||||
'\0' => Self::EndOfFile {},
|
||||
'\n' | '\r' | ';' => Self::EndStatement {},
|
||||
'\n' | ';' => Self::EndStatement {},
|
||||
_ => Self::Regular { out: input },
|
||||
},
|
||||
Self::Octothorpe { .. } => match input_char {
|
||||
|
|
|
@ -68,7 +68,7 @@ fn main() {
|
|||
// start REPL
|
||||
println!("Welcome to MPS interactive mode!");
|
||||
println!("Run ?help for usage instructions.");
|
||||
println!("End a statement with ; to execute it.");
|
||||
//println!("End a statement with ; to execute it.");
|
||||
repl::repl(args)
|
||||
}
|
||||
}
|
||||
|
|
16
src/repl.rs
16
src/repl.rs
|
@ -43,7 +43,13 @@ pub fn repl(args: CliArgs) {
|
|||
read_loop(&args, &mut state, || {
|
||||
match player.save_m3u8(&mut playlist_writer) {
|
||||
Ok(_) => {}
|
||||
Err(e) => eprintln!("{}", e.message()),
|
||||
Err(e) => {
|
||||
eprintln!("{}", e.message());
|
||||
// consume any further errors (this shouldn't actually write anything)
|
||||
while let Err(e) = player.save_m3u8(&mut playlist_writer) {
|
||||
eprintln!("{}", e.message());
|
||||
}
|
||||
},
|
||||
}
|
||||
playlist_writer
|
||||
.flush()
|
||||
|
@ -59,8 +65,15 @@ pub fn repl(args: CliArgs) {
|
|||
Err(e) => eprintln!("{}", e.message()),
|
||||
}
|
||||
} else {
|
||||
// consume all incoming errors
|
||||
let mut had_err = true;
|
||||
while had_err {
|
||||
let mut new_had_err = false;
|
||||
for e in ctrl.check_ack() {
|
||||
eprintln!("{}", e.message());
|
||||
new_had_err = true;
|
||||
}
|
||||
had_err = new_had_err;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -85,7 +98,6 @@ fn read_loop<F: FnMut()>(args: &CliArgs, state: &mut ReplState, mut execute: F)
|
|||
let statement_result = std::str::from_utf8(state.statement_buf.as_slice());
|
||||
if statement_result.is_ok() && statement_result.unwrap().starts_with("?") {
|
||||
repl_commands(statement_result.unwrap());
|
||||
state.writer.write(&[';' as u8]).unwrap_or(0);
|
||||
} else {
|
||||
state
|
||||
.writer
|
||||
|
|
Loading…
Reference in a new issue