added parent_id to MarkupNode, created SlowPool mock because Pool can not with a mix of 64 and 32 byte nodes, renamed Hole to Blank: closes #1080

This commit is contained in:
Anton-4 2021-03-16 16:21:14 +01:00
parent 64a88dd31c
commit afe0dc16ea
10 changed files with 231 additions and 64 deletions

View File

@ -3,6 +3,7 @@ use super::style::CODE_TXT_XY;
use super::util::slice_get;
use crate::editor::ed_error::print_ui_err;
use crate::editor::resources::strings::NOTHING_OPENED;
use crate::editor::slow_pool::SlowPool;
use crate::editor::{
config::Config,
ed_error::print_err,
@ -131,6 +132,7 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
let mut env_pool = Pool::with_capacity(1024);
let env_arena = Bump::new();
let code_arena = Bump::new();
let mut markup_node_pool = SlowPool::new();
let mut var_store = VarStore::default();
let dep_idents = IdentIds::exposed_builtins(8);
@ -165,7 +167,7 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
}
let ed_model_opt = {
let ed_model_res = ed_model::init_model(&code_str, env, &code_arena);
let ed_model_res = ed_model::init_model(&code_str, env, &code_arena, &mut markup_node_pool);
match ed_model_res {
Ok(mut ed_model) => {
@ -290,6 +292,7 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box<dyn Error>> {
&size,
CODE_TXT_XY.into(),
&config,
&markup_node_pool,
);
match text_and_rects_res {

View File

@ -1,6 +1,7 @@
#![allow(dead_code)]
use super::syntax_highlight::HighlightStyle;
use crate::editor::slow_pool::{SlowNodeId, SlowPool};
use crate::lang::{
ast::Expr2,
expr::Env,
@ -13,18 +14,21 @@ pub enum MarkupNode {
// TODO add parent field, necessary for moving caret to next node
Nested {
ast_node_id: NodeId<Expr2>,
children: Vec<MarkupNode>,
children_ids: Vec<SlowNodeId>,
parent_id_opt: Option<SlowNodeId>,
},
Text {
content: String,
ast_node_id: NodeId<Expr2>,
syn_high_style: HighlightStyle,
attributes: Vec<Attribute>,
parent_id_opt: Option<SlowNodeId>,
},
Hole {
Blank {
ast_node_id: NodeId<Expr2>,
attributes: Vec<Attribute>,
syn_high_style: HighlightStyle,
parent_id_opt: Option<SlowNodeId>,
},
}
@ -45,82 +49,111 @@ fn get_string<'a>(env: &Env<'a>, pool_str: &PoolStr) -> String {
pool_str.as_str(env.pool).to_owned()
}
fn new_markup(text: String, node_id: NodeId<Expr2>, highlight_style: HighlightStyle) -> MarkupNode {
MarkupNode::Text {
fn new_markup_node(
text: String,
node_id: NodeId<Expr2>,
highlight_style: HighlightStyle,
markup_node_pool: &mut SlowPool,
) -> SlowNodeId {
let node = MarkupNode::Text {
content: text,
ast_node_id: node_id,
syn_high_style: highlight_style,
attributes: Vec::new(),
}
parent_id_opt: None,
};
markup_node_pool.add(node)
}
// make Markup Nodes: generate String representation, assign Highlighting Style
pub fn expr2_to_markup<'a, 'b>(arena: &'a Bump, env: &mut Env<'b>, expr2: &Expr2) -> MarkupNode {
pub fn expr2_to_markup<'a, 'b>(
arena: &'a Bump,
env: &mut Env<'b>,
expr2: &Expr2,
markup_node_pool: &mut SlowPool,
) -> SlowNodeId {
// TODO find way to add current expr2 to pool
let node_id = env.pool.add(Expr2::Hole);
let node_id = env.pool.add(Expr2::Blank);
match expr2 {
Expr2::SmallInt { text, .. }
| Expr2::I128 { text, .. }
| Expr2::U128 { text, .. }
| Expr2::Float { text, .. } => {
new_markup(get_string(env, &text), node_id, HighlightStyle::Number)
}
Expr2::Str(text) => new_markup(
| Expr2::Float { text, .. } => new_markup_node(
get_string(env, &text),
node_id,
HighlightStyle::Number,
markup_node_pool,
),
Expr2::Str(text) => new_markup_node(
"\"".to_owned() + text.as_str(env.pool) + "\"",
node_id,
HighlightStyle::String,
markup_node_pool,
),
Expr2::GlobalTag { name, .. } => new_markup_node(
get_string(env, &name),
node_id,
HighlightStyle::Type,
markup_node_pool,
),
Expr2::GlobalTag { name, .. } => {
new_markup(get_string(env, &name), node_id, HighlightStyle::Type)
}
Expr2::Call { expr: expr_id, .. } => {
let expr = env.pool.get(*expr_id);
expr2_to_markup(arena, env, expr)
expr2_to_markup(arena, env, expr, markup_node_pool)
}
Expr2::Var(symbol) => {
//TODO make bump_format with arena
let text = format!("{:?}", symbol);
new_markup(text, node_id, HighlightStyle::Variable)
new_markup_node(text, node_id, HighlightStyle::Variable, markup_node_pool)
}
Expr2::List { elems, .. } => {
let mut children: Vec<MarkupNode> = Vec::new();
children.push(new_markup(
let mut children_ids = Vec::new();
children_ids.push(new_markup_node(
"[ ".to_string(),
node_id,
HighlightStyle::Bracket,
markup_node_pool,
));
for (idx, node_id) in elems.iter_node_ids().enumerate() {
let sub_expr2 = env.pool.get(node_id);
children.push(expr2_to_markup(arena, env, sub_expr2));
children_ids.push(expr2_to_markup(arena, env, sub_expr2, markup_node_pool));
if idx + 1 < elems.len() {
children.push(new_markup(
children_ids.push(new_markup_node(
", ".to_string(),
node_id,
HighlightStyle::Operator,
markup_node_pool,
));
}
}
children.push(new_markup(
children_ids.push(new_markup_node(
"] ".to_string(),
node_id,
HighlightStyle::Bracket,
markup_node_pool,
));
MarkupNode::Nested {
let list_node = MarkupNode::Nested {
ast_node_id: node_id,
children,
}
children_ids,
parent_id_opt: None,
};
markup_node_pool.add(list_node)
}
Expr2::Record { fields, .. } => {
let mut children: Vec<MarkupNode> = Vec::new();
children.push(new_markup(
let mut children_ids = Vec::new();
children_ids.push(new_markup_node(
"{ ".to_string(),
node_id,
HighlightStyle::Bracket,
markup_node_pool,
));
for (idx, field_node_id) in fields.iter_node_ids().enumerate() {
@ -130,56 +163,118 @@ pub fn expr2_to_markup<'a, 'b>(arena: &'a Bump, env: &mut Env<'b>, expr2: &Expr2
let sub_expr2 = env.pool.get(*sub_expr2_node_id);
children.push(new_markup(
children_ids.push(new_markup_node(
field_name.to_string(),
node_id,
HighlightStyle::RecordField,
markup_node_pool,
));
children.push(new_markup(
children_ids.push(new_markup_node(
": ".to_string(),
node_id,
HighlightStyle::Operator,
markup_node_pool,
));
children.push(expr2_to_markup(arena, env, sub_expr2));
children_ids.push(expr2_to_markup(arena, env, sub_expr2, markup_node_pool));
if idx + 1 < fields.len() {
children.push(new_markup(
children_ids.push(new_markup_node(
", ".to_string(),
node_id,
HighlightStyle::Operator,
markup_node_pool,
));
}
}
children.push(new_markup(
children_ids.push(new_markup_node(
" }".to_string(),
node_id,
HighlightStyle::Bracket,
markup_node_pool,
));
MarkupNode::Nested {
let record_node = MarkupNode::Nested {
ast_node_id: node_id,
children,
}
children_ids,
parent_id_opt: None,
};
markup_node_pool.add(record_node)
}
Expr2::Hole => MarkupNode::Hole {
Expr2::Blank => markup_node_pool.add(MarkupNode::Blank {
ast_node_id: node_id,
attributes: Vec::new(),
syn_high_style: HighlightStyle::Hole,
},
syn_high_style: HighlightStyle::Blank,
parent_id_opt: None,
}),
rest => todo!("implement expr2_to_markup for {:?}", rest),
}
}
pub fn set_caret_at_start(markup_node: &mut MarkupNode) {
pub fn set_parent_for_all(markup_node_id: SlowNodeId, markup_node_pool: &mut SlowPool) {
let node = markup_node_pool.get(markup_node_id);
if let MarkupNode::Nested {
ast_node_id: _,
children_ids,
parent_id_opt: _,
} = node
{
if let Some(child_id) = children_ids.first() {
set_parent_for_all_helper(*child_id, markup_node_id, markup_node_pool);
}
}
}
pub fn set_parent_for_all_helper(
markup_node_id: SlowNodeId,
parent_node_id: SlowNodeId,
markup_node_pool: &mut SlowPool,
) {
let node = markup_node_pool.get_mut(markup_node_id);
match node {
MarkupNode::Nested {
ast_node_id: _,
children_ids,
parent_id_opt,
} => {
*parent_id_opt = Some(parent_node_id);
if let Some(child_id) = children_ids.first() {
set_parent_for_all_helper(*child_id, markup_node_id, markup_node_pool);
}
}
MarkupNode::Text {
content: _,
ast_node_id: _,
syn_high_style: _,
attributes: _,
parent_id_opt,
} => *parent_id_opt = Some(parent_node_id),
MarkupNode::Blank {
ast_node_id: _,
attributes: _,
syn_high_style: _,
parent_id_opt,
} => *parent_id_opt = Some(parent_node_id),
}
}
pub fn set_caret_at_start(markup_node_id: SlowNodeId, markup_node_pool: &mut SlowPool) {
let markup_node = markup_node_pool.get_mut(markup_node_id);
match markup_node {
MarkupNode::Nested {
ast_node_id: _,
children,
children_ids,
parent_id_opt: _,
} => {
if let Some(child) = children.first_mut() {
set_caret_at_start(child)
if let Some(child_id) = children_ids.first() {
set_caret_at_start(*child_id, markup_node_pool);
}
}
MarkupNode::Text {
@ -187,11 +282,13 @@ pub fn set_caret_at_start(markup_node: &mut MarkupNode) {
ast_node_id: _,
syn_high_style: _,
attributes,
parent_id_opt: _,
} => attributes.push(Attribute::Caret { offset_col: 0 }),
MarkupNode::Hole {
MarkupNode::Blank {
ast_node_id: _,
attributes,
syn_high_style: _,
parent_id_opt: _,
} => attributes.push(Attribute::Caret { offset_col: 0 }),
};
}

View File

@ -6,6 +6,7 @@ mod markup;
mod mvc;
mod render_ast;
mod resources;
mod slow_pool;
mod style;
mod syntax_highlight;
mod theme;

View File

@ -1,6 +1,9 @@
use crate::editor::ed_error::EdError::ParseError;
use crate::editor::ed_error::EdResult;
use crate::editor::markup::{expr2_to_markup, set_caret_at_start, Attribute, MarkupNode};
use crate::editor::markup::{
expr2_to_markup, set_caret_at_start, set_parent_for_all, Attribute, MarkupNode,
};
use crate::editor::slow_pool::{SlowNodeId, SlowPool};
use crate::editor::syntax_highlight::HighlightStyle;
use crate::graphics::primitives::rect::Rect;
use crate::lang::ast::Expr2;
@ -14,7 +17,7 @@ use roc_region::all::Region;
pub struct EdModel<'a> {
pub module: EdModule<'a>,
pub code_as_str: &'a str,
pub markup_root: MarkupNode,
pub markup_root_id: SlowNodeId,
pub glyph_dim_rect_opt: Option<Rect>,
pub has_focus: bool,
carets: Vec<&'a MarkupNode>,
@ -24,27 +27,38 @@ pub fn init_model<'a>(
code_str: &'a BumpString,
env: Env<'a>,
code_arena: &'a Bump,
markup_node_pool: &mut SlowPool,
) -> EdResult<EdModel<'a>> {
let mut module = EdModule::new(&code_str, env, code_arena)?;
// TODO fix moving issue and insert module.ast_root into pool
let ast_root_id = module.env.pool.add(Expr2::Hole);
let ast_root_id = module.env.pool.add(Expr2::Blank);
let markup_root = if code_str.is_empty() {
MarkupNode::Hole {
let markup_root_id = if code_str.is_empty() {
let blank_root = MarkupNode::Blank {
ast_node_id: ast_root_id,
attributes: vec![Attribute::Caret { offset_col: 0 }],
syn_high_style: HighlightStyle::Hole,
}
syn_high_style: HighlightStyle::Blank,
parent_id_opt: None,
};
markup_node_pool.add(blank_root)
} else {
let mut temp_markup_root = expr2_to_markup(code_arena, &mut module.env, &module.ast_root);
set_caret_at_start(&mut temp_markup_root);
temp_markup_root
let temp_markup_root_id = expr2_to_markup(
code_arena,
&mut module.env,
&module.ast_root,
markup_node_pool,
);
set_parent_for_all(temp_markup_root_id, markup_node_pool);
set_caret_at_start(temp_markup_root_id, markup_node_pool);
temp_markup_root_id
};
Ok(EdModel {
module,
code_as_str: code_str,
markup_root,
markup_root_id,
glyph_dim_rect_opt: None,
has_focus: true,
carets: Vec::new(),
@ -78,7 +92,7 @@ impl<'a> EdModule<'a> {
} else {
Ok(EdModule {
env,
ast_root: Expr2::Hole,
ast_root: Expr2::Blank,
})
}
}

View File

@ -2,6 +2,7 @@ use super::ed_model::EdModel;
use crate::editor::config::Config;
use crate::editor::ed_error::EdResult;
use crate::editor::render_ast::build_code_graphics;
use crate::editor::slow_pool::SlowPool;
use crate::graphics::primitives::rect::Rect;
use crate::ui::ui_error::MissingGlyphDims;
use cgmath::Vector2;
@ -14,14 +15,16 @@ pub fn model_to_wgpu<'a>(
size: &PhysicalSize<u32>,
txt_coords: Vector2<f32>,
config: &Config,
markup_node_pool: &'a SlowPool,
) -> EdResult<(wgpu_glyph::Section<'a>, Vec<Rect>)> {
let glyph_dim_rect = ed_model.glyph_dim_rect_opt.context(MissingGlyphDims {})?;
build_code_graphics(
&ed_model.markup_root,
markup_node_pool.get(ed_model.markup_root_id),
size,
txt_coords,
config,
glyph_dim_rect,
markup_node_pool,
)
}

View File

@ -1,4 +1,5 @@
use super::markup::{Attribute, MarkupNode};
use crate::editor::slow_pool::SlowPool;
use crate::editor::{ed_error::EdResult, theme::EdTheme, util::map_get};
use crate::graphics::primitives::rect::Rect;
use crate::graphics::primitives::text as gr_text;
@ -14,6 +15,7 @@ pub fn build_code_graphics<'a>(
txt_coords: Vector2<f32>,
config: &Config,
glyph_dim_rect: Rect,
markup_node_pool: &'a SlowPool,
) -> EdResult<(wgpu_glyph::Section<'a>, Vec<Rect>)> {
let area_bounds = (size.width as f32, size.height as f32);
let layout = wgpu_glyph::Layout::default().h_align(wgpu_glyph::HorizontalAlign::Left);
@ -26,6 +28,7 @@ pub fn build_code_graphics<'a>(
txt_coords,
glyph_dim_rect,
},
markup_node_pool,
)?;
let section =
@ -44,6 +47,7 @@ struct CodeStyle<'a> {
fn markup_to_wgpu<'a>(
markup_node: &'a MarkupNode,
code_style: &CodeStyle,
markup_node_pool: &'a SlowPool,
) -> EdResult<(Vec<wgpu_glyph::Text<'a>>, Vec<Rect>)> {
let mut wgpu_texts: Vec<wgpu_glyph::Text<'a>> = Vec::new();
let mut rects: Vec<Rect> = Vec::new();
@ -56,6 +60,7 @@ fn markup_to_wgpu<'a>(
&mut rects,
code_style,
&mut txt_row_col,
markup_node_pool,
)?;
Ok((wgpu_texts, rects))
@ -99,14 +104,24 @@ fn markup_to_wgpu_helper<'a>(
rects: &mut Vec<Rect>,
code_style: &CodeStyle,
txt_row_col: &mut (usize, usize),
markup_node_pool: &'a SlowPool,
) -> EdResult<()> {
match markup_node {
MarkupNode::Nested {
ast_node_id: _,
children,
children_ids,
parent_id_opt: _,
} => {
for child in children.iter() {
markup_to_wgpu_helper(child, wgpu_texts, rects, code_style, txt_row_col)?;
for child_id in children_ids.iter() {
let child = markup_node_pool.get(*child_id);
markup_to_wgpu_helper(
child,
wgpu_texts,
rects,
code_style,
txt_row_col,
markup_node_pool,
)?;
}
}
MarkupNode::Text {
@ -114,6 +129,7 @@ fn markup_to_wgpu_helper<'a>(
ast_node_id: _,
syn_high_style,
attributes,
parent_id_opt: _,
} => {
let highlight_color = map_get(&code_style.ed_theme.syntax_high_map, &syn_high_style)?;
@ -125,10 +141,11 @@ fn markup_to_wgpu_helper<'a>(
txt_row_col.1 += content.len();
wgpu_texts.push(glyph_text);
}
MarkupNode::Hole {
MarkupNode::Blank {
ast_node_id: _,
attributes,
syn_high_style,
parent_id_opt: _,
} => {
let hole_placeholder = " ";
let glyph_text = wgpu_glyph::Text::new(hole_placeholder)

View File

@ -0,0 +1,32 @@
use crate::editor::markup::MarkupNode;
pub type SlowNodeId = usize;
#[derive(Debug)]
pub struct SlowPool {
nodes: Vec<MarkupNode>,
}
impl SlowPool {
pub fn new() -> SlowPool {
SlowPool { nodes: Vec::new() }
}
pub fn add(&mut self, node: MarkupNode) -> SlowNodeId {
let id = self.nodes.len();
self.nodes.push(node);
id
}
pub fn get(&self, node_id: usize) -> &MarkupNode {
// unwrap because Pool doesn't return Result either
self.nodes.get(node_id).unwrap()
}
pub fn get_mut(&mut self, node_id: usize) -> &mut MarkupNode {
// unwrap because Pool doesn't return Result either
self.nodes.get_mut(node_id).unwrap()
}
}

View File

@ -14,7 +14,7 @@ pub enum HighlightStyle {
PackageRelated, // app, packages, imports, exposes, provides...
Variable,
RecordField,
Hole,
Blank,
}
pub fn default_highlight_map() -> HashMap<HighlightStyle, RgbaTup> {
@ -31,7 +31,7 @@ pub fn default_highlight_map() -> HashMap<HighlightStyle, RgbaTup> {
(PackageRelated, gr_colors::WHITE),
(Variable, gr_colors::WHITE),
(RecordField, from_hsb(258, 50, 90)),
(Hole, from_hsb(258, 50, 90)),
(Blank, from_hsb(258, 50, 90)),
// comment from_hsb(285, 6, 47) or 186, 35, 40
]
.iter()

View File

@ -198,7 +198,7 @@ pub enum Expr2 {
ext_var: Variable, // 4B
arguments: PoolVec<(Variable, NodeId<Expr2>)>, // 8B
},
Hole, // Rendered as empty box in editor
Blank, // Rendered as empty box in editor
// Compiles, but will crash if reached
RuntimeError(/* TODO make a version of RuntimeError that fits in 15B */),

View File

@ -150,7 +150,7 @@ impl Pool {
}
}
fn get_mut<T>(&mut self, node_id: NodeId<T>) -> &mut T {
pub fn get_mut<T>(&mut self, node_id: NodeId<T>) -> &mut T {
unsafe {
let node_ptr = self.nodes.offset(node_id.index as isize) as *mut T;