multi element lists without updating ast nodes

This commit is contained in:
Anton-4 2021-07-01 19:08:39 +02:00
parent c34c27b58d
commit fdb0aa9eb7
7 changed files with 163 additions and 74 deletions

View file

@ -166,9 +166,9 @@ where
p.build()?
};
if DEBUG {
/*if DEBUG {
eprintln!("{}", program.to_source_string());
}
}*/
morphic_lib::solve(program)
}

View file

@ -6,6 +6,7 @@ use crate::editor::ed_error::NestedNodeRequired;
use crate::editor::slow_pool::MarkNodeId;
use crate::editor::slow_pool::SlowPool;
use crate::editor::syntax_highlight::HighlightStyle;
use crate::lang::ast::ExprId;
use crate::lang::ast::RecordField;
use crate::lang::{
ast::Expr2,
@ -146,6 +147,7 @@ pub const RIGHT_ACCOLADE: &str = " }";
pub const LEFT_SQUARE_BR: &str = "[ ";
pub const RIGHT_SQUARE_BR: &str = " ]";
pub const COLON: &str = ": ";
pub const COMMA: &str = ", ";
pub const STRING_QUOTES: &str = "\"\"";
fn new_markup_node(
@ -217,21 +219,24 @@ pub fn expr2_to_markup<'a, 'b>(
markup_node_pool,
)];
for (idx, node_id) in elems.iter_node_ids().enumerate() {
let sub_expr2 = env.pool.get(node_id);
let indexed_node_ids: Vec<(usize, ExprId)> =
elems.iter(env.pool).copied().enumerate().collect();
for (idx, node_id) in indexed_node_ids.iter() {
let sub_expr2 = env.pool.get(*node_id);
children_ids.push(expr2_to_markup(
arena,
env,
sub_expr2,
node_id,
*node_id,
markup_node_pool,
));
if idx + 1 < elems.len() {
children_ids.push(new_markup_node(
", ".to_string(),
node_id,
*node_id,
HighlightStyle::Operator,
markup_node_pool,
));

View file

@ -13,7 +13,7 @@ use crate::editor::mvc::ed_model::EdModel;
use crate::editor::mvc::ed_model::SelectedExpression;
use crate::editor::mvc::int_update::start_new_int;
use crate::editor::mvc::int_update::update_int;
use crate::editor::mvc::list_update::{prep_empty_list, start_new_list};
use crate::editor::mvc::list_update::{add_blank_child, start_new_list};
use crate::editor::mvc::lookup_update::update_invalid_lookup;
use crate::editor::mvc::record_update::start_new_record;
use crate::editor::mvc::record_update::update_empty_record;
@ -689,7 +689,7 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult
if prev_mark_node.get_content()? == nodes::LEFT_SQUARE_BR {
if curr_mark_node.get_content()? == nodes::RIGHT_SQUARE_BR {
prep_empty_list(ed_model)?; // insert a Blank first, this results in cleaner code
add_blank_child(ed_model)?; // insert a Blank first, this results in cleaner code
handle_new_char(received_char, ed_model)?
} else {
InputOutcome::Ignored
@ -726,12 +726,33 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult
} else {
InputOutcome::Ignored
}
} else if *ch == ',' {
let mark_parent_id_opt = curr_mark_node.get_parent_id_opt();
if let Some(mark_parent_id) = mark_parent_id_opt {
let parent_ast_id = ed_model.markup_node_pool.get(mark_parent_id).get_ast_node_id();
let parent_expr2 = ed_model.module.env.pool.get(parent_ast_id);
match parent_expr2 {
Expr2::List { elem_var:_, elems:_} => {
add_blank_child(ed_model)?
}
Expr2::Record { record_var:_, fields:_ } => {
todo!("multiple record fields")
}
_ => {
InputOutcome::Ignored
}
}
} else {
InputOutcome::Ignored
}
} else if "\"{[".contains(*ch) {
let prev_mark_node = ed_model.markup_node_pool.get(prev_mark_node_id);
if prev_mark_node.get_content()? == nodes::LEFT_SQUARE_BR {
if curr_mark_node.get_content()? == nodes::RIGHT_SQUARE_BR {
prep_empty_list(ed_model)?; // insert a Blank first, this results in cleaner code
add_blank_child(ed_model)?; // insert a Blank first, this results in cleaner code
handle_new_char(received_char, ed_model)?
} else {
InputOutcome::Ignored

View file

@ -1,5 +1,5 @@
use crate::editor::ed_error::EdResult;
use crate::editor::ed_error::{MissingParent, UnexpectedASTNode, UnexpectedEmptyPoolVec};
use crate::editor::ed_error::{MissingParent, UnexpectedASTNode};
use crate::editor::markup::attribute::Attributes;
use crate::editor::markup::nodes;
use crate::editor::markup::nodes::MarkupNode;
@ -7,11 +7,12 @@ use crate::editor::mvc::app_update::InputOutcome;
use crate::editor::mvc::ed_model::EdModel;
use crate::editor::mvc::ed_update::get_node_context;
use crate::editor::mvc::ed_update::NodeContext;
use crate::editor::slow_pool::MarkNodeId;
use crate::editor::syntax_highlight::HighlightStyle;
use crate::lang::ast::expr2_to_string;
use crate::lang::ast::Expr2;
use crate::lang::ast::{expr2_to_string, ExprId};
use crate::lang::pool::PoolVec;
use snafu::OptionExt;
use crate::ui::text::text_pos::TextPos;
pub fn start_new_list(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
let NodeContext {
@ -89,7 +90,7 @@ pub fn start_new_list(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
}
// insert Blank at current position for easy code reuse
pub fn prep_empty_list(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
pub fn add_blank_child(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
let NodeContext {
old_caret_pos,
curr_mark_node_id,
@ -98,30 +99,68 @@ pub fn prep_empty_list(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
ast_node_id,
} = get_node_context(&ed_model)?;
let blank_elt = Expr2::Blank;
let trip_result: EdResult<(ExprId, usize, ExprId, MarkNodeId)> =
if let Some(parent_id) = parent_id_opt {
let parent = ed_model.markup_node_pool.get(parent_id);
let list_ast_node = ed_model.module.env.pool.get(ast_node_id);
let new_child_index = parent.get_children_ids().len() - 1; // TODO support adding child at place other than end
let list_ast_node_id = parent.get_ast_node_id();
let list_ast_node = ed_model.module.env.pool.get(list_ast_node_id);
match list_ast_node {
Expr2::List { elem_var, elems: _ } => {
let children: Vec<Expr2> = vec![blank_elt];
let children_pool_vec = PoolVec::new(children.into_iter(), ed_model.module.env.pool);
Expr2::List {
elem_var: _,
elems: _,
} => {
let blank_elt = Expr2::Blank;
let blank_elt_id = ed_model.module.env.pool.add(blank_elt);
let blank_elt_id =
children_pool_vec
.iter_node_ids()
.next()
.context(UnexpectedEmptyPoolVec {
descriptive_vec_name: "\"children of List AST node\"",
})?;
let new_list_node = Expr2::List {
elem_var: *elem_var,
elems: children_pool_vec,
Ok((blank_elt_id, new_child_index, list_ast_node_id, parent_id))
}
_ => UnexpectedASTNode {
required_node_type: "List".to_string(),
encountered_node_type: expr2_to_string(ast_node_id, ed_model.module.env.pool),
}
.fail(),
}
} else {
MissingParent {
node_id: curr_mark_node_id,
}
.fail()
};
ed_model.module.env.pool.set(ast_node_id, new_list_node);
let (blank_elt_id, new_child_index, list_ast_node_id, parent_id) = trip_result?;
let new_mark_children = make_mark_children(
new_child_index,
blank_elt_id,
list_ast_node_id,
old_caret_pos,
parent_id_opt,
ed_model,
)?;
let parent = ed_model.markup_node_pool.get_mut(parent_id);
for (indx, child) in new_mark_children.iter().enumerate() {
parent.add_child_at_index(new_child_index + indx, *child)?;
}
//TODO add ast children
Ok(InputOutcome::Accepted)
}
pub fn make_mark_children(
new_child_index: usize,
blank_elt_id: ExprId,
list_ast_node_id: ExprId,
old_caret_pos: TextPos,
parent_id_opt: Option<MarkNodeId>,
ed_model: &mut EdModel,
) -> EdResult<Vec<MarkNodeId>> {
let blank_mark_node = MarkupNode::Blank {
ast_node_id: blank_elt_id,
syn_high_style: HighlightStyle::Blank,
@ -131,34 +170,46 @@ pub fn prep_empty_list(ed_model: &mut EdModel) -> EdResult<InputOutcome> {
let blank_mark_node_id = ed_model.markup_node_pool.add(blank_mark_node);
// add blank mark node to nested mark node from list
if let Some(parent_id) = parent_id_opt {
let parent = ed_model.markup_node_pool.get_mut(parent_id);
let mut children: Vec<MarkNodeId> = vec![];
let new_child_index = 1; // 1 because left bracket is first element
if new_child_index > 1 {
let comma_mark_node = MarkupNode::Text {
content: nodes::COMMA.to_owned(),
ast_node_id: list_ast_node_id,
syn_high_style: HighlightStyle::Blank,
attributes: Attributes::new(),
parent_id_opt,
};
parent.add_child_at_index(new_child_index, blank_mark_node_id)?;
let comma_mark_node_id = ed_model.markup_node_pool.add(comma_mark_node);
ed_model.simple_move_carets_right(nodes::COMMA.len());
ed_model.insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
nodes::COMMA,
comma_mark_node_id,
)?;
children.push(comma_mark_node_id);
}
children.push(blank_mark_node_id);
let comma_shift = if new_child_index == 1 {
0
} else {
MissingParent {
node_id: curr_mark_node_id,
}
.fail()?
}
nodes::COMMA.len()
};
// update GridNodeMap and CodeLines
ed_model.insert_between_line(
old_caret_pos.line,
old_caret_pos.column,
old_caret_pos.column + comma_shift,
nodes::BLANK_PLACEHOLDER,
blank_mark_node_id,
)?;
Ok(InputOutcome::Accepted)
}
_ => UnexpectedASTNode {
required_node_type: "List".to_string(),
encountered_node_type: expr2_to_string(ast_node_id, ed_model.module.env.pool),
}
.fail()?,
}
Ok(children)
}

View file

@ -115,7 +115,7 @@ pub enum Expr2 {
List {
elem_var: Variable, // 4B
elems: PoolVec<Expr2>, // 8B
elems: PoolVec<ExprId>, // 8B
},
If {
cond_var: Variable, // 4B
@ -438,13 +438,15 @@ fn expr2_to_string_helper(
let mut first_elt = true;
for elem_expr2 in elems.iter(pool) {
for elem_expr2_id in elems.iter(pool) {
if !first_elt {
out_string.push_str(", ")
} else {
first_elt = false;
}
let elem_expr2 = pool.get(*elem_expr2_id);
expr2_to_string_helper(elem_expr2, indent_level + 2, pool, out_string)
}

View file

@ -1,7 +1,7 @@
use bumpalo::{collections::Vec as BumpVec, Bump};
use crate::lang::{
ast::{Expr2, RecordField, WhenBranch},
ast::{Expr2, ExprId, RecordField, WhenBranch},
expr::Env,
pattern::{DestructType, Pattern2, PatternState2, RecordDestruct},
pool::{Pool, PoolStr, PoolVec, ShallowClone},
@ -131,7 +131,10 @@ pub fn constrain_expr<'a>(
let list_elem_type = Type2::Variable(*elem_var);
for (index, elem_node_id) in elems.iter_node_ids().enumerate() {
let indexed_node_ids: Vec<(usize, ExprId)> =
elems.iter(env.pool).copied().enumerate().collect();
for (index, elem_node_id) in indexed_node_ids {
let elem_expr = env.pool.get(elem_node_id);
let elem_expected = Expected::ForReason(

View file

@ -19,6 +19,7 @@ use roc_module::low_level::LowLevel;
use roc_module::operator::CalledVia;
use roc_module::symbol::{IdentIds, ModuleId, ModuleIds, Symbol};
use roc_parse::ast;
use roc_parse::ast::Expr;
use roc_parse::ast::StrLiteral;
use roc_parse::parser::{loc, Parser, State, SyntaxError};
use roc_problem::can::{Problem, RuntimeError};
@ -337,12 +338,18 @@ pub fn to_expr2<'a>(
let elems = PoolVec::with_capacity(items.len() as u32, env.pool);
for (node_id, item) in elems.iter_node_ids().zip(items.iter()) {
let node_id_item_tups: Vec<(ExprId, &Located<Expr>)> = elems
.iter(env.pool)
.map(|node_ref| *node_ref)
.zip(items.iter().map(|item_ref| *item_ref))
.collect();
for (node_id, item) in node_id_item_tups.iter() {
let (expr, sub_output) = to_expr2(env, scope, &item.value, item.region);
output_ref.union(sub_output);
env.pool[node_id] = expr;
env.pool.set(*node_id, expr);
}
let expr = Expr2::List {