mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 08:34:33 +00:00
multi element lists without updating ast nodes
This commit is contained in:
parent
c34c27b58d
commit
fdb0aa9eb7
7 changed files with 163 additions and 74 deletions
|
@ -166,9 +166,9 @@ where
|
|||
p.build()?
|
||||
};
|
||||
|
||||
if DEBUG {
|
||||
/*if DEBUG {
|
||||
eprintln!("{}", program.to_source_string());
|
||||
}
|
||||
}*/
|
||||
|
||||
morphic_lib::solve(program)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,67 +99,117 @@ 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
|
||||
|
||||
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);
|
||||
let list_ast_node_id = parent.get_ast_node_id();
|
||||
let list_ast_node = ed_model.module.env.pool.get(list_ast_node_id);
|
||||
|
||||
let blank_elt_id =
|
||||
children_pool_vec
|
||||
.iter_node_ids()
|
||||
.next()
|
||||
.context(UnexpectedEmptyPoolVec {
|
||||
descriptive_vec_name: "\"children of List AST node\"",
|
||||
})?;
|
||||
match list_ast_node {
|
||||
Expr2::List {
|
||||
elem_var: _,
|
||||
elems: _,
|
||||
} => {
|
||||
let blank_elt = Expr2::Blank;
|
||||
let blank_elt_id = ed_model.module.env.pool.add(blank_elt);
|
||||
|
||||
let new_list_node = Expr2::List {
|
||||
elem_var: *elem_var,
|
||||
elems: children_pool_vec,
|
||||
};
|
||||
|
||||
ed_model.module.env.pool.set(ast_node_id, new_list_node);
|
||||
|
||||
let blank_mark_node = MarkupNode::Blank {
|
||||
ast_node_id: blank_elt_id,
|
||||
syn_high_style: HighlightStyle::Blank,
|
||||
attributes: Attributes::new(),
|
||||
parent_id_opt,
|
||||
};
|
||||
|
||||
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 new_child_index = 1; // 1 because left bracket is first element
|
||||
|
||||
parent.add_child_at_index(new_child_index, blank_mark_node_id)?;
|
||||
} else {
|
||||
MissingParent {
|
||||
node_id: curr_mark_node_id,
|
||||
Ok((blank_elt_id, new_child_index, list_ast_node_id, parent_id))
|
||||
}
|
||||
.fail()?
|
||||
_ => 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()
|
||||
};
|
||||
|
||||
// update GridNodeMap and CodeLines
|
||||
ed_model.insert_between_line(
|
||||
old_caret_pos.line,
|
||||
old_caret_pos.column,
|
||||
nodes::BLANK_PLACEHOLDER,
|
||||
blank_mark_node_id,
|
||||
)?;
|
||||
let (blank_elt_id, new_child_index, list_ast_node_id, parent_id) = trip_result?;
|
||||
|
||||
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()?,
|
||||
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,
|
||||
attributes: Attributes::new(),
|
||||
parent_id_opt,
|
||||
};
|
||||
|
||||
let blank_mark_node_id = ed_model.markup_node_pool.add(blank_mark_node);
|
||||
|
||||
let mut children: Vec<MarkNodeId> = vec![];
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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 {
|
||||
nodes::COMMA.len()
|
||||
};
|
||||
|
||||
// update GridNodeMap and CodeLines
|
||||
ed_model.insert_between_line(
|
||||
old_caret_pos.line,
|
||||
old_caret_pos.column + comma_shift,
|
||||
nodes::BLANK_PLACEHOLDER,
|
||||
blank_mark_node_id,
|
||||
)?;
|
||||
|
||||
Ok(children)
|
||||
}
|
||||
|
|
|
@ -114,8 +114,8 @@ pub enum Expr2 {
|
|||
InvalidLookup(PoolStr), // 8B
|
||||
|
||||
List {
|
||||
elem_var: Variable, // 4B
|
||||
elems: PoolVec<Expr2>, // 8B
|
||||
elem_var: Variable, // 4B
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue