From 45629a38d11e4a3a17138ef91a7c04a7c7cb15f1 Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Fri, 13 Aug 2021 19:54:35 +0200 Subject: [PATCH] parse header progress --- .gitignore | 5 + Cargo.lock | 15 ++ editor/Cargo.toml | 4 + editor/src/editor/ed_error.rs | 6 +- editor/src/editor/main.rs | 115 ++++++++++---- editor/src/editor/mvc/ed_model.rs | 238 ++++++++++++++++------------- editor/src/editor/mvc/ed_update.rs | 44 +++--- editor/src/lang/mod.rs | 1 + editor/src/lang/parse.rs | 55 +++++++ 9 files changed, 323 insertions(+), 160 deletions(-) create mode 100644 editor/src/lang/parse.rs diff --git a/.gitignore b/.gitignore index d0ccfa7943..cffca3739b 100644 --- a/.gitignore +++ b/.gitignore @@ -25,8 +25,13 @@ editor/benches/resources/25000000_lines.roc editor/benches/resources/50000_lines.roc editor/benches/resources/500_lines.roc +# file editor creates when none is selected +UntitledApp.roc + # rust cache (sccache folder) sccache_dir # self-contained benchmark folder bench-folder* + + diff --git a/Cargo.lock b/Cargo.lock index f0b1a3fe97..d9d517ffab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "ab_glyph" version = "0.2.11" @@ -3172,9 +3174,11 @@ dependencies = [ "quickcheck 1.0.3", "quickcheck_macros 1.0.0", "rand 0.8.3", + "roc_builtins", "roc_can", "roc_collections", "roc_fmt", + "roc_load", "roc_module", "roc_parse", "roc_problem", @@ -3186,6 +3190,8 @@ dependencies = [ "ropey", "serde", "snafu", + "tempfile", + "uuid", "ven_graph", "wgpu", "wgpu_glyph", @@ -4189,6 +4195,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.3", +] + [[package]] name = "vec_map" version = "0.8.2" diff --git a/editor/Cargo.toml b/editor/Cargo.toml index 1843d94132..c9104c3896 100644 --- a/editor/Cargo.toml +++ b/editor/Cargo.toml @@ -9,6 +9,8 @@ exclude = ["src/shaders/*.spv"] [dependencies] roc_collections = { path = "../compiler/collections" } +roc_load = { path = "../compiler/load" } +roc_builtins = { path = "../compiler/builtins" } roc_can = { path = "../compiler/can" } roc_parse = { path = "../compiler/parse" } roc_region = { path = "../compiler/region" } @@ -50,6 +52,8 @@ confy = { git = 'https://github.com/rust-cli/confy', features = [ ], default-features = false } serde = { version = "1.0.123", features = ["derive"] } nonempty = "0.6.0" +tempfile = "3.2.0" +uuid = { version = "0.8", features = ["v4"] } [dependencies.bytemuck] version = "1.4" diff --git a/editor/src/editor/ed_error.rs b/editor/src/editor/ed_error.rs index 0cee446d72..6270be053e 100644 --- a/editor/src/editor/ed_error.rs +++ b/editor/src/editor/ed_error.rs @@ -165,7 +165,7 @@ pub enum EdError { }, #[snafu(display("ParseError: Failed to parse AST: SyntaxError: {}.", syntax_err))] - ParseError { syntax_err: String }, + SrcParseError { syntax_err: String }, #[snafu(display("RecordWithoutFields: expected record to have at least one field because it is not an EmptyRecord."))] RecordWithoutFields { backtrace: Backtrace }, @@ -187,13 +187,13 @@ pub fn print_err(err: &EdError) { } } -pub fn print_ui_err(err: &UIError) { +/*pub fn print_ui_err(err: &UIError) { eprintln!("{}", format!("{}", err).truecolor(255, 0, 0)); if let Some(backtrace) = ErrorCompat::backtrace(err) { eprintln!("{}", color_backtrace(backtrace)); } -} +}*/ fn color_backtrace(backtrace: &snafu::Backtrace) -> String { let backtrace_str = format!("{}", backtrace); diff --git a/editor/src/editor/main.rs b/editor/src/editor/main.rs index d2977cc506..6e0c9caf7e 100644 --- a/editor/src/editor/main.rs +++ b/editor/src/editor/main.rs @@ -1,7 +1,5 @@ use super::keyboard_input; -use super::mvc::ed_model::init_model_refs; use super::style::CODE_TXT_XY; -use crate::editor::ed_error::print_ui_err; use crate::editor::mvc::ed_view; use crate::editor::mvc::ed_view::RenderedWgpu; use crate::editor::resources::strings::NOTHING_OPENED; @@ -21,17 +19,17 @@ use crate::graphics::{ }; use crate::lang::expr::Env; use crate::lang::pool::Pool; -use crate::ui::ui_error::UIError::FileOpenFailed; use crate::ui::util::slice_get; -use bumpalo::collections::String as BumpString; use bumpalo::Bump; use cgmath::Vector2; use pipelines::RectResources; -use roc_module::symbol::Interns; -use roc_module::symbol::{IdentIds, ModuleIds}; +use roc_can::builtins::builtin_defs_map; +use roc_collections::all::MutMap; +use roc_load; +use roc_load::file::LoadedModule; +use roc_module::symbol::IdentIds; use roc_types::subs::VarStore; use std::fs::File; -use std::os::unix::fs; use std::{error::Error, io, path::Path}; use std::io::{Write}; use wgpu::{CommandEncoder, RenderPass, TextureView}; @@ -134,17 +132,38 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box> { let is_animating = true; - let mut ed_model_refs = init_model_refs(); + let mut env_pool = Pool::with_capacity(1024); + let env_arena = Bump::new(); + let code_arena = Bump::new(); - let (file_path, code_bump_str) = read_file(file_path_opt, &ed_model_refs.code_arena); + let (file_path, code_str) = read_file(file_path_opt); + + let loaded_module = load_module(&file_path); + + let mut var_store = VarStore::default(); + let dep_idents = IdentIds::exposed_builtins(8); + let exposed_ident_ids = IdentIds::default(); + let module_ids = loaded_module.interns.module_ids.clone(); + + let env = Env::new( + loaded_module.module_id, + &env_arena, + &mut env_pool, + &mut var_store, + dep_idents, + &module_ids, + exposed_ident_ids, + ); let ed_model_opt = { let ed_model_res = - ed_model::init_model_and_env( - &code_bump_str, + ed_model::init_model( + &code_str, file_path, - "HelloApp".to_owned(), - &mut ed_model_refs); + env, + loaded_module, + &code_arena, + ); match ed_model_res { Ok(mut ed_model) => { @@ -383,7 +402,7 @@ fn begin_render_pass<'a>( }) } -fn read_file<'a>(file_path_opt: Option<&'a Path>, code_arena: &'a Bump) -> (&'a Path, BumpString<'a>) { +fn read_file(file_path_opt: Option<&Path>) -> (&Path, String) { if let Some(file_path) = file_path_opt { @@ -392,10 +411,8 @@ fn read_file<'a>(file_path_opt: Option<&'a Path>, code_arena: &'a Bump) -> (&'a .expect( &format!("Failed to read from provided file path: {:?}", file_path) ); - - let code_str = BumpString::from_str_in(&file_as_str, code_arena); - (file_path, code_str) + (file_path, file_as_str) } else { let untitled_path = Path::new("UntitledApp.roc"); @@ -407,32 +424,66 @@ fn read_file<'a>(file_path_opt: Option<&'a Path>, code_arena: &'a Bump) -> (&'a &format!("I wanted to create {:?}, but it failed.", untitled_path) ); - let hello_world_roc = r#" -app "untitled-app" -packages { base: "platform" } -imports [] -provides [ main ] to base + let hello_world_roc = r#"app "untitled-app" + packages { base: "platform" } + imports [] + provides [ main ] to base main = "Hello, world!" "#; - write!(untitled_file, "{}", hello_world_roc)?; - - BumpString::from_str_in(hello_world_roc, code_arena) - } else { - let file_as_str = - std::fs::read_to_string(untitled_path) - .expect( - &format!("I detected an existing {:?}, but I failed to read from it.", untitled_path) - ); + write!(untitled_file, "{}", hello_world_roc) + .expect( + &format!( + r#"I wanted to write: + +{:?} + +to file {:?}, but it failed."# + , hello_world_roc + , untitled_file + ) + ); + + hello_world_roc.to_string() + } else { + + std::fs::read_to_string(untitled_path) + .expect( + &format!("I detected an existing {:?}, but I failed to read from it.", untitled_path) + ) - BumpString::from_str_in(&file_as_str, code_arena) }; (untitled_path, code_str) } } +pub fn load_module(src_file: &Path) -> LoadedModule { + let subs_by_module = MutMap::default(); + + let arena = Bump::new(); + let loaded = roc_load::file::load_and_typecheck( + &arena, + src_file.to_path_buf(), + arena.alloc(roc_builtins::std::standard_stdlib()), + src_file.parent().expect(&format!("src_file {:?} did not have a parent directory but I need to have one.", src_file)), + subs_by_module, + 8, + builtin_defs_map, + ); + + dbg!(&loaded); + + match loaded { + Ok(x) => x, + Err(roc_load::file::LoadingProblem::FormattedReport(report)) => { + panic!("Failed to load module from src_file {:?}. Report: {:?}", src_file,report); + } + Err(e) => panic!("Failed to load module from src_file {:?}: {:?}", src_file, e), + } +} + fn queue_no_file_text( size: &PhysicalSize, text: &str, diff --git a/editor/src/editor/mvc/ed_model.rs b/editor/src/editor/mvc/ed_model.rs index 6bde7d9e10..afdbab83ff 100644 --- a/editor/src/editor/mvc/ed_model.rs +++ b/editor/src/editor/mvc/ed_model.rs @@ -3,27 +3,23 @@ use crate::editor::grid_node_map::GridNodeMap; use crate::editor::markup::common_nodes::new_blank_mn; use crate::editor::slow_pool::{MarkNodeId, SlowPool}; use crate::editor::{ - ed_error::EdError::ParseError, + ed_error::EdError::SrcParseError, ed_error::{EdResult, MissingParent, NoNodeAtCaretPosition}, markup::nodes::{expr2_to_markup, set_parent_for_all}, }; use crate::graphics::primitives::rect::Rect; -use crate::lang::ast::Expr2; -use crate::lang::expr::{str_to_expr2, Env}; -use crate::lang::pool::{NodeId, Pool}; +use crate::lang::ast::{Expr2}; +use crate::lang::expr::{Env}; +use crate::lang::parse::AST; +use crate::lang::pool::{NodeId}; use crate::lang::pool::PoolStr; -use crate::lang::scope::Scope; use crate::ui::text::caret_w_select::CaretWSelect; use crate::ui::text::lines::SelectableLines; use crate::ui::text::text_pos::TextPos; use crate::ui::ui_error::UIResult; -use bumpalo::collections::String as BumpString; use bumpalo::Bump; use nonempty::NonEmpty; -use roc_collections::all::MutMap; -use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds}; -use roc_region::all::Region; -use roc_types::subs::VarStore; +use roc_load::file::LoadedModule; use std::path::Path; #[derive(Debug)] @@ -40,7 +36,7 @@ pub struct EdModel<'a> { pub has_focus: bool, pub caret_w_select_vec: NonEmpty<(CaretWSelect, Option)>, pub selected_expr_opt: Option, - pub interns: Interns, // this should eventually come from LoadedModule, see #1442 + pub loaded_module: LoadedModule, pub show_debug_view: bool, // EdModel is dirty if it has changed since the previous render. pub dirty: bool, @@ -53,37 +49,15 @@ pub struct SelectedExpression { pub type_str: PoolStr, } -pub fn init_model_and_env<'a>( - code_str: &'a BumpString, +pub fn init_model<'a>( + code_str: &'a str, file_path: &'a Path, - module_name: String, - ed_model_refs: &'a mut EdModelRefs, + env: Env<'a>, + loaded_module: LoadedModule, + code_arena: &'a Bump, ) -> EdResult> { - let dep_idents = IdentIds::exposed_builtins(8); - let exposed_ident_ids = IdentIds::default(); - - let mut interns = Interns { - module_ids: ModuleIds::default(), - all_ident_ids: IdentIds::exposed_builtins(8), - }; - - let mod_id = - interns - .module_ids - .get_or_insert(&module_name.into()); - - let env = Env::new( - mod_id, - &ed_model_refs.env_arena, - &mut ed_model_refs.env_pool, - &mut ed_model_refs.var_store, - dep_idents, - &interns.module_ids, - exposed_ident_ids, - ); - - let mut module = EdModule::new(&code_str, env, &mut interns.all_ident_ids, &ed_model_refs.code_arena)?; + let mut module = EdModule::new(&code_str, env, &code_arena)?; let ast_root_id = module.ast_root_id; let mut markup_node_pool = SlowPool::new(); @@ -97,12 +71,12 @@ pub fn init_model_and_env<'a>( let ast_root = &module.env.pool.get(ast_root_id); let temp_markup_root_id = expr2_to_markup( - &ed_model_refs.code_arena, + &code_arena, &mut module.env, ast_root, ast_root_id, &mut markup_node_pool, - &interns + &loaded_module.interns )?; set_parent_for_all(temp_markup_root_id, &mut markup_node_pool); @@ -123,7 +97,7 @@ pub fn init_model_and_env<'a>( has_focus: true, caret_w_select_vec: NonEmpty::new((CaretWSelect::default(), None)), selected_expr_opt: None, - interns, + loaded_module, show_debug_view: false, dirty: true, }) @@ -180,76 +154,47 @@ impl<'a> EdModel<'a> { } } -pub struct EdModelRefs { - pub code_arena: Bump, - pub env_arena: Bump, - pub env_pool: Pool, - pub var_store: VarStore, -} - -pub fn init_model_refs() -> EdModelRefs { - EdModelRefs { - code_arena: Bump::new(), - env_arena: Bump::new(), - env_pool: Pool::with_capacity(1024), - var_store: VarStore::default(), - } -} - #[derive(Debug)] pub struct EdModule<'a> { pub env: Env<'a>, - pub ast_root_id: NodeId, + pub ast: AST, } // for debugging -use crate::lang::ast::expr2_to_string; +//use crate::lang::ast::expr2_to_string; impl<'a> EdModule<'a> { - pub fn new(code_str: &'a str, mut env: Env<'a>, all_ident_ids: &mut MutMap, ast_arena: &'a Bump) -> EdResult> { + pub fn new(code_str: &'a str, mut env: Env<'a>, ast_arena: &'a Bump) -> EdResult> { if !code_str.is_empty() { - let mut scope = Scope::new(env.home, env.pool, env.var_store); + + let parse_res = AST::parse_from_string(code_str, env, ast_arena); - let region = Region::new(0, 0, 0, 0); - - let expr2_result = str_to_expr2(&ast_arena, &code_str, &mut env, &mut scope, region); - - match expr2_result { - Ok((expr2, output)) => { - - let bound_symbols = output.references.bound_symbols; - - let mut module_ident_ids = - all_ident_ids - .get_mut(&env.home) - .unwrap_or_else(|| { - panic!( - "Could not find env.home (ModuleId: {:?}) in interns.all_ident_ids.keys: {:?}", - &env.home, - all_ident_ids.keys() - ) - }); - - - all_ident_ids - .insert(env.home, env.ident_ids); - - - let ast_root_id = env.pool.add(expr2); - - // for debugging - dbg!(expr2_to_string(ast_root_id, env.pool)); - - Ok(EdModule { env, ast_root_id }) - } - Err(err) => Err(ParseError { + match parse_res { + Ok(ast) => { + Ok( + EdModule { + env, + ast, + } + ) + }, + Err(err) => Err(SrcParseError { syntax_err: format!("{:?}", err), - }), + }) } + } else { let ast_root_id = env.pool.add(Expr2::Blank); - Ok(EdModule { env, ast_root_id }) + Ok( + EdModule { + env, + ast: AST { + header: "".to_string(), + expressions: vec![ast_root_id], + } + } + ) } } } @@ -257,40 +202,119 @@ impl<'a> EdModule<'a> { #[cfg(test)] pub mod test_ed_model { use crate::editor::ed_error::EdResult; + use crate::editor::main::load_module; use crate::editor::mvc::ed_model; + use crate::lang::expr::Env; + use crate::lang::pool::Pool; use crate::ui::text::caret_w_select::test_caret_w_select::convert_dsl_to_selection; use crate::ui::text::caret_w_select::test_caret_w_select::convert_selection_to_dsl; use crate::ui::text::lines::SelectableLines; use crate::ui::ui_error::UIResult; - use bumpalo::collections::String as BumpString; + use bumpalo::Bump; use ed_model::EdModel; + use roc_load::file::LoadedModule; + use roc_module::symbol::IdentIds; + use roc_module::symbol::ModuleIds; + use roc_types::subs::VarStore; + use tempfile::tempdir; + use uuid::Uuid; + use std::fs::File; use std::path::Path; - - use super::EdModelRefs; + use std::path::PathBuf; + use std::io::Write; pub fn init_dummy_model<'a>( - code_str: &'a BumpString, + code_str: &'a str, + loaded_module: LoadedModule, + module_ids: &'a ModuleIds, ed_model_refs: &'a mut EdModelRefs, + code_arena: &'a Bump, ) -> EdResult> { let file_path = Path::new(""); - ed_model::init_model_and_env( - &code_str, + let dep_idents = IdentIds::exposed_builtins(8); + let exposed_ident_ids = IdentIds::default(); + + let env = Env::new( + loaded_module.module_id, + &ed_model_refs.env_arena, + &mut ed_model_refs.env_pool, + &mut ed_model_refs.var_store, + dep_idents, + module_ids, + exposed_ident_ids, + ); + + ed_model::init_model( + code_str, file_path, - "TestApp".to_owned(), - ed_model_refs, + env, + loaded_module, + code_arena, ) } + pub struct EdModelRefs { + env_arena: Bump, + env_pool: Pool, + var_store: VarStore, + } + + pub fn init_model_refs() -> EdModelRefs { + EdModelRefs { + env_arena: Bump::new(), + env_pool: Pool::with_capacity(1024), + var_store: VarStore::default(), + } + } + pub fn ed_model_from_dsl<'a>( - clean_code_str: &'a BumpString, + clean_code_str: &'a mut String, code_lines: &[&str], ed_model_refs: &'a mut EdModelRefs, + module_ids: &'a ModuleIds, + code_arena: &'a Bump, ) -> Result, String> { let code_lines_vec: Vec = (*code_lines).iter().map(|s| s.to_string()).collect(); let caret_w_select = convert_dsl_to_selection(&code_lines_vec)?; - let mut ed_model = init_dummy_model(clean_code_str, ed_model_refs)?; + let header_str = r#" +app "test-app" +packages { base: "platform" } +imports [] +provides [ main ] to base + +main = "Hello, world!" + +"#; + + *clean_code_str = [header_str, clean_code_str.as_str()].join(""); + + let temp_dir = tempdir().expect("Failed to create temporary directory for test."); + let temp_file_path_buf = PathBuf::from( + [Uuid::new_v4().to_string(), ".roc".to_string()].join("") + ); + let temp_file_full_path = temp_dir.path().join(temp_file_path_buf); + + let mut file = File::create(temp_file_full_path.clone()) + .expect( + &format!("Failed to create temporary file for path {:?}", temp_file_full_path) + ); + writeln!(file, "{}", clean_code_str) + .expect( + &format!("Failed to write {:?} to file: {:?}", clean_code_str, file) + ); + + let loaded_module = load_module(&temp_file_full_path); + + let mut ed_model = + init_dummy_model( + clean_code_str, + loaded_module, + module_ids, + ed_model_refs, + code_arena, + )?; ed_model.set_caret(caret_w_select.caret_pos); diff --git a/editor/src/editor/mvc/ed_update.rs b/editor/src/editor/mvc/ed_update.rs index 8680626471..f83815af71 100644 --- a/editor/src/editor/mvc/ed_update.rs +++ b/editor/src/editor/mvc/ed_update.rs @@ -305,7 +305,7 @@ impl<'a> EdModel<'a> { let content = subs.get(var).content; PoolStr::new( - &content_to_string(content, &subs, self.module.env.home, &self.interns), + &content_to_string(content, &subs, self.module.env.home, &self.loaded_module.interns), self.module.env.pool, ) } @@ -871,7 +871,7 @@ pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult pub mod test_ed_update { use crate::editor::mvc::ed_model::test_ed_model::ed_model_from_dsl; use crate::editor::mvc::ed_model::test_ed_model::ed_model_to_dsl; - use crate::editor::mvc::ed_model::init_model_refs; + use crate::editor::mvc::ed_model::test_ed_model::init_model_refs; use crate::editor::mvc::ed_update::handle_new_char; use crate::editor::mvc::ed_update::EdModel; use crate::editor::mvc::ed_update::EdResult; @@ -880,8 +880,8 @@ pub mod test_ed_update { use crate::window::keyboard_input::no_mods; use crate::window::keyboard_input::test_modifiers::ctrl_cmd_shift; use crate::window::keyboard_input::Modifiers; - use bumpalo::collections::String as BumpString; use bumpalo::Bump; + use roc_module::symbol::ModuleIds; use winit::event::VirtualKeyCode::*; fn ed_res_to_res(ed_res: EdResult) -> Result { @@ -919,12 +919,14 @@ pub mod test_ed_update { expected_post_lines: &[&str], new_char_seq: &str, ) -> Result<(), String> { - let test_arena = Bump::new(); - let code_str = BumpString::from_str_in(&pre_lines.join("\n").replace("┃", ""), &test_arena); + + let mut code_str = pre_lines.join("\n").replace("┃", ""); let mut model_refs = init_model_refs(); + let code_arena = Bump::new(); + let module_ids = ModuleIds::default(); - let mut ed_model = ed_model_from_dsl(&code_str, pre_lines, &mut model_refs)?; + let mut ed_model = ed_model_from_dsl(&mut code_str, pre_lines, &mut model_refs, &module_ids, &code_arena)?; for input_char in new_char_seq.chars() { if input_char == '🡲' { @@ -1808,12 +1810,14 @@ pub mod test_ed_update { expected_post_lines: &[&str], repeats: usize, ) -> Result<(), String> { - let test_arena = Bump::new(); - let code_str = BumpString::from_str_in(&pre_lines.join("").replace("┃", ""), &test_arena); + + let mut code_str = pre_lines.join("").replace("┃", ""); let mut model_refs = init_model_refs(); + let code_arena = Bump::new(); + let module_ids = ModuleIds::default(); - let mut ed_model = ed_model_from_dsl(&code_str, pre_lines, &mut model_refs)?; + let mut ed_model = ed_model_from_dsl(&mut code_str, pre_lines, &mut model_refs, &module_ids, &code_arena)?; for _ in 0..repeats { ed_model.ed_handle_key_down(&ctrl_cmd_shift(), Up)?; @@ -2066,12 +2070,14 @@ pub mod test_ed_update { expected_tooltips: &[&str], new_char_seq: &str, ) -> Result<(), String> { - let test_arena = Bump::new(); - let code_str = BumpString::from_str_in(&pre_lines.join("").replace("┃", ""), &test_arena); + + let mut code_str = pre_lines.join("").replace("┃", ""); let mut model_refs = init_model_refs(); + let code_arena = Bump::new(); + let module_ids = ModuleIds::default(); - let mut ed_model = ed_model_from_dsl(&code_str, pre_lines, &mut model_refs)?; + let mut ed_model = ed_model_from_dsl(&mut code_str, pre_lines, &mut model_refs, &module_ids, &code_arena)?; for input_char in new_char_seq.chars() { if input_char == '🡲' { @@ -2220,12 +2226,13 @@ pub mod test_ed_update { repeats: usize, move_caret_fun: ModelMoveCaretFun, ) -> Result<(), String> { - let test_arena = Bump::new(); - let code_str = BumpString::from_str_in(&pre_lines.join("").replace("┃", ""), &test_arena); + let mut code_str = pre_lines.join("").replace("┃", ""); let mut model_refs = init_model_refs(); + let code_arena = Bump::new(); + let module_ids = ModuleIds::default(); - let mut ed_model = ed_model_from_dsl(&code_str, pre_lines, &mut model_refs)?; + let mut ed_model = ed_model_from_dsl(&mut code_str, pre_lines, &mut model_refs, &module_ids, &code_arena)?; for _ in 0..repeats { ed_model.ed_handle_key_down(&ctrl_cmd_shift(), Up)?; @@ -2349,12 +2356,13 @@ pub mod test_ed_update { expected_post_lines: &[&str], repeats: usize, ) -> Result<(), String> { - let test_arena = Bump::new(); - let code_str = BumpString::from_str_in(&pre_lines.join("").replace("┃", ""), &test_arena); + let mut code_str = pre_lines.join("").replace("┃", ""); let mut model_refs = init_model_refs(); + let code_arena = Bump::new(); + let module_ids = ModuleIds::default(); - let mut ed_model = ed_model_from_dsl(&code_str, pre_lines, &mut model_refs)?; + let mut ed_model = ed_model_from_dsl(&mut code_str, pre_lines, &mut model_refs, &module_ids, &code_arena)?; for _ in 0..repeats { ed_model.ed_handle_key_down(&ctrl_cmd_shift(), Up)?; diff --git a/editor/src/lang/mod.rs b/editor/src/lang/mod.rs index 99e508d3cb..45f3dee65a 100644 --- a/editor/src/lang/mod.rs +++ b/editor/src/lang/mod.rs @@ -1,4 +1,5 @@ pub mod ast; +pub mod parse; pub mod constrain; mod def; pub mod expr; diff --git a/editor/src/lang/parse.rs b/editor/src/lang/parse.rs new file mode 100644 index 0000000000..ba8d1e1e28 --- /dev/null +++ b/editor/src/lang/parse.rs @@ -0,0 +1,55 @@ +use bumpalo::Bump; +use roc_parse::parser::SyntaxError; +use crate::lang::scope::Scope; +use roc_region::all::Region; + +use super::{ast::ExprId, expr::{Env, str_to_expr2}}; + + + +// +#[derive(Debug)] +pub struct AST { + pub header: String, + pub expressions: Vec, +} + +impl AST { + pub fn parse_from_string<'a>(code_str: &str, mut env: Env<'a>, ast_arena: &Bump) -> Result> { + + let mut split_string = code_str.split("\n\n"); + + let split_code_vec: Vec<&str> = split_string.collect(); + + if let Some((head, tail)) = split_code_vec.split_first() { + + let mut scope = Scope::new(env.home, env.pool, env.var_store); + + let region = Region::new(0, 0, 0, 0); + + let expressions = + tail + .iter() + .map(|&expr_str| + { + let (expr2, _output) = str_to_expr2(&ast_arena, code_str, &mut env, &mut scope, region)?; + + let expr_id = env.pool.add(expr2); + + expr_id + } + ).collect::>(); + + + Ok( + AST { + header: head.to_string(), + expressions, + } + ) + } else { + panic!("I was expecting a double newline to split header and rest of code.") + } + } +} +// \ No newline at end of file