Don't persist defs if they have errors

This commit is contained in:
Richard Feldman 2022-10-30 03:42:30 -04:00
parent 60d2d00651
commit 4d8a3ba3d7
No known key found for this signature in database
GPG key ID: F1F21AA5B1D9E43B
4 changed files with 32 additions and 47 deletions

View file

@ -25,7 +25,6 @@ pub fn gen_and_eval_llvm<'a>(
src: &str,
target: Triple,
opt_level: OptLevel,
var_name: String,
) -> (Option<ReplOutput>, Problems) {
let arena = Bump::new();
let target_info = TargetInfo::from(&target);
@ -64,7 +63,6 @@ pub fn gen_and_eval_llvm<'a>(
Some(ReplOutput {
expr: "<function>".to_string(),
expr_type: expr_type_str,
var_name,
}),
problems,
);
@ -90,10 +88,7 @@ pub fn gen_and_eval_llvm<'a>(
target_info,
);
(
Some(format_answer(&arena, expr, expr_type_str, var_name)),
problems,
)
(Some(format_answer(&arena, expr, expr_type_str)), problems)
}
struct CliApp {

View file

@ -190,31 +190,34 @@ impl ReplState {
// Record e.g. "val1" as a past def, unless our input was exactly the name of
// an existing identifer (e.g. I just typed "val1" into the prompt - there's no
// need to reassign "val1" to "val2" just because I wanted to see what its value was!)
let opt_var_name;
let (output, problems) = match self.past_def_idents.get(src.trim()) {
Some(existing_ident) => gen_and_eval_llvm(
&self.with_past_defs(src),
Triple::host(),
OptLevel::Normal,
existing_ident.to_string(),
),
Some(existing_ident) => {
opt_var_name = Some(existing_ident.to_string());
gen_and_eval_llvm(&self.with_past_defs(src), Triple::host(), OptLevel::Normal)
}
None => {
let var_name = format!("{AUTO_VAR_PREFIX}{}", self.next_auto_ident());
let answer = gen_and_eval_llvm(
&self.with_past_defs(src),
Triple::host(),
OptLevel::Normal,
var_name.clone(),
);
let (output, problems) =
gen_and_eval_llvm(&self.with_past_defs(src), Triple::host(), OptLevel::Normal);
let src = format!("{var_name} = {}", src.trim_end());
// Don't persist defs that have compile errors
if problems.errors.is_empty() {
let var_name = format!("{AUTO_VAR_PREFIX}{}", self.next_auto_ident());
let src = format!("{var_name} = {}", src.trim_end());
self.add_past_def(var_name, src);
opt_var_name = Some(var_name.clone());
answer
self.add_past_def(var_name, src);
} else {
opt_var_name = None;
}
(output, problems)
}
};
format_output(output, problems)
format_output(output, problems, opt_var_name)
}
fn next_auto_ident(&mut self) -> u64 {
@ -396,7 +399,11 @@ impl Validator for ReplState {
}
}
fn format_output(opt_output: Option<ReplOutput>, problems: Problems) -> String {
fn format_output(
opt_output: Option<ReplOutput>,
problems: Problems,
opt_var_name: Option<String>,
) -> String {
let mut buf = String::new();
// Only print errors; discard warnings.
@ -410,12 +417,7 @@ fn format_output(opt_output: Option<ReplOutput>, problems: Problems) -> String {
buf.push('\n');
}
if let Some(ReplOutput {
expr,
expr_type,
var_name,
}) = opt_output
{
if let Some(ReplOutput { expr, expr_type }) = opt_output {
// If expr was empty, it was a type annotation or ability declaration;
// don't print anything!
if !expr.is_empty() {
@ -432,7 +434,7 @@ fn format_output(opt_output: Option<ReplOutput>, problems: Problems) -> String {
}
// Print var_name right-aligned on the last line of output.
{
if let Some(var_name) = opt_var_name {
use unicode_segmentation::UnicodeSegmentation;
const VAR_NAME_PREFIX: &str = " # "; // e.g. in " # val1"

View file

@ -14,15 +14,9 @@ use roc_target::TargetInfo;
pub struct ReplOutput {
pub expr: String,
pub expr_type: String,
pub var_name: String,
}
pub fn format_answer(
arena: &Bump,
answer: Expr<'_>,
expr_type: String,
var_name: String,
) -> ReplOutput {
pub fn format_answer(arena: &Bump, answer: Expr<'_>, expr_type: String) -> ReplOutput {
let mut expr = roc_fmt::Buf::new_in(arena);
answer.format_with_options(&mut expr, Parens::NotNeeded, Newlines::Yes, 0);
@ -30,7 +24,6 @@ pub fn format_answer(
ReplOutput {
expr: expr.into_bump_str().to_string(),
expr_type,
var_name,
}
}

View file

@ -284,16 +284,11 @@ pub async fn entrypoint_from_js(src: String) -> Result<String, String> {
target_info,
);
let val_name = String::new(); // TODO
let var_name = String::new(); // TODO turn this into something like " # val1"
// Transform the Expr to a string
// `Result::Err` becomes a JS exception that will be caught and displayed
let ReplOutput { expr, expr_type } = format_answer(arena, res_answer, expr_type_str);
let ReplOutput {
expr,
expr_type,
var_name,
} = format_answer(arena, res_answer, expr_type_str, val_name);
Ok(format!("{expr} : {expr_type} # {var_name}"))
Ok(format!("{expr} : {expr_type}{var_name}"))
}