mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
Merge branch 'trunk' into add-list-dropLast
This commit is contained in:
commit
a4b5b81d60
48 changed files with 1242 additions and 693 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -3716,6 +3716,7 @@ name = "roc_code_markup"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
|
"itertools 0.10.1",
|
||||||
"palette",
|
"palette",
|
||||||
"roc_ast",
|
"roc_ast",
|
||||||
"roc_module",
|
"roc_module",
|
||||||
|
@ -3772,6 +3773,7 @@ dependencies = [
|
||||||
"roc_parse",
|
"roc_parse",
|
||||||
"roc_region",
|
"roc_region",
|
||||||
"roc_types",
|
"roc_types",
|
||||||
|
"snafu",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
@ -4012,6 +4014,7 @@ dependencies = [
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_ident",
|
"roc_ident",
|
||||||
"roc_region",
|
"roc_region",
|
||||||
|
"snafu",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
use roc_module::{ident::Ident, module_err::ModuleError};
|
||||||
|
use roc_parse::parser::SyntaxError;
|
||||||
|
use roc_region::all::{Located, Region};
|
||||||
use snafu::{Backtrace, Snafu};
|
use snafu::{Backtrace, Snafu};
|
||||||
|
|
||||||
use crate::lang::core::ast::ASTNodeId;
|
use crate::lang::core::ast::ASTNodeId;
|
||||||
|
@ -33,6 +36,38 @@ pub enum ASTError {
|
||||||
encountered_pattern2: String,
|
encountered_pattern2: String,
|
||||||
backtrace: Backtrace,
|
backtrace: Backtrace,
|
||||||
},
|
},
|
||||||
|
#[snafu(display("IdentExistsError: {}", msg))]
|
||||||
|
IdentExistsError { msg: String },
|
||||||
|
|
||||||
|
WrapModuleError {
|
||||||
|
#[snafu(backtrace)]
|
||||||
|
source: ModuleError,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[snafu(display("SyntaxError: {}", msg))]
|
||||||
|
SyntaxErrorNoBacktrace { msg: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ASTResult<T, E = ASTError> = std::result::Result<T, E>;
|
pub type ASTResult<T, E = ASTError> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
impl From<ModuleError> for ASTError {
|
||||||
|
fn from(module_err: ModuleError) -> Self {
|
||||||
|
Self::WrapModuleError { source: module_err }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(Region, Located<Ident>)> for ASTError {
|
||||||
|
fn from(ident_exists_err: (Region, Located<Ident>)) -> Self {
|
||||||
|
Self::IdentExistsError {
|
||||||
|
msg: format!("{:?}", ident_exists_err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<SyntaxError<'a>> for ASTError {
|
||||||
|
fn from(syntax_err: SyntaxError) -> Self {
|
||||||
|
Self::SyntaxErrorNoBacktrace {
|
||||||
|
msg: format!("{:?}", syntax_err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -273,7 +273,7 @@ pub fn constrain_expr<'a>(
|
||||||
Expr2::Call {
|
Expr2::Call {
|
||||||
args,
|
args,
|
||||||
expr_var,
|
expr_var,
|
||||||
expr: expr_node_id,
|
expr_id: expr_node_id,
|
||||||
closure_var,
|
closure_var,
|
||||||
fn_var,
|
fn_var,
|
||||||
..
|
..
|
||||||
|
@ -944,8 +944,8 @@ pub fn constrain_expr<'a>(
|
||||||
}
|
}
|
||||||
Expr2::Closure {
|
Expr2::Closure {
|
||||||
args,
|
args,
|
||||||
name,
|
uniq_symbol,
|
||||||
body: body_id,
|
body_id,
|
||||||
function_type: fn_var,
|
function_type: fn_var,
|
||||||
extra,
|
extra,
|
||||||
..
|
..
|
||||||
|
@ -992,7 +992,7 @@ pub fn constrain_expr<'a>(
|
||||||
let closure_constraint = constrain_closure_size(
|
let closure_constraint = constrain_closure_size(
|
||||||
arena,
|
arena,
|
||||||
env,
|
env,
|
||||||
*name,
|
*uniq_symbol,
|
||||||
region,
|
region,
|
||||||
captured_symbols,
|
captured_symbols,
|
||||||
*closure_var,
|
*closure_var,
|
||||||
|
|
|
@ -488,9 +488,9 @@ fn canonicalize_pending_def<'a>(
|
||||||
match loc_can_expr {
|
match loc_can_expr {
|
||||||
Expr2::Closure {
|
Expr2::Closure {
|
||||||
args: closure_args,
|
args: closure_args,
|
||||||
body,
|
body_id,
|
||||||
extra,
|
extra,
|
||||||
name: closure_symbol,
|
uniq_symbol: closure_symbol,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let symbol = match env.pool[loc_can_pattern] {
|
let symbol = match env.pool[loc_can_pattern] {
|
||||||
|
@ -570,7 +570,7 @@ fn canonicalize_pending_def<'a>(
|
||||||
arguments,
|
arguments,
|
||||||
rigids: env.pool.add(rigids),
|
rigids: env.pool.add(rigids),
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let def = Def::Function(function_def);
|
let def = Def::Function(function_def);
|
||||||
|
@ -656,9 +656,9 @@ fn canonicalize_pending_def<'a>(
|
||||||
match loc_can_expr {
|
match loc_can_expr {
|
||||||
Expr2::Closure {
|
Expr2::Closure {
|
||||||
args: closure_args,
|
args: closure_args,
|
||||||
body,
|
body_id,
|
||||||
extra,
|
extra,
|
||||||
name: closure_symbol,
|
uniq_symbol: closure_symbol,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let symbol = match env.pool[loc_can_pattern] {
|
let symbol = match env.pool[loc_can_pattern] {
|
||||||
|
@ -703,7 +703,7 @@ fn canonicalize_pending_def<'a>(
|
||||||
name: symbol,
|
name: symbol,
|
||||||
arguments,
|
arguments,
|
||||||
return_var: env.var_store.fresh(),
|
return_var: env.var_store.fresh(),
|
||||||
body,
|
body_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let def = Def::Function(function_def);
|
let def = Def::Function(function_def);
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
|
use roc_module::symbol::IdentId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
lang::core::{
|
lang::core::expr::{expr2::Expr2, expr2_to_string::expr2_to_string},
|
||||||
expr::{expr2::Expr2, expr2_to_string::expr2_to_string},
|
|
||||||
pattern::Pattern2,
|
|
||||||
},
|
|
||||||
mem_pool::pool::{NodeId, Pool},
|
mem_pool::pool::{NodeId, Pool},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,7 +10,7 @@ use crate::{
|
||||||
pub enum Def2 {
|
pub enum Def2 {
|
||||||
// ValueDef example: `main = "Hello, world!"`. identifier -> `main`, expr -> "Hello, world!"
|
// ValueDef example: `main = "Hello, world!"`. identifier -> `main`, expr -> "Hello, world!"
|
||||||
ValueDef {
|
ValueDef {
|
||||||
identifier_id: NodeId<Pattern2>,
|
identifier_id: IdentId,
|
||||||
expr_id: NodeId<Expr2>,
|
expr_id: NodeId<Expr2>,
|
||||||
},
|
},
|
||||||
Blank,
|
Blank,
|
||||||
|
@ -30,7 +29,7 @@ pub fn def2_to_string(node_id: DefId, pool: &Pool) -> String {
|
||||||
} => {
|
} => {
|
||||||
full_string.push_str(&format!(
|
full_string.push_str(&format!(
|
||||||
"Def2::ValueDef(identifier_id: >>{:?}), expr_id: >>{:?})",
|
"Def2::ValueDef(identifier_id: >>{:?}), expr_id: >>{:?})",
|
||||||
pool.get(*identifier_id),
|
identifier_id,
|
||||||
expr2_to_string(*expr_id, pool)
|
expr2_to_string(*expr_id, pool)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
use bumpalo::collections::Vec as BumpVec;
|
use bumpalo::collections::Vec as BumpVec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_parse::{parser::SyntaxError, pattern::PatternType};
|
use roc_module::ident::{Ident, IdentStr};
|
||||||
|
use roc_parse::parser::SyntaxError;
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
|
|
||||||
use crate::lang::{
|
use crate::lang::{core::expr::expr_to_expr2::loc_expr_to_expr2, env::Env, scope::Scope};
|
||||||
core::{expr::expr_to_expr2::loc_expr_to_expr2, pattern::to_pattern2},
|
|
||||||
env::Env,
|
|
||||||
scope::Scope,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::def2::Def2;
|
use super::def2::Def2;
|
||||||
|
|
||||||
|
@ -37,26 +34,18 @@ pub fn def_to_def2<'a>(
|
||||||
SpaceBefore(inner_def, _) => def_to_def2(arena, env, scope, inner_def, region),
|
SpaceBefore(inner_def, _) => def_to_def2(arena, env, scope, inner_def, region),
|
||||||
SpaceAfter(inner_def, _) => def_to_def2(arena, env, scope, inner_def, region),
|
SpaceAfter(inner_def, _) => def_to_def2(arena, env, scope, inner_def, region),
|
||||||
Body(&loc_pattern, &loc_expr) => {
|
Body(&loc_pattern, &loc_expr) => {
|
||||||
// TODO loc_pattern use identifier
|
|
||||||
let expr2 = loc_expr_to_expr2(arena, loc_expr, env, scope, region).0;
|
let expr2 = loc_expr_to_expr2(arena, loc_expr, env, scope, region).0;
|
||||||
let expr_id = env.pool.add(expr2);
|
let expr_id = env.pool.add(expr2);
|
||||||
|
|
||||||
use roc_parse::ast::Pattern::*;
|
use roc_parse::ast::Pattern::*;
|
||||||
|
|
||||||
match loc_pattern.value {
|
match loc_pattern.value {
|
||||||
Identifier(_) => {
|
Identifier(id_str) => {
|
||||||
let (_, pattern2) = to_pattern2(
|
let identifier_id = env.ident_ids.get_or_insert(&Ident(IdentStr::from(id_str)));
|
||||||
env,
|
|
||||||
scope,
|
|
||||||
PatternType::TopLevelDef,
|
|
||||||
&loc_pattern.value,
|
|
||||||
region,
|
|
||||||
);
|
|
||||||
let pattern_id = env.pool.add(pattern2);
|
|
||||||
|
|
||||||
// TODO support with annotation
|
// TODO support with annotation
|
||||||
Def2::ValueDef {
|
Def2::ValueDef {
|
||||||
identifier_id: pattern_id,
|
identifier_id,
|
||||||
expr_id,
|
expr_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub enum Expr2 {
|
||||||
},
|
},
|
||||||
Call {
|
Call {
|
||||||
args: PoolVec<(Variable, ExprId)>, // 8B
|
args: PoolVec<(Variable, ExprId)>, // 8B
|
||||||
expr: ExprId, // 4B
|
expr_id: ExprId, // 4B
|
||||||
expr_var: Variable, // 4B
|
expr_var: Variable, // 4B
|
||||||
fn_var: Variable, // 4B
|
fn_var: Variable, // 4B
|
||||||
closure_var: Variable, // 4B
|
closure_var: Variable, // 4B
|
||||||
|
@ -108,11 +108,11 @@ pub enum Expr2 {
|
||||||
},
|
},
|
||||||
Closure {
|
Closure {
|
||||||
args: PoolVec<(Variable, NodeId<Pattern2>)>, // 8B
|
args: PoolVec<(Variable, NodeId<Pattern2>)>, // 8B
|
||||||
name: Symbol, // 8B
|
uniq_symbol: Symbol, // 8B This is a globally uniqe symbol for the closure
|
||||||
body: ExprId, // 4B
|
body_id: ExprId, // 4B
|
||||||
function_type: Variable, // 4B
|
function_type: Variable, // 4B
|
||||||
recursive: Recursive, // 1B
|
recursive: Recursive, // 1B
|
||||||
extra: NodeId<ClosureExtra>, // 4B
|
extra: NodeId<ClosureExtra>, // 4B
|
||||||
},
|
},
|
||||||
// Product Types
|
// Product Types
|
||||||
Record {
|
Record {
|
||||||
|
|
|
@ -128,6 +128,26 @@ fn expr2_to_string_helper(
|
||||||
pool.get(*body_id)
|
pool.get(*body_id)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
Expr2::Call { .. } => {
|
||||||
|
out_string.push_str(&format!("Call({:?})", expr2,));
|
||||||
|
}
|
||||||
|
Expr2::Closure { args, .. } => {
|
||||||
|
out_string.push_str("Closure:\n");
|
||||||
|
out_string.push_str(&format!("{}args: [\n", get_spacing(indent_level + 1)));
|
||||||
|
|
||||||
|
for (_, pattern_id) in args.iter(pool) {
|
||||||
|
let arg_pattern2 = pool.get(*pattern_id);
|
||||||
|
|
||||||
|
out_string.push_str(&format!(
|
||||||
|
"{}{:?}\n",
|
||||||
|
get_spacing(indent_level + 2),
|
||||||
|
arg_pattern2
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Expr2::Var { .. } => {
|
||||||
|
out_string.push_str(&format!("{:?}", expr2,));
|
||||||
|
}
|
||||||
other => todo!("Implement for {:?}", other),
|
other => todo!("Implement for {:?}", other),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,7 @@ pub fn expr_to_expr2<'a>(
|
||||||
// env.problems.push(Problem::RuntimeError(error));
|
// env.problems.push(Problem::RuntimeError(error));
|
||||||
//
|
//
|
||||||
// (answer, Output::default())
|
// (answer, Output::default())
|
||||||
todo!()
|
todo!("{:?}", &can_update)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,10 +487,10 @@ pub fn expr_to_expr2<'a>(
|
||||||
(
|
(
|
||||||
Expr2::Closure {
|
Expr2::Closure {
|
||||||
function_type: env.var_store.fresh(),
|
function_type: env.var_store.fresh(),
|
||||||
name: symbol,
|
uniq_symbol: symbol,
|
||||||
recursive: Recursive::NotRecursive,
|
recursive: Recursive::NotRecursive,
|
||||||
args: can_args,
|
args: can_args,
|
||||||
body: env.add(body_expr, loc_body_expr.region),
|
body_id: env.add(body_expr, loc_body_expr.region),
|
||||||
extra: env.pool.add(extra),
|
extra: env.pool.add(extra),
|
||||||
},
|
},
|
||||||
output,
|
output,
|
||||||
|
@ -504,7 +504,6 @@ pub fn expr_to_expr2<'a>(
|
||||||
|
|
||||||
// Canonicalize the function expression and its arguments
|
// Canonicalize the function expression and its arguments
|
||||||
let (fn_expr, mut output) = expr_to_expr2(env, scope, &loc_fn.value, fn_region);
|
let (fn_expr, mut output) = expr_to_expr2(env, scope, &loc_fn.value, fn_region);
|
||||||
|
|
||||||
// The function's return type
|
// The function's return type
|
||||||
let args = PoolVec::with_capacity(loc_args.len() as u32, env.pool);
|
let args = PoolVec::with_capacity(loc_args.len() as u32, env.pool);
|
||||||
|
|
||||||
|
@ -533,7 +532,7 @@ pub fn expr_to_expr2<'a>(
|
||||||
let fn_expr_id = env.add(fn_expr, fn_region);
|
let fn_expr_id = env.add(fn_expr, fn_region);
|
||||||
Expr2::Call {
|
Expr2::Call {
|
||||||
args,
|
args,
|
||||||
expr: fn_expr_id,
|
expr_id: fn_expr_id,
|
||||||
expr_var: env.var_store.fresh(),
|
expr_var: env.var_store.fresh(),
|
||||||
fn_var: env.var_store.fresh(),
|
fn_var: env.var_store.fresh(),
|
||||||
closure_var: env.var_store.fresh(),
|
closure_var: env.var_store.fresh(),
|
||||||
|
@ -571,7 +570,7 @@ pub fn expr_to_expr2<'a>(
|
||||||
let fn_expr_id = env.add(fn_expr, fn_region);
|
let fn_expr_id = env.add(fn_expr, fn_region);
|
||||||
Expr2::Call {
|
Expr2::Call {
|
||||||
args,
|
args,
|
||||||
expr: fn_expr_id,
|
expr_id: fn_expr_id,
|
||||||
expr_var: env.var_store.fresh(),
|
expr_var: env.var_store.fresh(),
|
||||||
fn_var: env.var_store.fresh(),
|
fn_var: env.var_store.fresh(),
|
||||||
closure_var: env.var_store.fresh(),
|
closure_var: env.var_store.fresh(),
|
||||||
|
@ -662,7 +661,10 @@ pub fn expr_to_expr2<'a>(
|
||||||
// (RuntimeError(problem), Output::default())
|
// (RuntimeError(problem), Output::default())
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
Var { module_name, ident } => canonicalize_lookup(env, scope, module_name, ident, region),
|
Var {
|
||||||
|
module_name, // module_name will only be filled if the original Roc code stated something like `5 + SomeModule.myVar`, module_name will be blank if it was `5 + myVar`
|
||||||
|
ident,
|
||||||
|
} => canonicalize_lookup(env, scope, module_name, ident, region),
|
||||||
|
|
||||||
// Below this point, we shouln't see any of these nodes anymore because
|
// Below this point, we shouln't see any of these nodes anymore because
|
||||||
// operator desugaring should have removed them!
|
// operator desugaring should have removed them!
|
||||||
|
|
|
@ -18,13 +18,13 @@ pub enum FunctionDef {
|
||||||
arguments: PoolVec<(PatternId, Type2)>, // 8B
|
arguments: PoolVec<(PatternId, Type2)>, // 8B
|
||||||
rigids: NodeId<Rigids>, // 4B
|
rigids: NodeId<Rigids>, // 4B
|
||||||
return_type: TypeId, // 4B
|
return_type: TypeId, // 4B
|
||||||
body: ExprId, // 4B
|
body_id: ExprId, // 4B
|
||||||
},
|
},
|
||||||
NoAnnotation {
|
NoAnnotation {
|
||||||
name: Symbol, // 8B
|
name: Symbol, // 8B
|
||||||
arguments: PoolVec<(PatternId, Variable)>, // 8B
|
arguments: PoolVec<(PatternId, Variable)>, // 8B
|
||||||
return_var: Variable, // 4B
|
return_var: Variable, // 4B
|
||||||
body: ExprId, // 4B
|
body_id: ExprId, // 4B
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,25 +36,25 @@ impl ShallowClone for FunctionDef {
|
||||||
arguments,
|
arguments,
|
||||||
rigids,
|
rigids,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body_id,
|
||||||
} => Self::WithAnnotation {
|
} => Self::WithAnnotation {
|
||||||
name: *name,
|
name: *name,
|
||||||
arguments: arguments.shallow_clone(),
|
arguments: arguments.shallow_clone(),
|
||||||
rigids: *rigids,
|
rigids: *rigids,
|
||||||
return_type: *return_type,
|
return_type: *return_type,
|
||||||
body: *body,
|
body_id: *body_id,
|
||||||
},
|
},
|
||||||
|
|
||||||
Self::NoAnnotation {
|
Self::NoAnnotation {
|
||||||
name,
|
name,
|
||||||
arguments,
|
arguments,
|
||||||
return_var,
|
return_var,
|
||||||
body,
|
body_id,
|
||||||
} => Self::NoAnnotation {
|
} => Self::NoAnnotation {
|
||||||
name: *name,
|
name: *name,
|
||||||
arguments: arguments.shallow_clone(),
|
arguments: arguments.shallow_clone(),
|
||||||
return_var: *return_var,
|
return_var: *return_var,
|
||||||
body: *body,
|
body_id: *body_id,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,7 +157,7 @@ fn desugar_str_segments(env: &mut Env, segments: Vec<StrSegment>) -> Expr2 {
|
||||||
|
|
||||||
let new_call = Expr2::Call {
|
let new_call = Expr2::Call {
|
||||||
args,
|
args,
|
||||||
expr: concat_expr_id,
|
expr_id: concat_expr_id,
|
||||||
expr_var: var_store.fresh(),
|
expr_var: var_store.fresh(),
|
||||||
fn_var: var_store.fresh(),
|
fn_var: var_store.fresh(),
|
||||||
closure_var: var_store.fresh(),
|
closure_var: var_store.fresh(),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::mem_pool::pool::{NodeId, Pool};
|
||||||
use bumpalo::{collections::Vec as BumpVec, Bump};
|
use bumpalo::{collections::Vec as BumpVec, Bump};
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_module::ident::{Ident, ModuleName};
|
use roc_module::ident::{Ident, ModuleName};
|
||||||
|
@ -6,8 +7,6 @@ use roc_problem::can::{Problem, RuntimeError};
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
use roc_types::subs::VarStore;
|
use roc_types::subs::VarStore;
|
||||||
|
|
||||||
use crate::mem_pool::pool::{NodeId, Pool};
|
|
||||||
|
|
||||||
use super::core::def::def::References;
|
use super::core::def::def::References;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -35,6 +34,7 @@ pub struct Env<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Env<'a> {
|
impl<'a> Env<'a> {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
|
@ -52,7 +52,7 @@ impl<'a> Env<'a> {
|
||||||
var_store,
|
var_store,
|
||||||
dep_idents,
|
dep_idents,
|
||||||
module_ids,
|
module_ids,
|
||||||
ident_ids: exposed_ident_ids.clone(), // we start with these, but will add more later
|
ident_ids: exposed_ident_ids.clone(), // we start with these, but will add more later using Scope.introduce
|
||||||
exposed_ident_ids,
|
exposed_ident_ids,
|
||||||
closures: MutMap::default(),
|
closures: MutMap::default(),
|
||||||
qualified_lookups: MutSet::default(),
|
qualified_lookups: MutSet::default(),
|
||||||
|
|
|
@ -2,13 +2,18 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::ast_error::ASTResult;
|
||||||
use crate::mem_pool::pool::Pool;
|
use crate::mem_pool::pool::Pool;
|
||||||
use crate::mem_pool::pool_str::PoolStr;
|
use crate::mem_pool::pool_str::PoolStr;
|
||||||
use crate::mem_pool::pool_vec::PoolVec;
|
use crate::mem_pool::pool_vec::PoolVec;
|
||||||
use crate::mem_pool::shallow_clone::ShallowClone;
|
use crate::mem_pool::shallow_clone::ShallowClone;
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_module::ident::{Ident, Lowercase};
|
use roc_module::ident::{Ident, Lowercase};
|
||||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
use roc_module::symbol::{
|
||||||
|
get_module_ident_ids, get_module_ident_ids_mut, IdentIds, Interns, ModuleId, Symbol,
|
||||||
|
};
|
||||||
use roc_problem::can::RuntimeError;
|
use roc_problem::can::RuntimeError;
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
use roc_types::{
|
use roc_types::{
|
||||||
|
@ -18,6 +23,7 @@ use roc_types::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::core::types::{Alias, Type2, TypeId};
|
use super::core::types::{Alias, Type2, TypeId};
|
||||||
|
use super::env::Env;
|
||||||
|
|
||||||
fn solved_type_to_type_id(
|
fn solved_type_to_type_id(
|
||||||
pool: &mut Pool,
|
pool: &mut Pool,
|
||||||
|
@ -312,6 +318,25 @@ impl Scope {
|
||||||
pub fn contains_alias(&mut self, name: Symbol) -> bool {
|
pub fn contains_alias(&mut self, name: Symbol) -> bool {
|
||||||
self.aliases.contains_key(&name)
|
self.aliases.contains_key(&name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fill_scope(
|
||||||
|
&mut self,
|
||||||
|
env: &Env,
|
||||||
|
all_ident_ids: &mut MutMap<ModuleId, IdentIds>,
|
||||||
|
) -> ASTResult<()> {
|
||||||
|
let ident_ids = get_module_ident_ids(all_ident_ids, &env.home)?.clone();
|
||||||
|
|
||||||
|
for (_, ident_ref) in ident_ids.idents() {
|
||||||
|
self.introduce(
|
||||||
|
ident_ref.as_inline_str().as_str().into(),
|
||||||
|
&env.exposed_ident_ids,
|
||||||
|
get_module_ident_ids_mut(all_ident_ids, &env.home)?,
|
||||||
|
Region::zero(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShallowClone for Scope {
|
impl ShallowClone for Scope {
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_parse::parser::SyntaxError;
|
use roc_module::symbol::Interns;
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
|
|
||||||
use crate::lang::{
|
use crate::{
|
||||||
core::{
|
ast_error::ASTResult,
|
||||||
ast::AST,
|
lang::{
|
||||||
def::{def2::DefId, def_to_def2::str_to_def2},
|
core::{
|
||||||
expr::expr2::Expr2,
|
ast::AST,
|
||||||
|
def::{def2::DefId, def_to_def2::str_to_def2},
|
||||||
|
expr::expr2::Expr2,
|
||||||
|
},
|
||||||
|
env::Env,
|
||||||
|
scope::Scope,
|
||||||
},
|
},
|
||||||
env::Env,
|
|
||||||
scope::Scope,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::parse_header;
|
use super::parse_header;
|
||||||
|
@ -18,7 +21,8 @@ pub fn parse_from_string<'a>(
|
||||||
code_str: &'a str,
|
code_str: &'a str,
|
||||||
env: &mut Env<'a>,
|
env: &mut Env<'a>,
|
||||||
ast_arena: &'a Bump,
|
ast_arena: &'a Bump,
|
||||||
) -> Result<AST, SyntaxError<'a>> {
|
interns: &mut Interns,
|
||||||
|
) -> ASTResult<AST> {
|
||||||
let blank_line_indx = code_str
|
let blank_line_indx = code_str
|
||||||
.find("\n\n")
|
.find("\n\n")
|
||||||
.expect("I was expecting a double newline to split header and rest of code.");
|
.expect("I was expecting a double newline to split header and rest of code.");
|
||||||
|
@ -27,6 +31,8 @@ pub fn parse_from_string<'a>(
|
||||||
let tail_str = &code_str[blank_line_indx..];
|
let tail_str = &code_str[blank_line_indx..];
|
||||||
|
|
||||||
let mut scope = Scope::new(env.home, env.pool, env.var_store);
|
let mut scope = Scope::new(env.home, env.pool, env.var_store);
|
||||||
|
scope.fill_scope(env, &mut interns.all_ident_ids)?;
|
||||||
|
|
||||||
let region = Region::new(0, 0, 0, 0);
|
let region = Region::new(0, 0, 0, 0);
|
||||||
|
|
||||||
let mut def_ids = Vec::<DefId>::new();
|
let mut def_ids = Vec::<DefId>::new();
|
||||||
|
|
|
@ -14,5 +14,6 @@ serde = { version = "1.0.123", features = ["derive"] }
|
||||||
palette = "0.5"
|
palette = "0.5"
|
||||||
snafu = { version = "0.6", features = ["backtraces"] }
|
snafu = { version = "0.6", features = ["backtraces"] }
|
||||||
bumpalo = { version = "3.2", features = ["collections"] }
|
bumpalo = { version = "3.2", features = ["collections"] }
|
||||||
|
itertools = "0.10.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
|
@ -16,9 +16,13 @@ pub fn new_equals_mn(ast_node_id: ASTNodeId, parent_id_opt: Option<MarkNodeId>)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_comma_mn(expr_id: ExprId, parent_id_opt: Option<MarkNodeId>) -> MarkupNode {
|
pub fn new_comma_mn(expr_id: ExprId, parent_id_opt: Option<MarkNodeId>) -> MarkupNode {
|
||||||
|
new_comma_mn_ast(ASTNodeId::AExprId(expr_id), parent_id_opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_comma_mn_ast(ast_node_id: ASTNodeId, parent_id_opt: Option<MarkNodeId>) -> MarkupNode {
|
||||||
MarkupNode::Text {
|
MarkupNode::Text {
|
||||||
content: nodes::COMMA.to_owned(),
|
content: nodes::COMMA.to_owned(),
|
||||||
ast_node_id: ASTNodeId::AExprId(expr_id),
|
ast_node_id,
|
||||||
syn_high_style: HighlightStyle::Comma,
|
syn_high_style: HighlightStyle::Comma,
|
||||||
attributes: Attributes::default(),
|
attributes: Attributes::default(),
|
||||||
parent_id_opt,
|
parent_id_opt,
|
||||||
|
@ -29,7 +33,6 @@ pub fn new_comma_mn(expr_id: ExprId, parent_id_opt: Option<MarkNodeId>) -> Marku
|
||||||
pub fn new_blank_mn(ast_node_id: ASTNodeId, parent_id_opt: Option<MarkNodeId>) -> MarkupNode {
|
pub fn new_blank_mn(ast_node_id: ASTNodeId, parent_id_opt: Option<MarkNodeId>) -> MarkupNode {
|
||||||
MarkupNode::Blank {
|
MarkupNode::Blank {
|
||||||
ast_node_id,
|
ast_node_id,
|
||||||
syn_high_style: HighlightStyle::Blank,
|
|
||||||
attributes: Attributes::default(),
|
attributes: Attributes::default(),
|
||||||
parent_id_opt,
|
parent_id_opt,
|
||||||
newlines_at_end: 0,
|
newlines_at_end: 0,
|
||||||
|
@ -43,7 +46,6 @@ pub fn new_blank_mn_w_nls(
|
||||||
) -> MarkupNode {
|
) -> MarkupNode {
|
||||||
MarkupNode::Blank {
|
MarkupNode::Blank {
|
||||||
ast_node_id,
|
ast_node_id,
|
||||||
syn_high_style: HighlightStyle::Blank,
|
|
||||||
attributes: Attributes::default(),
|
attributes: Attributes::default(),
|
||||||
parent_id_opt,
|
parent_id_opt,
|
||||||
newlines_at_end: nr_of_newlines,
|
newlines_at_end: nr_of_newlines,
|
||||||
|
@ -51,8 +53,16 @@ pub fn new_blank_mn_w_nls(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_colon_mn(expr_id: ExprId, parent_id_opt: Option<MarkNodeId>) -> MarkupNode {
|
pub fn new_colon_mn(expr_id: ExprId, parent_id_opt: Option<MarkNodeId>) -> MarkupNode {
|
||||||
|
new_operator_mn(nodes::COLON.to_owned(), expr_id, parent_id_opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_operator_mn(
|
||||||
|
content: String,
|
||||||
|
expr_id: ExprId,
|
||||||
|
parent_id_opt: Option<MarkNodeId>,
|
||||||
|
) -> MarkupNode {
|
||||||
MarkupNode::Text {
|
MarkupNode::Text {
|
||||||
content: nodes::COLON.to_owned(),
|
content,
|
||||||
ast_node_id: ASTNodeId::AExprId(expr_id),
|
ast_node_id: ASTNodeId::AExprId(expr_id),
|
||||||
syn_high_style: HighlightStyle::Operator,
|
syn_high_style: HighlightStyle::Operator,
|
||||||
attributes: Attributes::default(),
|
attributes: Attributes::default(),
|
||||||
|
@ -104,3 +114,36 @@ pub fn new_right_square_mn(expr_id: ExprId, parent_id_opt: Option<MarkNodeId>) -
|
||||||
newlines_at_end: 0,
|
newlines_at_end: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_func_name_mn(content: String, expr_id: ExprId) -> MarkupNode {
|
||||||
|
MarkupNode::Text {
|
||||||
|
content,
|
||||||
|
ast_node_id: ASTNodeId::AExprId(expr_id),
|
||||||
|
syn_high_style: HighlightStyle::FunctionName,
|
||||||
|
attributes: Attributes::default(),
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_arg_name_mn(content: String, expr_id: ExprId) -> MarkupNode {
|
||||||
|
MarkupNode::Text {
|
||||||
|
content,
|
||||||
|
ast_node_id: ASTNodeId::AExprId(expr_id),
|
||||||
|
syn_high_style: HighlightStyle::FunctionArgName,
|
||||||
|
attributes: Attributes::default(),
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_arrow_mn(ast_node_id: ASTNodeId, newlines_at_end: usize) -> MarkupNode {
|
||||||
|
MarkupNode::Text {
|
||||||
|
content: nodes::ARROW.to_owned(),
|
||||||
|
ast_node_id,
|
||||||
|
syn_high_style: HighlightStyle::Operator,
|
||||||
|
attributes: Attributes::default(),
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
34
code_markup/src/markup/convert/from_ast.rs
Normal file
34
code_markup/src/markup/convert/from_ast.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use roc_ast::{
|
||||||
|
ast_error::ASTResult,
|
||||||
|
lang::{core::ast::AST, env::Env},
|
||||||
|
};
|
||||||
|
use roc_module::symbol::Interns;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
markup::{
|
||||||
|
convert::{from_def2::def2_to_markup, from_header::header_to_markup},
|
||||||
|
nodes::set_parent_for_all,
|
||||||
|
},
|
||||||
|
slow_pool::{MarkNodeId, SlowPool},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn ast_to_mark_nodes<'a>(
|
||||||
|
env: &mut Env<'a>,
|
||||||
|
ast: &AST,
|
||||||
|
mark_node_pool: &mut SlowPool,
|
||||||
|
interns: &Interns,
|
||||||
|
) -> ASTResult<Vec<MarkNodeId>> {
|
||||||
|
let mut all_mark_node_ids = vec![header_to_markup(&ast.header, mark_node_pool)];
|
||||||
|
|
||||||
|
for &def_id in ast.def_ids.iter() {
|
||||||
|
let def2 = env.pool.get(def_id);
|
||||||
|
|
||||||
|
let expr2_markup_id = def2_to_markup(env, def2, def_id, mark_node_pool, interns)?;
|
||||||
|
|
||||||
|
set_parent_for_all(expr2_markup_id, mark_node_pool);
|
||||||
|
|
||||||
|
all_mark_node_ids.push(expr2_markup_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(all_mark_node_ids)
|
||||||
|
}
|
52
code_markup/src/markup/convert/from_def2.rs
Normal file
52
code_markup/src/markup/convert/from_def2.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::{
|
||||||
|
markup::{common_nodes::new_blank_mn_w_nls, top_level_def::tld_mark_node},
|
||||||
|
slow_pool::{MarkNodeId, SlowPool},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::from_expr2::expr2_to_markup;
|
||||||
|
|
||||||
|
use roc_ast::{
|
||||||
|
ast_error::ASTResult,
|
||||||
|
lang::{
|
||||||
|
core::{
|
||||||
|
ast::ASTNodeId,
|
||||||
|
def::def2::{Def2, DefId},
|
||||||
|
},
|
||||||
|
env::Env,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use roc_module::symbol::Interns;
|
||||||
|
|
||||||
|
pub fn def2_to_markup<'a>(
|
||||||
|
env: &mut Env<'a>,
|
||||||
|
def2: &Def2,
|
||||||
|
def2_node_id: DefId,
|
||||||
|
mark_node_pool: &mut SlowPool,
|
||||||
|
interns: &Interns,
|
||||||
|
) -> ASTResult<MarkNodeId> {
|
||||||
|
let ast_node_id = ASTNodeId::ADefId(def2_node_id);
|
||||||
|
|
||||||
|
let mark_node_id = match def2 {
|
||||||
|
Def2::ValueDef {
|
||||||
|
identifier_id,
|
||||||
|
expr_id,
|
||||||
|
} => {
|
||||||
|
let expr_mn_id = expr2_to_markup(
|
||||||
|
env,
|
||||||
|
env.pool.get(*expr_id),
|
||||||
|
*expr_id,
|
||||||
|
mark_node_pool,
|
||||||
|
interns,
|
||||||
|
0,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let tld_mn =
|
||||||
|
tld_mark_node(*identifier_id, expr_mn_id, ast_node_id, mark_node_pool, env)?;
|
||||||
|
|
||||||
|
mark_node_pool.add(tld_mn)
|
||||||
|
}
|
||||||
|
Def2::Blank => mark_node_pool.add(new_blank_mn_w_nls(ast_node_id, None, 2)),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(mark_node_id)
|
||||||
|
}
|
390
code_markup/src/markup/convert/from_expr2.rs
Normal file
390
code_markup/src/markup/convert/from_expr2.rs
Normal file
|
@ -0,0 +1,390 @@
|
||||||
|
use crate::{
|
||||||
|
markup::{
|
||||||
|
attribute::Attributes,
|
||||||
|
common_nodes::{
|
||||||
|
new_arg_name_mn, new_arrow_mn, new_blank_mn, new_colon_mn, new_comma_mn, new_equals_mn,
|
||||||
|
new_left_accolade_mn, new_left_square_mn, new_operator_mn, new_right_accolade_mn,
|
||||||
|
new_right_square_mn,
|
||||||
|
},
|
||||||
|
nodes::{
|
||||||
|
get_string, join_mark_nodes_commas, join_mark_nodes_spaces, new_markup_node, MarkupNode,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
slow_pool::{MarkNodeId, SlowPool},
|
||||||
|
syntax_highlight::HighlightStyle,
|
||||||
|
};
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
use roc_ast::{
|
||||||
|
ast_error::ASTResult,
|
||||||
|
lang::{
|
||||||
|
core::{
|
||||||
|
ast::ASTNodeId,
|
||||||
|
expr::{
|
||||||
|
expr2::{Expr2, ExprId},
|
||||||
|
record_field::RecordField,
|
||||||
|
},
|
||||||
|
pattern::{get_identifier_string, Pattern2},
|
||||||
|
val_def::ValueDef,
|
||||||
|
},
|
||||||
|
env::Env,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use roc_module::{
|
||||||
|
module_err::ModuleResult,
|
||||||
|
symbol::{get_module_ident_ids, Interns},
|
||||||
|
};
|
||||||
|
|
||||||
|
// make Markup Nodes: generate String representation, assign Highlighting Style
|
||||||
|
pub fn expr2_to_markup<'a>(
|
||||||
|
env: &Env<'a>,
|
||||||
|
expr2: &Expr2,
|
||||||
|
expr2_node_id: ExprId,
|
||||||
|
mark_node_pool: &mut SlowPool,
|
||||||
|
interns: &Interns,
|
||||||
|
indent_level: usize,
|
||||||
|
) -> ASTResult<MarkNodeId> {
|
||||||
|
let ast_node_id = ASTNodeId::AExprId(expr2_node_id);
|
||||||
|
|
||||||
|
let mark_node_id = match expr2 {
|
||||||
|
Expr2::SmallInt { text, .. }
|
||||||
|
| Expr2::I128 { text, .. }
|
||||||
|
| Expr2::U128 { text, .. }
|
||||||
|
| Expr2::Float { text, .. } => {
|
||||||
|
let num_str = get_string(env, text);
|
||||||
|
|
||||||
|
new_markup_node(
|
||||||
|
with_indent(indent_level, &num_str),
|
||||||
|
ast_node_id,
|
||||||
|
HighlightStyle::Number,
|
||||||
|
mark_node_pool,
|
||||||
|
indent_level,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Expr2::Str(text) => {
|
||||||
|
let content = format!("\"{}\"", text.as_str(env.pool));
|
||||||
|
|
||||||
|
new_markup_node(
|
||||||
|
with_indent(indent_level, &content),
|
||||||
|
ast_node_id,
|
||||||
|
HighlightStyle::String,
|
||||||
|
mark_node_pool,
|
||||||
|
indent_level,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Expr2::GlobalTag { name, .. } => new_markup_node(
|
||||||
|
with_indent(indent_level, &get_string(env, name)),
|
||||||
|
ast_node_id,
|
||||||
|
HighlightStyle::Type,
|
||||||
|
mark_node_pool,
|
||||||
|
indent_level,
|
||||||
|
),
|
||||||
|
Expr2::Call { args, expr_id, .. } => {
|
||||||
|
let expr = env.pool.get(*expr_id);
|
||||||
|
let fun_call_mark_id =
|
||||||
|
expr2_to_markup(env, expr, *expr_id, mark_node_pool, interns, indent_level)?;
|
||||||
|
|
||||||
|
let arg_expr_ids: Vec<ExprId> =
|
||||||
|
args.iter(env.pool).map(|(_, arg_id)| *arg_id).collect();
|
||||||
|
|
||||||
|
let arg_call_mark_ids: Vec<MarkNodeId> = arg_expr_ids
|
||||||
|
.iter()
|
||||||
|
.map(|arg_id| {
|
||||||
|
let arg_expr = env.pool.get(*arg_id);
|
||||||
|
|
||||||
|
expr2_to_markup(env, arg_expr, *arg_id, mark_node_pool, interns, 0)
|
||||||
|
})
|
||||||
|
.collect::<ASTResult<Vec<MarkNodeId>>>()?;
|
||||||
|
|
||||||
|
let mut args_with_sapces =
|
||||||
|
join_mark_nodes_spaces(arg_call_mark_ids, true, ast_node_id, mark_node_pool);
|
||||||
|
|
||||||
|
let mut children_ids = vec![fun_call_mark_id];
|
||||||
|
children_ids.append(&mut args_with_sapces);
|
||||||
|
|
||||||
|
let call_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids,
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(call_node)
|
||||||
|
}
|
||||||
|
Expr2::Var(symbol) => {
|
||||||
|
let text = get_module_ident_ids(&interns.all_ident_ids, &env.home)?
|
||||||
|
.get_name_str_res(symbol.ident_id())?;
|
||||||
|
|
||||||
|
new_markup_node(
|
||||||
|
text.to_string(),
|
||||||
|
ast_node_id,
|
||||||
|
HighlightStyle::Value,
|
||||||
|
mark_node_pool,
|
||||||
|
indent_level,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Expr2::List { elems, .. } => {
|
||||||
|
let mut children_ids =
|
||||||
|
vec![mark_node_pool.add(new_left_square_mn(expr2_node_id, None))];
|
||||||
|
|
||||||
|
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(
|
||||||
|
env,
|
||||||
|
sub_expr2,
|
||||||
|
*node_id,
|
||||||
|
mark_node_pool,
|
||||||
|
interns,
|
||||||
|
indent_level,
|
||||||
|
)?);
|
||||||
|
|
||||||
|
if idx + 1 < elems.len() {
|
||||||
|
children_ids.push(mark_node_pool.add(new_comma_mn(expr2_node_id, None)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
children_ids.push(mark_node_pool.add(new_right_square_mn(expr2_node_id, None)));
|
||||||
|
|
||||||
|
let list_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids,
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(list_node)
|
||||||
|
}
|
||||||
|
Expr2::EmptyRecord => {
|
||||||
|
let children_ids = vec![
|
||||||
|
mark_node_pool.add(new_left_accolade_mn(expr2_node_id, None)),
|
||||||
|
mark_node_pool.add(new_right_accolade_mn(expr2_node_id, None)),
|
||||||
|
];
|
||||||
|
|
||||||
|
let record_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids,
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(record_node)
|
||||||
|
}
|
||||||
|
Expr2::Record { fields, .. } => {
|
||||||
|
let mut children_ids =
|
||||||
|
vec![mark_node_pool.add(new_left_accolade_mn(expr2_node_id, None))];
|
||||||
|
|
||||||
|
for (idx, field_node_id) in fields.iter_node_ids().enumerate() {
|
||||||
|
let record_field = env.pool.get(field_node_id);
|
||||||
|
|
||||||
|
let field_name = record_field.get_record_field_pool_str();
|
||||||
|
|
||||||
|
children_ids.push(new_markup_node(
|
||||||
|
field_name.as_str(env.pool).to_owned(),
|
||||||
|
ast_node_id,
|
||||||
|
HighlightStyle::RecordField,
|
||||||
|
mark_node_pool,
|
||||||
|
indent_level,
|
||||||
|
));
|
||||||
|
|
||||||
|
match record_field {
|
||||||
|
RecordField::InvalidLabelOnly(_, _) => (),
|
||||||
|
RecordField::LabelOnly(_, _, _) => (),
|
||||||
|
RecordField::LabeledValue(_, _, sub_expr2_node_id) => {
|
||||||
|
children_ids.push(mark_node_pool.add(new_colon_mn(expr2_node_id, None)));
|
||||||
|
|
||||||
|
let sub_expr2 = env.pool.get(*sub_expr2_node_id);
|
||||||
|
children_ids.push(expr2_to_markup(
|
||||||
|
env,
|
||||||
|
sub_expr2,
|
||||||
|
*sub_expr2_node_id,
|
||||||
|
mark_node_pool,
|
||||||
|
interns,
|
||||||
|
indent_level,
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if idx + 1 < fields.len() {
|
||||||
|
children_ids.push(mark_node_pool.add(new_comma_mn(expr2_node_id, None)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
children_ids.push(mark_node_pool.add(new_right_accolade_mn(expr2_node_id, None)));
|
||||||
|
|
||||||
|
let record_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids,
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(record_node)
|
||||||
|
}
|
||||||
|
Expr2::Blank => mark_node_pool.add(new_blank_mn(ast_node_id, None)),
|
||||||
|
Expr2::LetValue {
|
||||||
|
def_id,
|
||||||
|
body_id: _,
|
||||||
|
body_var: _,
|
||||||
|
} => {
|
||||||
|
let pattern_id = env.pool.get(*def_id).get_pattern_id();
|
||||||
|
|
||||||
|
let pattern2 = env.pool.get(pattern_id);
|
||||||
|
|
||||||
|
let val_name = get_identifier_string(pattern2, interns)?;
|
||||||
|
|
||||||
|
let val_name_mn = MarkupNode::Text {
|
||||||
|
content: val_name,
|
||||||
|
ast_node_id,
|
||||||
|
syn_high_style: HighlightStyle::Value,
|
||||||
|
attributes: Attributes::default(),
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let val_name_mn_id = mark_node_pool.add(val_name_mn);
|
||||||
|
|
||||||
|
let equals_mn_id = mark_node_pool.add(new_equals_mn(ast_node_id, None));
|
||||||
|
|
||||||
|
let value_def = env.pool.get(*def_id);
|
||||||
|
|
||||||
|
match value_def {
|
||||||
|
ValueDef::NoAnnotation {
|
||||||
|
pattern_id: _,
|
||||||
|
expr_id,
|
||||||
|
expr_var: _,
|
||||||
|
} => {
|
||||||
|
let body_mn_id = expr2_to_markup(
|
||||||
|
env,
|
||||||
|
env.pool.get(*expr_id),
|
||||||
|
*expr_id,
|
||||||
|
mark_node_pool,
|
||||||
|
interns,
|
||||||
|
indent_level,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let body_mn = mark_node_pool.get_mut(body_mn_id);
|
||||||
|
body_mn.add_newline_at_end();
|
||||||
|
|
||||||
|
let full_let_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids: vec![val_name_mn_id, equals_mn_id, body_mn_id],
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(full_let_node)
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
unimplemented!(
|
||||||
|
"I don't know how to convert {:?} into a MarkupNode yet.",
|
||||||
|
other
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expr2::Closure {
|
||||||
|
function_type: _,
|
||||||
|
uniq_symbol: _,
|
||||||
|
recursive: _,
|
||||||
|
args,
|
||||||
|
body_id,
|
||||||
|
extra: _,
|
||||||
|
} => {
|
||||||
|
let backslash_mn = new_operator_mn("\\".to_string(), expr2_node_id, None);
|
||||||
|
let backslash_mn_id = mark_node_pool.add(backslash_mn);
|
||||||
|
|
||||||
|
let arg_names: Vec<&str> = args
|
||||||
|
.iter(env.pool)
|
||||||
|
.map(|(_, arg_node_id)| {
|
||||||
|
let arg_pattern2 = env.pool.get(*arg_node_id);
|
||||||
|
|
||||||
|
match arg_pattern2 {
|
||||||
|
Pattern2::Identifier(id_symbol) => {
|
||||||
|
let ident_id = id_symbol.ident_id();
|
||||||
|
|
||||||
|
env.ident_ids.get_name_str_res(ident_id)
|
||||||
|
}
|
||||||
|
Pattern2::Shadowed { shadowed_ident } => {
|
||||||
|
Ok(shadowed_ident.as_str(env.pool))
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
todo!(
|
||||||
|
"TODO: support the following pattern2 as function arg: {:?}",
|
||||||
|
other
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<ModuleResult<Vec<&str>>>()?;
|
||||||
|
|
||||||
|
let arg_mark_nodes = arg_names
|
||||||
|
.iter()
|
||||||
|
.map(|arg_name| new_arg_name_mn(arg_name.to_string(), expr2_node_id))
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
let args_with_commas: Vec<MarkupNode> =
|
||||||
|
join_mark_nodes_commas(arg_mark_nodes, ASTNodeId::AExprId(expr2_node_id));
|
||||||
|
|
||||||
|
let mut args_with_commas_ids: Vec<MarkNodeId> = args_with_commas
|
||||||
|
.into_iter()
|
||||||
|
.map(|mark_node| mark_node_pool.add(mark_node))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let arrow_mn = new_arrow_mn(ASTNodeId::AExprId(expr2_node_id), 1);
|
||||||
|
let arrow_mn_id = mark_node_pool.add(arrow_mn);
|
||||||
|
|
||||||
|
let mut children_ids = vec![backslash_mn_id];
|
||||||
|
children_ids.append(&mut args_with_commas_ids);
|
||||||
|
children_ids.push(arrow_mn_id);
|
||||||
|
|
||||||
|
let args_mn = MarkupNode::Nested {
|
||||||
|
ast_node_id: ASTNodeId::AExprId(expr2_node_id),
|
||||||
|
children_ids,
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
let args_mn_id = mark_node_pool.add(args_mn);
|
||||||
|
|
||||||
|
let body_expr = env.pool.get(*body_id);
|
||||||
|
let body_mn_id = expr2_to_markup(
|
||||||
|
env,
|
||||||
|
body_expr,
|
||||||
|
*body_id,
|
||||||
|
mark_node_pool,
|
||||||
|
interns,
|
||||||
|
indent_level + 1,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let function_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids: vec![args_mn_id, body_mn_id],
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(function_node)
|
||||||
|
}
|
||||||
|
Expr2::RuntimeError() => new_markup_node(
|
||||||
|
"RunTimeError".to_string(),
|
||||||
|
ast_node_id,
|
||||||
|
HighlightStyle::Blank,
|
||||||
|
mark_node_pool,
|
||||||
|
indent_level,
|
||||||
|
),
|
||||||
|
rest => todo!("implement expr2_to_markup for {:?}", rest),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(mark_node_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_indent(indent_level: usize, some_str: &str) -> String {
|
||||||
|
let full_indent = std::iter::repeat(" ").take(indent_level * 4);
|
||||||
|
let mut full_string: String = full_indent.collect();
|
||||||
|
|
||||||
|
full_string.push_str(some_str);
|
||||||
|
|
||||||
|
full_string
|
||||||
|
}
|
205
code_markup/src/markup/convert/from_header.rs
Normal file
205
code_markup/src/markup/convert/from_header.rs
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
use roc_ast::lang::core::{ast::ASTNodeId, expr::expr2::ExprId, header::AppHeader};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
markup::{
|
||||||
|
attribute::Attributes,
|
||||||
|
common_nodes::{
|
||||||
|
new_comma_mn, new_left_accolade_mn, new_left_square_mn, new_right_accolade_mn,
|
||||||
|
new_right_square_mn,
|
||||||
|
},
|
||||||
|
nodes::{set_parent_for_all, MarkupNode},
|
||||||
|
},
|
||||||
|
slow_pool::{MarkNodeId, SlowPool},
|
||||||
|
syntax_highlight::HighlightStyle,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn header_to_markup(app_header: &AppHeader, mark_node_pool: &mut SlowPool) -> MarkNodeId {
|
||||||
|
let expr_id = app_header.ast_node_id;
|
||||||
|
let ast_node_id = ASTNodeId::AExprId(expr_id);
|
||||||
|
|
||||||
|
let app_node_id = header_mn("app ".to_owned(), expr_id, mark_node_pool);
|
||||||
|
|
||||||
|
let app_name_node_id = header_val_mn(
|
||||||
|
app_header.app_name.clone(),
|
||||||
|
expr_id,
|
||||||
|
HighlightStyle::String,
|
||||||
|
mark_node_pool,
|
||||||
|
);
|
||||||
|
|
||||||
|
let full_app_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids: vec![app_node_id, app_name_node_id],
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let packages_node_id = header_mn(" packages ".to_owned(), expr_id, mark_node_pool);
|
||||||
|
|
||||||
|
let pack_left_acc_node_id = mark_node_pool.add(new_left_accolade_mn(expr_id, None));
|
||||||
|
|
||||||
|
let pack_base_node_id = header_val_mn(
|
||||||
|
"base: ".to_owned(),
|
||||||
|
expr_id,
|
||||||
|
HighlightStyle::RecordField,
|
||||||
|
mark_node_pool,
|
||||||
|
);
|
||||||
|
|
||||||
|
let pack_val_node_id = header_val_mn(
|
||||||
|
app_header.packages_base.clone(),
|
||||||
|
expr_id,
|
||||||
|
HighlightStyle::String,
|
||||||
|
mark_node_pool,
|
||||||
|
);
|
||||||
|
|
||||||
|
let pack_right_acc_node_id = mark_node_pool.add(new_right_accolade_mn(expr_id, None));
|
||||||
|
|
||||||
|
let full_packages_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids: vec![
|
||||||
|
packages_node_id,
|
||||||
|
pack_left_acc_node_id,
|
||||||
|
pack_base_node_id,
|
||||||
|
pack_val_node_id,
|
||||||
|
pack_right_acc_node_id,
|
||||||
|
],
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let imports_node_id = header_mn(" imports ".to_owned(), expr_id, mark_node_pool);
|
||||||
|
|
||||||
|
let imports_left_square_node_id = mark_node_pool.add(new_left_square_mn(expr_id, None));
|
||||||
|
|
||||||
|
let mut import_child_ids: Vec<MarkNodeId> = add_header_mn_list(
|
||||||
|
&app_header.imports,
|
||||||
|
expr_id,
|
||||||
|
HighlightStyle::Import,
|
||||||
|
mark_node_pool,
|
||||||
|
);
|
||||||
|
|
||||||
|
let imports_right_square_node_id = mark_node_pool.add(new_right_square_mn(expr_id, None));
|
||||||
|
|
||||||
|
let mut full_import_children = vec![imports_node_id, imports_left_square_node_id];
|
||||||
|
|
||||||
|
full_import_children.append(&mut import_child_ids);
|
||||||
|
full_import_children.push(imports_right_square_node_id);
|
||||||
|
|
||||||
|
let full_import_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids: full_import_children,
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let provides_node_id = header_mn(" provides ".to_owned(), expr_id, mark_node_pool);
|
||||||
|
|
||||||
|
let provides_left_square_node_id = mark_node_pool.add(new_left_square_mn(expr_id, None));
|
||||||
|
|
||||||
|
let mut provides_val_node_ids: Vec<MarkNodeId> = add_header_mn_list(
|
||||||
|
&app_header.provides,
|
||||||
|
expr_id,
|
||||||
|
HighlightStyle::Provides,
|
||||||
|
mark_node_pool,
|
||||||
|
);
|
||||||
|
|
||||||
|
let provides_right_square_node_id = mark_node_pool.add(new_right_square_mn(expr_id, None));
|
||||||
|
|
||||||
|
let provides_end_node_id = header_mn(" to base".to_owned(), expr_id, mark_node_pool);
|
||||||
|
|
||||||
|
let mut full_provides_children = vec![provides_node_id, provides_left_square_node_id];
|
||||||
|
|
||||||
|
full_provides_children.append(&mut provides_val_node_ids);
|
||||||
|
full_provides_children.push(provides_right_square_node_id);
|
||||||
|
full_provides_children.push(provides_end_node_id);
|
||||||
|
|
||||||
|
let full_provides_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids: full_provides_children,
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let full_app_node_id = mark_node_pool.add(full_app_node);
|
||||||
|
let full_packages_node = mark_node_pool.add(full_packages_node);
|
||||||
|
let full_import_node_id = mark_node_pool.add(full_import_node);
|
||||||
|
let full_provides_node_id = mark_node_pool.add(full_provides_node);
|
||||||
|
|
||||||
|
let header_mark_node = MarkupNode::Nested {
|
||||||
|
ast_node_id,
|
||||||
|
children_ids: vec![
|
||||||
|
full_app_node_id,
|
||||||
|
full_packages_node,
|
||||||
|
full_import_node_id,
|
||||||
|
full_provides_node_id,
|
||||||
|
],
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let header_mn_id = mark_node_pool.add(header_mark_node);
|
||||||
|
|
||||||
|
set_parent_for_all(header_mn_id, mark_node_pool);
|
||||||
|
|
||||||
|
header_mn_id
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for provides and imports
|
||||||
|
fn add_header_mn_list(
|
||||||
|
str_vec: &[String],
|
||||||
|
expr_id: ExprId,
|
||||||
|
highlight_style: HighlightStyle,
|
||||||
|
mark_node_pool: &mut SlowPool,
|
||||||
|
) -> Vec<MarkNodeId> {
|
||||||
|
let nr_of_elts = str_vec.len();
|
||||||
|
|
||||||
|
str_vec
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(indx, provide_str)| {
|
||||||
|
let provide_str = header_val_mn(
|
||||||
|
provide_str.to_owned(),
|
||||||
|
expr_id,
|
||||||
|
highlight_style,
|
||||||
|
mark_node_pool,
|
||||||
|
);
|
||||||
|
|
||||||
|
if indx != nr_of_elts - 1 {
|
||||||
|
vec![provide_str, mark_node_pool.add(new_comma_mn(expr_id, None))]
|
||||||
|
} else {
|
||||||
|
vec![provide_str]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header_mn(content: String, expr_id: ExprId, mark_node_pool: &mut SlowPool) -> MarkNodeId {
|
||||||
|
let mark_node = MarkupNode::Text {
|
||||||
|
content,
|
||||||
|
ast_node_id: ASTNodeId::AExprId(expr_id),
|
||||||
|
syn_high_style: HighlightStyle::PackageRelated,
|
||||||
|
attributes: Attributes::default(),
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(mark_node)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header_val_mn(
|
||||||
|
content: String,
|
||||||
|
expr_id: ExprId,
|
||||||
|
highlight_style: HighlightStyle,
|
||||||
|
mark_node_pool: &mut SlowPool,
|
||||||
|
) -> MarkNodeId {
|
||||||
|
let mark_node = MarkupNode::Text {
|
||||||
|
content,
|
||||||
|
ast_node_id: ASTNodeId::AExprId(expr_id),
|
||||||
|
syn_high_style: highlight_style,
|
||||||
|
attributes: Attributes::default(),
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(mark_node)
|
||||||
|
}
|
4
code_markup/src/markup/convert/mod.rs
Normal file
4
code_markup/src/markup/convert/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
pub mod from_ast;
|
||||||
|
pub mod from_def2;
|
||||||
|
pub mod from_expr2;
|
||||||
|
pub mod from_header;
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod attribute;
|
pub mod attribute;
|
||||||
pub mod common_nodes;
|
pub mod common_nodes;
|
||||||
|
pub mod convert;
|
||||||
pub mod nodes;
|
pub mod nodes;
|
||||||
pub mod top_level_def;
|
pub mod top_level_def;
|
||||||
|
|
|
@ -1,37 +1,17 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
markup::common_nodes::{
|
|
||||||
new_blank_mn, new_colon_mn, new_comma_mn, new_equals_mn, new_left_accolade_mn,
|
|
||||||
new_left_square_mn, new_right_accolade_mn, new_right_square_mn,
|
|
||||||
},
|
|
||||||
markup_error::MarkResult,
|
markup_error::MarkResult,
|
||||||
slow_pool::{MarkNodeId, SlowPool},
|
slow_pool::{MarkNodeId, SlowPool},
|
||||||
syntax_highlight::HighlightStyle,
|
syntax_highlight::HighlightStyle,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{attribute::Attributes, common_nodes::new_comma_mn_ast};
|
||||||
attribute::Attributes, common_nodes::new_blank_mn_w_nls, top_level_def::tld_mark_node,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::markup_error::{ExpectedTextNode, NestedNodeMissingChild, NestedNodeRequired};
|
use crate::markup_error::{ExpectedTextNode, NestedNodeMissingChild, NestedNodeRequired};
|
||||||
|
use itertools::Itertools;
|
||||||
use roc_ast::{
|
use roc_ast::{
|
||||||
ast_error::ASTResult,
|
lang::{core::ast::ASTNodeId, env::Env},
|
||||||
lang::{
|
|
||||||
core::{
|
|
||||||
ast::{ASTNodeId, AST},
|
|
||||||
def::def2::{Def2, DefId},
|
|
||||||
expr::{
|
|
||||||
expr2::{Expr2, ExprId},
|
|
||||||
record_field::RecordField,
|
|
||||||
},
|
|
||||||
header::AppHeader,
|
|
||||||
pattern::get_identifier_string,
|
|
||||||
val_def::ValueDef,
|
|
||||||
},
|
|
||||||
env::Env,
|
|
||||||
},
|
|
||||||
mem_pool::pool_str::PoolStr,
|
mem_pool::pool_str::PoolStr,
|
||||||
};
|
};
|
||||||
use roc_module::symbol::Interns;
|
|
||||||
use roc_utils::{index_of, slice_get};
|
use roc_utils::{index_of, slice_get};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -54,10 +34,14 @@ pub enum MarkupNode {
|
||||||
Blank {
|
Blank {
|
||||||
ast_node_id: ASTNodeId,
|
ast_node_id: ASTNodeId,
|
||||||
attributes: Attributes,
|
attributes: Attributes,
|
||||||
syn_high_style: HighlightStyle, // TODO remove HighlightStyle, this is always HighlightStyle::Blank
|
|
||||||
parent_id_opt: Option<MarkNodeId>,
|
parent_id_opt: Option<MarkNodeId>,
|
||||||
newlines_at_end: usize,
|
newlines_at_end: usize,
|
||||||
},
|
},
|
||||||
|
Indent {
|
||||||
|
ast_node_id: ASTNodeId,
|
||||||
|
indent_level: usize,
|
||||||
|
parent_id_opt: Option<MarkNodeId>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MarkupNode {
|
impl MarkupNode {
|
||||||
|
@ -66,6 +50,7 @@ impl MarkupNode {
|
||||||
MarkupNode::Nested { ast_node_id, .. } => *ast_node_id,
|
MarkupNode::Nested { ast_node_id, .. } => *ast_node_id,
|
||||||
MarkupNode::Text { ast_node_id, .. } => *ast_node_id,
|
MarkupNode::Text { ast_node_id, .. } => *ast_node_id,
|
||||||
MarkupNode::Blank { ast_node_id, .. } => *ast_node_id,
|
MarkupNode::Blank { ast_node_id, .. } => *ast_node_id,
|
||||||
|
MarkupNode::Indent { ast_node_id, .. } => *ast_node_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +59,7 @@ impl MarkupNode {
|
||||||
MarkupNode::Nested { parent_id_opt, .. } => *parent_id_opt,
|
MarkupNode::Nested { parent_id_opt, .. } => *parent_id_opt,
|
||||||
MarkupNode::Text { parent_id_opt, .. } => *parent_id_opt,
|
MarkupNode::Text { parent_id_opt, .. } => *parent_id_opt,
|
||||||
MarkupNode::Blank { parent_id_opt, .. } => *parent_id_opt,
|
MarkupNode::Blank { parent_id_opt, .. } => *parent_id_opt,
|
||||||
|
MarkupNode::Indent { parent_id_opt, .. } => *parent_id_opt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +68,7 @@ impl MarkupNode {
|
||||||
MarkupNode::Nested { children_ids, .. } => children_ids.to_vec(),
|
MarkupNode::Nested { children_ids, .. } => children_ids.to_vec(),
|
||||||
MarkupNode::Text { .. } => vec![],
|
MarkupNode::Text { .. } => vec![],
|
||||||
MarkupNode::Blank { .. } => vec![],
|
MarkupNode::Blank { .. } => vec![],
|
||||||
|
MarkupNode::Indent { .. } => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,6 +163,7 @@ impl MarkupNode {
|
||||||
MarkupNode::Nested { .. } => "".to_owned(),
|
MarkupNode::Nested { .. } => "".to_owned(),
|
||||||
MarkupNode::Text { content, .. } => content.clone(),
|
MarkupNode::Text { content, .. } => content.clone(),
|
||||||
MarkupNode::Blank { .. } => BLANK_PLACEHOLDER.to_owned(),
|
MarkupNode::Blank { .. } => BLANK_PLACEHOLDER.to_owned(),
|
||||||
|
MarkupNode::Indent { indent_level, .. } => SINGLE_INDENT.repeat(*indent_level),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,13 +180,8 @@ impl MarkupNode {
|
||||||
|
|
||||||
pub fn get_content_mut(&mut self) -> MarkResult<&mut String> {
|
pub fn get_content_mut(&mut self) -> MarkResult<&mut String> {
|
||||||
match self {
|
match self {
|
||||||
MarkupNode::Nested { .. } => ExpectedTextNode {
|
|
||||||
function_name: "set_content".to_owned(),
|
|
||||||
node_type: self.node_type_as_string(),
|
|
||||||
}
|
|
||||||
.fail(),
|
|
||||||
MarkupNode::Text { content, .. } => Ok(content),
|
MarkupNode::Text { content, .. } => Ok(content),
|
||||||
MarkupNode::Blank { .. } => ExpectedTextNode {
|
_ => ExpectedTextNode {
|
||||||
function_name: "set_content".to_owned(),
|
function_name: "set_content".to_owned(),
|
||||||
node_type: self.node_type_as_string(),
|
node_type: self.node_type_as_string(),
|
||||||
}
|
}
|
||||||
|
@ -230,6 +213,7 @@ impl MarkupNode {
|
||||||
MarkupNode::Nested { .. } => "Nested",
|
MarkupNode::Nested { .. } => "Nested",
|
||||||
MarkupNode::Text { .. } => "Text",
|
MarkupNode::Text { .. } => "Text",
|
||||||
MarkupNode::Blank { .. } => "Blank",
|
MarkupNode::Blank { .. } => "Blank",
|
||||||
|
MarkupNode::Indent { .. } => "Indent",
|
||||||
};
|
};
|
||||||
|
|
||||||
type_str.to_owned()
|
type_str.to_owned()
|
||||||
|
@ -254,6 +238,7 @@ impl MarkupNode {
|
||||||
MarkupNode::Blank {
|
MarkupNode::Blank {
|
||||||
newlines_at_end, ..
|
newlines_at_end, ..
|
||||||
} => *newlines_at_end,
|
} => *newlines_at_end,
|
||||||
|
MarkupNode::Indent { .. } => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,11 +253,12 @@ impl MarkupNode {
|
||||||
MarkupNode::Blank {
|
MarkupNode::Blank {
|
||||||
newlines_at_end, ..
|
newlines_at_end, ..
|
||||||
} => *newlines_at_end += 1,
|
} => *newlines_at_end += 1,
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_string<'a>(env: &Env<'a>, pool_str: &PoolStr) -> String {
|
pub fn get_string<'a>(env: &Env<'a>, pool_str: &PoolStr) -> String {
|
||||||
pool_str.as_str(env.pool).to_owned()
|
pool_str.as_str(env.pool).to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,14 +271,17 @@ pub const COLON: &str = ": ";
|
||||||
pub const COMMA: &str = ", ";
|
pub const COMMA: &str = ", ";
|
||||||
pub const STRING_QUOTES: &str = "\"\"";
|
pub const STRING_QUOTES: &str = "\"\"";
|
||||||
pub const EQUALS: &str = " = ";
|
pub const EQUALS: &str = " = ";
|
||||||
|
pub const ARROW: &str = " -> ";
|
||||||
|
pub const SINGLE_INDENT: &str = " "; // 4 spaces
|
||||||
|
|
||||||
fn new_markup_node(
|
pub fn new_markup_node(
|
||||||
text: String,
|
text: String,
|
||||||
node_id: ASTNodeId,
|
node_id: ASTNodeId,
|
||||||
highlight_style: HighlightStyle,
|
highlight_style: HighlightStyle,
|
||||||
mark_node_pool: &mut SlowPool,
|
mark_node_pool: &mut SlowPool,
|
||||||
|
indent_level: usize,
|
||||||
) -> MarkNodeId {
|
) -> MarkNodeId {
|
||||||
let node = MarkupNode::Text {
|
let content_node = MarkupNode::Text {
|
||||||
content: text,
|
content: text,
|
||||||
ast_node_id: node_id,
|
ast_node_id: node_id,
|
||||||
syn_high_style: highlight_style,
|
syn_high_style: highlight_style,
|
||||||
|
@ -301,256 +290,28 @@ fn new_markup_node(
|
||||||
newlines_at_end: 0,
|
newlines_at_end: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
mark_node_pool.add(node)
|
let content_node_id = mark_node_pool.add(content_node);
|
||||||
}
|
|
||||||
|
|
||||||
pub fn def2_to_markup<'a>(
|
if indent_level > 0 {
|
||||||
env: &mut Env<'a>,
|
let indent_node = MarkupNode::Indent {
|
||||||
def2: &Def2,
|
ast_node_id: node_id,
|
||||||
def2_node_id: DefId,
|
indent_level,
|
||||||
mark_node_pool: &mut SlowPool,
|
parent_id_opt: None,
|
||||||
interns: &Interns,
|
};
|
||||||
) -> ASTResult<MarkNodeId> {
|
|
||||||
let ast_node_id = ASTNodeId::ADefId(def2_node_id);
|
|
||||||
|
|
||||||
let mark_node_id = match def2 {
|
let indent_node_id = mark_node_pool.add(indent_node);
|
||||||
Def2::ValueDef {
|
|
||||||
identifier_id,
|
|
||||||
expr_id,
|
|
||||||
} => {
|
|
||||||
let expr_mn_id = expr2_to_markup(
|
|
||||||
env,
|
|
||||||
env.pool.get(*expr_id),
|
|
||||||
*expr_id,
|
|
||||||
mark_node_pool,
|
|
||||||
interns,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let tld_mn = tld_mark_node(
|
let nested_node = MarkupNode::Nested {
|
||||||
*identifier_id,
|
ast_node_id: node_id,
|
||||||
expr_mn_id,
|
children_ids: vec![indent_node_id, content_node_id],
|
||||||
ast_node_id,
|
parent_id_opt: None,
|
||||||
mark_node_pool,
|
newlines_at_end: 0,
|
||||||
env,
|
};
|
||||||
interns,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
mark_node_pool.add(tld_mn)
|
mark_node_pool.add(nested_node)
|
||||||
}
|
} else {
|
||||||
Def2::Blank => mark_node_pool.add(new_blank_mn_w_nls(ast_node_id, None, 2)),
|
content_node_id
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(mark_node_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// make Markup Nodes: generate String representation, assign Highlighting Style
|
|
||||||
pub fn expr2_to_markup<'a>(
|
|
||||||
env: &mut Env<'a>,
|
|
||||||
expr2: &Expr2,
|
|
||||||
expr2_node_id: ExprId,
|
|
||||||
mark_node_pool: &mut SlowPool,
|
|
||||||
interns: &Interns,
|
|
||||||
) -> ASTResult<MarkNodeId> {
|
|
||||||
let ast_node_id = ASTNodeId::AExprId(expr2_node_id);
|
|
||||||
|
|
||||||
let mark_node_id = match expr2 {
|
|
||||||
Expr2::SmallInt { text, .. }
|
|
||||||
| Expr2::I128 { text, .. }
|
|
||||||
| Expr2::U128 { text, .. }
|
|
||||||
| Expr2::Float { text, .. } => {
|
|
||||||
let num_str = get_string(env, text);
|
|
||||||
|
|
||||||
new_markup_node(num_str, ast_node_id, HighlightStyle::Number, mark_node_pool)
|
|
||||||
}
|
|
||||||
Expr2::Str(text) => new_markup_node(
|
|
||||||
"\"".to_owned() + text.as_str(env.pool) + "\"",
|
|
||||||
ast_node_id,
|
|
||||||
HighlightStyle::String,
|
|
||||||
mark_node_pool,
|
|
||||||
),
|
|
||||||
Expr2::GlobalTag { name, .. } => new_markup_node(
|
|
||||||
get_string(env, name),
|
|
||||||
ast_node_id,
|
|
||||||
HighlightStyle::Type,
|
|
||||||
mark_node_pool,
|
|
||||||
),
|
|
||||||
Expr2::Call { expr: expr_id, .. } => {
|
|
||||||
let expr = env.pool.get(*expr_id);
|
|
||||||
expr2_to_markup(env, expr, *expr_id, mark_node_pool, interns)?
|
|
||||||
}
|
|
||||||
Expr2::Var(symbol) => {
|
|
||||||
//TODO make bump_format with arena
|
|
||||||
let text = format!("{:?}", symbol);
|
|
||||||
new_markup_node(text, ast_node_id, HighlightStyle::Variable, mark_node_pool)
|
|
||||||
}
|
|
||||||
Expr2::List { elems, .. } => {
|
|
||||||
let mut children_ids =
|
|
||||||
vec![mark_node_pool.add(new_left_square_mn(expr2_node_id, None))];
|
|
||||||
|
|
||||||
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(
|
|
||||||
env,
|
|
||||||
sub_expr2,
|
|
||||||
*node_id,
|
|
||||||
mark_node_pool,
|
|
||||||
interns,
|
|
||||||
)?);
|
|
||||||
|
|
||||||
if idx + 1 < elems.len() {
|
|
||||||
children_ids.push(mark_node_pool.add(new_comma_mn(expr2_node_id, None)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
children_ids.push(mark_node_pool.add(new_right_square_mn(expr2_node_id, None)));
|
|
||||||
|
|
||||||
let list_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids,
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
mark_node_pool.add(list_node)
|
|
||||||
}
|
|
||||||
Expr2::EmptyRecord => {
|
|
||||||
let children_ids = vec![
|
|
||||||
mark_node_pool.add(new_left_accolade_mn(expr2_node_id, None)),
|
|
||||||
mark_node_pool.add(new_right_accolade_mn(expr2_node_id, None)),
|
|
||||||
];
|
|
||||||
|
|
||||||
let record_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids,
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
mark_node_pool.add(record_node)
|
|
||||||
}
|
|
||||||
Expr2::Record { fields, .. } => {
|
|
||||||
let mut children_ids =
|
|
||||||
vec![mark_node_pool.add(new_left_accolade_mn(expr2_node_id, None))];
|
|
||||||
|
|
||||||
for (idx, field_node_id) in fields.iter_node_ids().enumerate() {
|
|
||||||
let record_field = env.pool.get(field_node_id);
|
|
||||||
|
|
||||||
let field_name = record_field.get_record_field_pool_str();
|
|
||||||
|
|
||||||
children_ids.push(new_markup_node(
|
|
||||||
field_name.as_str(env.pool).to_owned(),
|
|
||||||
ast_node_id,
|
|
||||||
HighlightStyle::RecordField,
|
|
||||||
mark_node_pool,
|
|
||||||
));
|
|
||||||
|
|
||||||
match record_field {
|
|
||||||
RecordField::InvalidLabelOnly(_, _) => (),
|
|
||||||
RecordField::LabelOnly(_, _, _) => (),
|
|
||||||
RecordField::LabeledValue(_, _, sub_expr2_node_id) => {
|
|
||||||
children_ids.push(mark_node_pool.add(new_colon_mn(expr2_node_id, None)));
|
|
||||||
|
|
||||||
let sub_expr2 = env.pool.get(*sub_expr2_node_id);
|
|
||||||
children_ids.push(expr2_to_markup(
|
|
||||||
env,
|
|
||||||
sub_expr2,
|
|
||||||
*sub_expr2_node_id,
|
|
||||||
mark_node_pool,
|
|
||||||
interns,
|
|
||||||
)?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx + 1 < fields.len() {
|
|
||||||
children_ids.push(mark_node_pool.add(new_comma_mn(expr2_node_id, None)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
children_ids.push(mark_node_pool.add(new_right_accolade_mn(expr2_node_id, None)));
|
|
||||||
|
|
||||||
let record_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids,
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
mark_node_pool.add(record_node)
|
|
||||||
}
|
|
||||||
Expr2::Blank => mark_node_pool.add(new_blank_mn(ast_node_id, None)),
|
|
||||||
Expr2::LetValue {
|
|
||||||
def_id,
|
|
||||||
body_id: _,
|
|
||||||
body_var: _,
|
|
||||||
} => {
|
|
||||||
let pattern_id = env.pool.get(*def_id).get_pattern_id();
|
|
||||||
|
|
||||||
let pattern2 = env.pool.get(pattern_id);
|
|
||||||
|
|
||||||
let val_name = get_identifier_string(pattern2, interns)?;
|
|
||||||
|
|
||||||
let val_name_mn = MarkupNode::Text {
|
|
||||||
content: val_name,
|
|
||||||
ast_node_id,
|
|
||||||
syn_high_style: HighlightStyle::Variable,
|
|
||||||
attributes: Attributes::default(),
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let val_name_mn_id = mark_node_pool.add(val_name_mn);
|
|
||||||
|
|
||||||
let equals_mn_id = mark_node_pool.add(new_equals_mn(ast_node_id, None));
|
|
||||||
|
|
||||||
let value_def = env.pool.get(*def_id);
|
|
||||||
|
|
||||||
match value_def {
|
|
||||||
ValueDef::NoAnnotation {
|
|
||||||
pattern_id: _,
|
|
||||||
expr_id,
|
|
||||||
expr_var: _,
|
|
||||||
} => {
|
|
||||||
let body_mn_id = expr2_to_markup(
|
|
||||||
env,
|
|
||||||
env.pool.get(*expr_id),
|
|
||||||
*expr_id,
|
|
||||||
mark_node_pool,
|
|
||||||
interns,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let body_mn = mark_node_pool.get_mut(body_mn_id);
|
|
||||||
body_mn.add_newline_at_end();
|
|
||||||
|
|
||||||
let full_let_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids: vec![val_name_mn_id, equals_mn_id, body_mn_id],
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
mark_node_pool.add(full_let_node)
|
|
||||||
}
|
|
||||||
other => {
|
|
||||||
unimplemented!(
|
|
||||||
"I don't know how to convert {:?} into a MarkupNode yet.",
|
|
||||||
other
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expr2::RuntimeError() => new_markup_node(
|
|
||||||
"RunTimeError".to_string(),
|
|
||||||
ast_node_id,
|
|
||||||
HighlightStyle::Blank,
|
|
||||||
mark_node_pool,
|
|
||||||
),
|
|
||||||
rest => todo!("implement expr2_to_markup for {:?}", rest),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(mark_node_id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_parent_for_all(markup_node_id: MarkNodeId, mark_node_pool: &mut SlowPool) {
|
pub fn set_parent_for_all(markup_node_id: MarkNodeId, mark_node_pool: &mut SlowPool) {
|
||||||
|
@ -596,221 +357,10 @@ pub fn set_parent_for_all_helper(
|
||||||
}
|
}
|
||||||
MarkupNode::Text { parent_id_opt, .. } => *parent_id_opt = Some(parent_node_id),
|
MarkupNode::Text { parent_id_opt, .. } => *parent_id_opt = Some(parent_node_id),
|
||||||
MarkupNode::Blank { parent_id_opt, .. } => *parent_id_opt = Some(parent_node_id),
|
MarkupNode::Blank { parent_id_opt, .. } => *parent_id_opt = Some(parent_node_id),
|
||||||
|
MarkupNode::Indent { parent_id_opt, .. } => *parent_id_opt = Some(parent_node_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn header_mn(content: String, expr_id: ExprId, mark_node_pool: &mut SlowPool) -> MarkNodeId {
|
|
||||||
let mark_node = MarkupNode::Text {
|
|
||||||
content,
|
|
||||||
ast_node_id: ASTNodeId::AExprId(expr_id),
|
|
||||||
syn_high_style: HighlightStyle::PackageRelated,
|
|
||||||
attributes: Attributes::default(),
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
mark_node_pool.add(mark_node)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn header_val_mn(
|
|
||||||
content: String,
|
|
||||||
expr_id: ExprId,
|
|
||||||
highlight_style: HighlightStyle,
|
|
||||||
mark_node_pool: &mut SlowPool,
|
|
||||||
) -> MarkNodeId {
|
|
||||||
let mark_node = MarkupNode::Text {
|
|
||||||
content,
|
|
||||||
ast_node_id: ASTNodeId::AExprId(expr_id),
|
|
||||||
syn_high_style: highlight_style,
|
|
||||||
attributes: Attributes::default(),
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
mark_node_pool.add(mark_node)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn header_to_markup(app_header: &AppHeader, mark_node_pool: &mut SlowPool) -> MarkNodeId {
|
|
||||||
let expr_id = app_header.ast_node_id;
|
|
||||||
let ast_node_id = ASTNodeId::AExprId(expr_id);
|
|
||||||
|
|
||||||
let app_node_id = header_mn("app ".to_owned(), expr_id, mark_node_pool);
|
|
||||||
|
|
||||||
let app_name_node_id = header_val_mn(
|
|
||||||
app_header.app_name.clone(),
|
|
||||||
expr_id,
|
|
||||||
HighlightStyle::String,
|
|
||||||
mark_node_pool,
|
|
||||||
);
|
|
||||||
|
|
||||||
let full_app_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids: vec![app_node_id, app_name_node_id],
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
let packages_node_id = header_mn(" packages ".to_owned(), expr_id, mark_node_pool);
|
|
||||||
|
|
||||||
let pack_left_acc_node_id = mark_node_pool.add(new_left_accolade_mn(expr_id, None));
|
|
||||||
|
|
||||||
let pack_base_node_id = header_val_mn(
|
|
||||||
"base: ".to_owned(),
|
|
||||||
expr_id,
|
|
||||||
HighlightStyle::RecordField,
|
|
||||||
mark_node_pool,
|
|
||||||
);
|
|
||||||
|
|
||||||
let pack_val_node_id = header_val_mn(
|
|
||||||
app_header.packages_base.clone(),
|
|
||||||
expr_id,
|
|
||||||
HighlightStyle::String,
|
|
||||||
mark_node_pool,
|
|
||||||
);
|
|
||||||
|
|
||||||
let pack_right_acc_node_id = mark_node_pool.add(new_right_accolade_mn(expr_id, None));
|
|
||||||
|
|
||||||
let full_packages_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids: vec![
|
|
||||||
packages_node_id,
|
|
||||||
pack_left_acc_node_id,
|
|
||||||
pack_base_node_id,
|
|
||||||
pack_val_node_id,
|
|
||||||
pack_right_acc_node_id,
|
|
||||||
],
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
let imports_node_id = header_mn(" imports ".to_owned(), expr_id, mark_node_pool);
|
|
||||||
|
|
||||||
let imports_left_square_node_id = mark_node_pool.add(new_left_square_mn(expr_id, None));
|
|
||||||
|
|
||||||
let mut import_child_ids: Vec<MarkNodeId> = add_header_mn_list(
|
|
||||||
&app_header.imports,
|
|
||||||
expr_id,
|
|
||||||
HighlightStyle::Import,
|
|
||||||
mark_node_pool,
|
|
||||||
);
|
|
||||||
|
|
||||||
let imports_right_square_node_id = mark_node_pool.add(new_right_square_mn(expr_id, None));
|
|
||||||
|
|
||||||
let mut full_import_children = vec![imports_node_id, imports_left_square_node_id];
|
|
||||||
|
|
||||||
full_import_children.append(&mut import_child_ids);
|
|
||||||
full_import_children.push(imports_right_square_node_id);
|
|
||||||
|
|
||||||
let full_import_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids: full_import_children,
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
let provides_node_id = header_mn(" provides ".to_owned(), expr_id, mark_node_pool);
|
|
||||||
|
|
||||||
let provides_left_square_node_id = mark_node_pool.add(new_left_square_mn(expr_id, None));
|
|
||||||
|
|
||||||
let mut provides_val_node_ids: Vec<MarkNodeId> = add_header_mn_list(
|
|
||||||
&app_header.provides,
|
|
||||||
expr_id,
|
|
||||||
HighlightStyle::Provides,
|
|
||||||
mark_node_pool,
|
|
||||||
);
|
|
||||||
|
|
||||||
let provides_right_square_node_id = mark_node_pool.add(new_right_square_mn(expr_id, None));
|
|
||||||
|
|
||||||
let provides_end_node_id = header_mn(" to base".to_owned(), expr_id, mark_node_pool);
|
|
||||||
|
|
||||||
let mut full_provides_children = vec![provides_node_id, provides_left_square_node_id];
|
|
||||||
|
|
||||||
full_provides_children.append(&mut provides_val_node_ids);
|
|
||||||
full_provides_children.push(provides_right_square_node_id);
|
|
||||||
full_provides_children.push(provides_end_node_id);
|
|
||||||
|
|
||||||
let full_provides_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids: full_provides_children,
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
let full_app_node_id = mark_node_pool.add(full_app_node);
|
|
||||||
let full_packages_node = mark_node_pool.add(full_packages_node);
|
|
||||||
let full_import_node_id = mark_node_pool.add(full_import_node);
|
|
||||||
let full_provides_node_id = mark_node_pool.add(full_provides_node);
|
|
||||||
|
|
||||||
let header_mark_node = MarkupNode::Nested {
|
|
||||||
ast_node_id,
|
|
||||||
children_ids: vec![
|
|
||||||
full_app_node_id,
|
|
||||||
full_packages_node,
|
|
||||||
full_import_node_id,
|
|
||||||
full_provides_node_id,
|
|
||||||
],
|
|
||||||
parent_id_opt: None,
|
|
||||||
newlines_at_end: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
let header_mn_id = mark_node_pool.add(header_mark_node);
|
|
||||||
|
|
||||||
set_parent_for_all(header_mn_id, mark_node_pool);
|
|
||||||
|
|
||||||
header_mn_id
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for provides and imports
|
|
||||||
fn add_header_mn_list(
|
|
||||||
str_vec: &[String],
|
|
||||||
expr_id: ExprId,
|
|
||||||
highlight_style: HighlightStyle,
|
|
||||||
mark_node_pool: &mut SlowPool,
|
|
||||||
) -> Vec<MarkNodeId> {
|
|
||||||
let nr_of_elts = str_vec.len();
|
|
||||||
|
|
||||||
str_vec
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(indx, provide_str)| {
|
|
||||||
let provide_str = header_val_mn(
|
|
||||||
provide_str.to_owned(),
|
|
||||||
expr_id,
|
|
||||||
highlight_style,
|
|
||||||
mark_node_pool,
|
|
||||||
);
|
|
||||||
|
|
||||||
if indx != nr_of_elts - 1 {
|
|
||||||
vec![provide_str, mark_node_pool.add(new_comma_mn(expr_id, None))]
|
|
||||||
} else {
|
|
||||||
vec![provide_str]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ast_to_mark_nodes<'a>(
|
|
||||||
env: &mut Env<'a>,
|
|
||||||
ast: &AST,
|
|
||||||
mark_node_pool: &mut SlowPool,
|
|
||||||
interns: &Interns,
|
|
||||||
) -> ASTResult<Vec<MarkNodeId>> {
|
|
||||||
let mut all_mark_node_ids = vec![header_to_markup(&ast.header, mark_node_pool)];
|
|
||||||
|
|
||||||
for &def_id in ast.def_ids.iter() {
|
|
||||||
let def2 = env.pool.get(def_id);
|
|
||||||
|
|
||||||
let def2_markup_id = def2_to_markup(env, def2, def_id, mark_node_pool, interns)?;
|
|
||||||
|
|
||||||
set_parent_for_all(def2_markup_id, mark_node_pool);
|
|
||||||
|
|
||||||
all_mark_node_ids.push(def2_markup_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(all_mark_node_ids)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for MarkupNode {
|
impl fmt::Display for MarkupNode {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
|
@ -871,3 +421,50 @@ pub fn get_root_mark_node_id(mark_node_id: MarkNodeId, mark_node_pool: &SlowPool
|
||||||
|
|
||||||
curr_mark_node_id
|
curr_mark_node_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// put space mark nodes between each node in mark_nodes
|
||||||
|
pub fn join_mark_nodes_spaces(
|
||||||
|
mark_nodes_ids: Vec<MarkNodeId>,
|
||||||
|
with_prepend: bool,
|
||||||
|
ast_node_id: ASTNodeId,
|
||||||
|
mark_node_pool: &mut SlowPool,
|
||||||
|
) -> Vec<MarkNodeId> {
|
||||||
|
let space_range_max = if with_prepend {
|
||||||
|
mark_nodes_ids.len()
|
||||||
|
} else {
|
||||||
|
mark_nodes_ids.len() - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
let join_nodes: Vec<MarkNodeId> = (0..space_range_max)
|
||||||
|
.map(|_| {
|
||||||
|
let space_node = MarkupNode::Text {
|
||||||
|
content: " ".to_string(),
|
||||||
|
ast_node_id,
|
||||||
|
syn_high_style: HighlightStyle::Blank,
|
||||||
|
attributes: Attributes::default(),
|
||||||
|
parent_id_opt: None,
|
||||||
|
newlines_at_end: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
mark_node_pool.add(space_node)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if with_prepend {
|
||||||
|
join_nodes.into_iter().interleave(mark_nodes_ids).collect()
|
||||||
|
} else {
|
||||||
|
mark_nodes_ids.into_iter().interleave(join_nodes).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// put comma mark nodes between each node in mark_nodes
|
||||||
|
pub fn join_mark_nodes_commas(
|
||||||
|
mark_nodes: Vec<MarkupNode>,
|
||||||
|
ast_node_id: ASTNodeId,
|
||||||
|
) -> Vec<MarkupNode> {
|
||||||
|
let join_nodes: Vec<MarkupNode> = (0..(mark_nodes.len() - 1))
|
||||||
|
.map(|_| new_comma_mn_ast(ast_node_id, None))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
mark_nodes.into_iter().interleave(join_nodes).collect()
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,8 @@
|
||||||
use roc_ast::{
|
use roc_ast::{
|
||||||
ast_error::ASTResult,
|
ast_error::ASTResult,
|
||||||
lang::{
|
lang::{core::ast::ASTNodeId, env::Env},
|
||||||
core::{
|
|
||||||
ast::ASTNodeId,
|
|
||||||
pattern::{get_identifier_string, PatternId},
|
|
||||||
},
|
|
||||||
env::Env,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use roc_module::symbol::Interns;
|
use roc_module::symbol::IdentId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
markup::{attribute::Attributes, common_nodes::new_equals_mn, nodes::MarkupNode},
|
markup::{attribute::Attributes, common_nodes::new_equals_mn, nodes::MarkupNode},
|
||||||
|
@ -17,20 +11,18 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn tld_mark_node<'a>(
|
pub fn tld_mark_node<'a>(
|
||||||
identifier_id: PatternId,
|
identifier_id: IdentId,
|
||||||
expr_mark_node_id: MarkNodeId,
|
expr_mark_node_id: MarkNodeId,
|
||||||
ast_node_id: ASTNodeId,
|
ast_node_id: ASTNodeId,
|
||||||
mark_node_pool: &mut SlowPool,
|
mark_node_pool: &mut SlowPool,
|
||||||
env: &Env<'a>,
|
env: &Env<'a>,
|
||||||
interns: &Interns,
|
|
||||||
) -> ASTResult<MarkupNode> {
|
) -> ASTResult<MarkupNode> {
|
||||||
let pattern2 = env.pool.get(identifier_id);
|
let val_name = env.ident_ids.get_name_str_res(identifier_id)?;
|
||||||
let val_name = get_identifier_string(pattern2, interns)?;
|
|
||||||
|
|
||||||
let val_name_mn = MarkupNode::Text {
|
let val_name_mn = MarkupNode::Text {
|
||||||
content: val_name,
|
content: val_name.to_owned(),
|
||||||
ast_node_id,
|
ast_node_id,
|
||||||
syn_high_style: HighlightStyle::Variable,
|
syn_high_style: HighlightStyle::Value,
|
||||||
attributes: Attributes::default(),
|
attributes: Attributes::default(),
|
||||||
parent_id_opt: None,
|
parent_id_opt: None,
|
||||||
newlines_at_end: 0,
|
newlines_at_end: 0,
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub enum MarkError {
|
||||||
node_type: String,
|
node_type: String,
|
||||||
backtrace: Backtrace,
|
backtrace: Backtrace,
|
||||||
},
|
},
|
||||||
#[snafu(display("UIError: {}", msg))]
|
#[snafu(display("UtilError: {}", msg))]
|
||||||
UtilErrorBacktrace { msg: String, backtrace: Backtrace },
|
UtilErrorBacktrace { msg: String, backtrace: Backtrace },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::colors::{self, from_hsb, RgbaTup};
|
use crate::colors::{from_hsb, RgbaTup};
|
||||||
|
|
||||||
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug, Deserialize, Serialize)]
|
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug, Deserialize, Serialize)]
|
||||||
pub enum HighlightStyle {
|
pub enum HighlightStyle {
|
||||||
|
@ -9,11 +9,12 @@ pub enum HighlightStyle {
|
||||||
Comma,
|
Comma,
|
||||||
String,
|
String,
|
||||||
FunctionName,
|
FunctionName,
|
||||||
|
FunctionArgName,
|
||||||
Type,
|
Type,
|
||||||
Bracket,
|
Bracket,
|
||||||
Number,
|
Number,
|
||||||
PackageRelated, // app, packages, imports, exposes, provides...
|
PackageRelated, // app, packages, imports, exposes, provides...
|
||||||
Variable,
|
Value,
|
||||||
RecordField,
|
RecordField,
|
||||||
Import,
|
Import,
|
||||||
Provides,
|
Provides,
|
||||||
|
@ -23,20 +24,23 @@ pub enum HighlightStyle {
|
||||||
pub fn default_highlight_map() -> HashMap<HighlightStyle, RgbaTup> {
|
pub fn default_highlight_map() -> HashMap<HighlightStyle, RgbaTup> {
|
||||||
use HighlightStyle::*;
|
use HighlightStyle::*;
|
||||||
|
|
||||||
|
let almost_white = from_hsb(258, 5, 95);
|
||||||
|
|
||||||
let mut highlight_map = HashMap::new();
|
let mut highlight_map = HashMap::new();
|
||||||
[
|
[
|
||||||
(Operator, colors::WHITE),
|
(Operator, from_hsb(185, 50, 75)),
|
||||||
(Comma, from_hsb(258, 50, 90)),
|
(Comma, from_hsb(258, 50, 90)),
|
||||||
(String, from_hsb(346, 65, 97)),
|
(String, from_hsb(346, 65, 97)),
|
||||||
(FunctionName, colors::WHITE),
|
(FunctionName, almost_white),
|
||||||
(Type, colors::WHITE),
|
(FunctionArgName, from_hsb(225, 50, 100)),
|
||||||
|
(Type, almost_white),
|
||||||
(Bracket, from_hsb(347, 80, 100)),
|
(Bracket, from_hsb(347, 80, 100)),
|
||||||
(Number, from_hsb(185, 50, 75)),
|
(Number, from_hsb(225, 50, 100)),
|
||||||
(PackageRelated, colors::WHITE),
|
(PackageRelated, almost_white),
|
||||||
(Variable, colors::WHITE),
|
(Value, almost_white),
|
||||||
(RecordField, from_hsb(258, 50, 90)),
|
(RecordField, from_hsb(258, 50, 90)),
|
||||||
(Import, from_hsb(185, 50, 75)),
|
(Import, from_hsb(225, 50, 100)),
|
||||||
(Provides, from_hsb(185, 50, 75)),
|
(Provides, from_hsb(225, 50, 100)),
|
||||||
(Blank, from_hsb(258, 50, 90)),
|
(Blank, from_hsb(258, 50, 90)),
|
||||||
// comment from_hsb(285, 6, 47) or 186, 35, 40
|
// comment from_hsb(285, 6, 47) or 186, 35, 40
|
||||||
]
|
]
|
||||||
|
|
|
@ -231,9 +231,9 @@ impl fmt::Debug for IdentStr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// IdentStr { is_small_str: false, storage: Refcounted(3), elements: [ 1,2,3,4] }
|
// IdentStr { is_small_str: false, storage: Refcounted(3), elements: [ 1,2,3,4] }
|
||||||
f.debug_struct("IdentStr")
|
f.debug_struct("IdentStr")
|
||||||
.field("is_small_str", &self.is_small_str())
|
//.field("is_small_str", &self.is_small_str())
|
||||||
.field("string", &self.as_str())
|
.field("string", &self.as_str())
|
||||||
.field("elements", &self.as_slice())
|
//.field("elements", &self.as_slice())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -646,6 +646,13 @@ impl LoadedModule {
|
||||||
|
|
||||||
total
|
total
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exposed_values_str(&self) -> Vec<&str> {
|
||||||
|
self.exposed_values
|
||||||
|
.iter()
|
||||||
|
.map(|symbol| symbol.ident_str(&self.interns).as_str())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -12,6 +12,7 @@ roc_collections = { path = "../collections" }
|
||||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
|
snafu = { version = "0.6", features = ["backtraces"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.5.1"
|
pretty_assertions = "0.5.1"
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::fmt;
|
||||||
|
|
||||||
/// This could be uppercase or lowercase, qualified or unqualified.
|
/// This could be uppercase or lowercase, qualified or unqualified.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct Ident(IdentStr);
|
pub struct Ident(pub IdentStr); // Is IdentStr allowed to be pub?
|
||||||
|
|
||||||
impl Ident {
|
impl Ident {
|
||||||
pub fn as_inline_str(&self) -> &IdentStr {
|
pub fn as_inline_str(&self) -> &IdentStr {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
pub mod ident;
|
pub mod ident;
|
||||||
pub mod low_level;
|
pub mod low_level;
|
||||||
|
pub mod module_err;
|
||||||
pub mod operator;
|
pub mod operator;
|
||||||
pub mod symbol;
|
pub mod symbol;
|
||||||
|
|
||||||
|
|
30
compiler/module/src/module_err.rs
Normal file
30
compiler/module/src/module_err.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use snafu::{Backtrace, Snafu};
|
||||||
|
|
||||||
|
use crate::symbol::IdentId;
|
||||||
|
|
||||||
|
#[derive(Debug, Snafu)]
|
||||||
|
#[snafu(visibility(pub))]
|
||||||
|
pub enum ModuleError {
|
||||||
|
#[snafu(display(
|
||||||
|
"ModuleIdNotFound: I could not find the ModuleId {} in Interns.all_ident_ids: {}.",
|
||||||
|
module_id,
|
||||||
|
all_ident_ids
|
||||||
|
))]
|
||||||
|
ModuleIdNotFound {
|
||||||
|
module_id: String,
|
||||||
|
all_ident_ids: String,
|
||||||
|
backtrace: Backtrace,
|
||||||
|
},
|
||||||
|
#[snafu(display(
|
||||||
|
"IdentIdNotFound: I could not find IdentId {:?} in ident_ids {:?}.",
|
||||||
|
ident_id,
|
||||||
|
ident_ids_str
|
||||||
|
))]
|
||||||
|
IdentIdNotFound {
|
||||||
|
ident_id: IdentId,
|
||||||
|
ident_ids_str: String,
|
||||||
|
backtrace: Backtrace,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ModuleResult<T, E = ModuleError> = std::result::Result<T, E>;
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::ident::{Ident, ModuleName};
|
use crate::ident::{Ident, ModuleName};
|
||||||
|
use crate::module_err::{IdentIdNotFound, ModuleIdNotFound, ModuleResult};
|
||||||
use roc_collections::all::{default_hasher, MutMap, SendMap};
|
use roc_collections::all::{default_hasher, MutMap, SendMap};
|
||||||
use roc_ident::IdentStr;
|
use roc_ident::IdentStr;
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
|
use snafu::OptionExt;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::{fmt, u32};
|
use std::{fmt, u32};
|
||||||
|
|
||||||
|
@ -253,6 +255,30 @@ impl Interns {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_module_ident_ids<'a>(
|
||||||
|
all_ident_ids: &'a MutMap<ModuleId, IdentIds>,
|
||||||
|
module_id: &ModuleId,
|
||||||
|
) -> ModuleResult<&'a IdentIds> {
|
||||||
|
all_ident_ids
|
||||||
|
.get(module_id)
|
||||||
|
.with_context(|| ModuleIdNotFound {
|
||||||
|
module_id: format!("{:?}", module_id),
|
||||||
|
all_ident_ids: format!("{:?}", all_ident_ids),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_module_ident_ids_mut<'a>(
|
||||||
|
all_ident_ids: &'a mut MutMap<ModuleId, IdentIds>,
|
||||||
|
module_id: &ModuleId,
|
||||||
|
) -> ModuleResult<&'a mut IdentIds> {
|
||||||
|
all_ident_ids
|
||||||
|
.get_mut(module_id)
|
||||||
|
.with_context(|| ModuleIdNotFound {
|
||||||
|
module_id: format!("{:?}", module_id),
|
||||||
|
all_ident_ids: "I could not return all_ident_ids here because of borrowing issues.",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// This is used in Debug builds only, to let us have a Debug instance
|
/// This is used in Debug builds only, to let us have a Debug instance
|
||||||
|
@ -621,6 +647,17 @@ impl IdentIds {
|
||||||
pub fn get_name(&self, id: IdentId) -> Option<&Ident> {
|
pub fn get_name(&self, id: IdentId) -> Option<&Ident> {
|
||||||
self.by_id.get(id.0 as usize)
|
self.by_id.get(id.0 as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_name_str_res(&self, ident_id: IdentId) -> ModuleResult<&str> {
|
||||||
|
Ok(self
|
||||||
|
.get_name(ident_id)
|
||||||
|
.with_context(|| IdentIdNotFound {
|
||||||
|
ident_id,
|
||||||
|
ident_ids_str: format!("{:?}", self),
|
||||||
|
})?
|
||||||
|
.as_inline_str()
|
||||||
|
.as_str())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUILTINS
|
// BUILTINS
|
||||||
|
|
|
@ -111,7 +111,7 @@ pub enum Expr<'a> {
|
||||||
|
|
||||||
// Lookups
|
// Lookups
|
||||||
Var {
|
Var {
|
||||||
module_name: &'a str,
|
module_name: &'a str, // module_name will only be filled if the original Roc code stated something like `5 + SomeModule.myVar`, module_name will be blank if it was `5 + myVar`
|
||||||
ident: &'a str,
|
ident: &'a str,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ roc_types = { path = "../compiler/types" }
|
||||||
roc_parse = { path = "../compiler/parse" }
|
roc_parse = { path = "../compiler/parse" }
|
||||||
roc_collections = { path = "../compiler/collections" }
|
roc_collections = { path = "../compiler/collections" }
|
||||||
bumpalo = { version = "3.2", features = ["collections"] }
|
bumpalo = { version = "3.2", features = ["collections"] }
|
||||||
|
snafu = { version = "0.6", features = ["backtraces"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.5.1"
|
pretty_assertions = "0.5.1"
|
||||||
|
|
|
@ -4,21 +4,20 @@ use roc_ast::{
|
||||||
lang::{self, core::def::def_to_def2::def_to_def2},
|
lang::{self, core::def::def_to_def2::def_to_def2},
|
||||||
mem_pool::pool::Pool,
|
mem_pool::pool::Pool,
|
||||||
};
|
};
|
||||||
use roc_code_markup::{markup::nodes::def2_to_markup, slow_pool::SlowPool};
|
use roc_code_markup::{markup::convert::from_def2::def2_to_markup, slow_pool::SlowPool};
|
||||||
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
|
use roc_module::symbol::{IdentIds, Interns, ModuleId};
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
use roc_types::subs::VarStore;
|
use roc_types::subs::VarStore;
|
||||||
|
|
||||||
use crate::html::mark_node_to_html;
|
use crate::{docs_error::DocsResult, html::mark_node_to_html};
|
||||||
|
|
||||||
// html is written to buf
|
// html is written to buf
|
||||||
pub fn defs_to_html<'a>(
|
pub fn defs_to_html<'a>(
|
||||||
buf: &mut BumpString<'a>,
|
buf: &mut BumpString<'a>,
|
||||||
defs: Vec<roc_parse::ast::Def<'a>>,
|
defs: Vec<roc_parse::ast::Def<'a>>,
|
||||||
env_module_id: ModuleId,
|
env_module_id: ModuleId,
|
||||||
env_module_ids: &'a ModuleIds,
|
interns: &mut Interns,
|
||||||
interns: &Interns,
|
) -> DocsResult<()> {
|
||||||
) {
|
|
||||||
let mut env_pool = Pool::with_capacity(1024);
|
let mut env_pool = Pool::with_capacity(1024);
|
||||||
let env_arena = Bump::new();
|
let env_arena = Bump::new();
|
||||||
|
|
||||||
|
@ -34,18 +33,20 @@ pub fn defs_to_html<'a>(
|
||||||
&mut env_pool,
|
&mut env_pool,
|
||||||
&mut var_store,
|
&mut var_store,
|
||||||
dep_idents,
|
dep_idents,
|
||||||
env_module_ids,
|
&interns.module_ids,
|
||||||
exposed_ident_ids,
|
exposed_ident_ids,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store);
|
let mut scope = lang::scope::Scope::new(env.home, env.pool, env.var_store);
|
||||||
|
scope.fill_scope(&env, &mut interns.all_ident_ids)?;
|
||||||
|
|
||||||
let region = Region::new(0, 0, 0, 0);
|
let region = Region::new(0, 0, 0, 0);
|
||||||
|
|
||||||
for def in defs.iter() {
|
for def in defs.iter() {
|
||||||
// TODO remove unwrap
|
write_def_to_bump_str_html(&def_arena, &mut env, &mut scope, region, def, interns, buf)?;
|
||||||
write_def_to_bump_str_html(&def_arena, &mut env, &mut scope, region, def, interns, buf)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_def_to_bump_str_html<'a, 'b>(
|
fn write_def_to_bump_str_html<'a, 'b>(
|
||||||
|
|
45
docs/src/docs_error.rs
Normal file
45
docs/src/docs_error.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
use roc_ast::ast_error::ASTError;
|
||||||
|
use roc_module::module_err::ModuleError;
|
||||||
|
use roc_parse::parser::SyntaxError;
|
||||||
|
use snafu::{NoneError, ResultExt, Snafu};
|
||||||
|
|
||||||
|
#[derive(Debug, Snafu)]
|
||||||
|
#[snafu(visibility(pub))]
|
||||||
|
#[allow(clippy::enum_variant_names)]
|
||||||
|
pub enum DocsError {
|
||||||
|
WrapASTError {
|
||||||
|
#[snafu(backtrace)]
|
||||||
|
source: ASTError,
|
||||||
|
},
|
||||||
|
WrapModuleError {
|
||||||
|
#[snafu(backtrace)]
|
||||||
|
source: ModuleError,
|
||||||
|
},
|
||||||
|
WrapSyntaxError {
|
||||||
|
msg: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DocsResult<T, E = DocsError> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
impl<'a> From<SyntaxError<'a>> for DocsError {
|
||||||
|
fn from(syntax_err: SyntaxError) -> Self {
|
||||||
|
let msg = format!("{:?}", syntax_err);
|
||||||
|
|
||||||
|
// hack to handle MarkError derive
|
||||||
|
let dummy_res: Result<(), NoneError> = Err(NoneError {});
|
||||||
|
dummy_res.context(WrapSyntaxError { msg }).unwrap_err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ASTError> for DocsError {
|
||||||
|
fn from(ast_err: ASTError) -> Self {
|
||||||
|
Self::WrapASTError { source: ast_err }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ModuleError> for DocsError {
|
||||||
|
fn from(module_err: ModuleError) -> Self {
|
||||||
|
Self::WrapModuleError { source: module_err }
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ use roc_ast::{
|
||||||
lang::{self, core::expr::expr_to_expr2::expr_to_expr2},
|
lang::{self, core::expr::expr_to_expr2::expr_to_expr2},
|
||||||
mem_pool::pool::Pool,
|
mem_pool::pool::Pool,
|
||||||
};
|
};
|
||||||
use roc_code_markup::{markup::nodes::expr2_to_markup, slow_pool::SlowPool};
|
use roc_code_markup::{markup::convert::from_expr2::expr2_to_markup, slow_pool::SlowPool};
|
||||||
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
|
use roc_module::symbol::{IdentIds, Interns, ModuleId, ModuleIds};
|
||||||
use roc_parse::ast::Expr;
|
use roc_parse::ast::Expr;
|
||||||
use roc_region::all::Region;
|
use roc_region::all::Region;
|
||||||
|
@ -63,6 +63,7 @@ fn write_expr_to_bump_str_html<'a, 'b>(
|
||||||
expr2_id,
|
expr2_id,
|
||||||
&mut mark_node_pool,
|
&mut mark_node_pool,
|
||||||
interns,
|
interns,
|
||||||
|
0,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let expr2_markup_node = mark_node_pool.get(expr2_markup_id);
|
let expr2_markup_node = mark_node_pool.get(expr2_markup_id);
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub fn mark_node_to_html<'a>(
|
||||||
mark_node_pool: &SlowPool,
|
mark_node_pool: &SlowPool,
|
||||||
buf: &mut BumpString<'a>,
|
buf: &mut BumpString<'a>,
|
||||||
) {
|
) {
|
||||||
let additional_newlines: usize;
|
let mut additional_newlines = 0;
|
||||||
|
|
||||||
match mark_node {
|
match mark_node {
|
||||||
MarkupNode::Nested {
|
MarkupNode::Nested {
|
||||||
|
@ -33,12 +33,13 @@ pub fn mark_node_to_html<'a>(
|
||||||
Operator => "operator",
|
Operator => "operator",
|
||||||
Comma => "comma",
|
Comma => "comma",
|
||||||
String => "string",
|
String => "string",
|
||||||
FunctionName => "function_name",
|
FunctionName => "function-name",
|
||||||
|
FunctionArgName => "function-arg-name",
|
||||||
Type => "type",
|
Type => "type",
|
||||||
Bracket => "bracket",
|
Bracket => "bracket",
|
||||||
Number => "number",
|
Number => "number",
|
||||||
PackageRelated => "package-related",
|
PackageRelated => "package-related",
|
||||||
Variable => "variable",
|
Value => "value",
|
||||||
RecordField => "recordfield",
|
RecordField => "recordfield",
|
||||||
Import => "import",
|
Import => "import",
|
||||||
Provides => "provides",
|
Provides => "provides",
|
||||||
|
@ -62,6 +63,11 @@ pub fn mark_node_to_html<'a>(
|
||||||
|
|
||||||
additional_newlines = *newlines_at_end;
|
additional_newlines = *newlines_at_end;
|
||||||
}
|
}
|
||||||
|
MarkupNode::Indent { .. } => {
|
||||||
|
let content_str = mark_node.get_content();
|
||||||
|
|
||||||
|
write_html_to_buf(&content_str, "indent", buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..additional_newlines {
|
for _ in 0..additional_newlines {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
extern crate pulldown_cmark;
|
extern crate pulldown_cmark;
|
||||||
extern crate roc_load;
|
extern crate roc_load;
|
||||||
use bumpalo::{collections::String as BumpString, collections::Vec as BumpVec, Bump};
|
use bumpalo::{collections::String as BumpString, Bump};
|
||||||
use def::defs_to_html;
|
use def::defs_to_html;
|
||||||
|
use docs_error::DocsResult;
|
||||||
use expr::expr_to_html;
|
use expr::expr_to_html;
|
||||||
use roc_builtins::std::StdLib;
|
use roc_builtins::std::StdLib;
|
||||||
use roc_can::builtins::builtin_defs_map;
|
use roc_can::builtins::builtin_defs_map;
|
||||||
|
@ -19,12 +20,12 @@ use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
mod def;
|
mod def;
|
||||||
|
mod docs_error;
|
||||||
mod expr;
|
mod expr;
|
||||||
mod html;
|
mod html;
|
||||||
|
|
||||||
pub fn generate_docs_html(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
pub fn generate_docs_html(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
||||||
let loaded_modules = load_modules_for_files(filenames, std_lib);
|
let loaded_modules = load_modules_for_files(filenames, std_lib);
|
||||||
let mut arena = Bump::new();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// TODO: get info from a file like "elm.json"
|
// TODO: get info from a file like "elm.json"
|
||||||
|
@ -83,18 +84,6 @@ pub fn generate_docs_html(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &
|
||||||
|
|
||||||
// Write each package's module docs html file
|
// Write each package's module docs html file
|
||||||
for loaded_module in package.modules.iter_mut() {
|
for loaded_module in package.modules.iter_mut() {
|
||||||
arena.reset();
|
|
||||||
|
|
||||||
let mut exports: BumpVec<&str> =
|
|
||||||
BumpVec::with_capacity_in(loaded_module.exposed_values.len(), &arena);
|
|
||||||
|
|
||||||
// TODO should this also include exposed_aliases?
|
|
||||||
for symbol in loaded_module.exposed_values.iter() {
|
|
||||||
exports.push(symbol.ident_str(&loaded_module.interns));
|
|
||||||
}
|
|
||||||
|
|
||||||
let exports = exports.into_bump_slice();
|
|
||||||
|
|
||||||
for module_docs in loaded_module.documentation.values() {
|
for module_docs in loaded_module.documentation.values() {
|
||||||
let module_dir = build_dir.join(module_docs.name.replace(".", "/").as_str());
|
let module_dir = build_dir.join(module_docs.name.replace(".", "/").as_str());
|
||||||
|
|
||||||
|
@ -109,7 +98,7 @@ pub fn generate_docs_html(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &
|
||||||
)
|
)
|
||||||
.replace(
|
.replace(
|
||||||
"<!-- Module Docs -->",
|
"<!-- Module Docs -->",
|
||||||
render_module_documentation(exports, module_docs, loaded_module).as_str(),
|
render_module_documentation(module_docs, loaded_module).as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
fs::write(module_dir.join("index.html"), rendered_module)
|
fs::write(module_dir.join("index.html"), rendered_module)
|
||||||
|
@ -148,25 +137,23 @@ pub fn syntax_highlight_top_level_defs<'a>(
|
||||||
buf: &mut BumpString<'a>,
|
buf: &mut BumpString<'a>,
|
||||||
code_str: &'a str,
|
code_str: &'a str,
|
||||||
env_module_id: ModuleId,
|
env_module_id: ModuleId,
|
||||||
env_module_ids: &'a ModuleIds,
|
interns: &mut Interns,
|
||||||
interns: &Interns,
|
) -> DocsResult<String> {
|
||||||
) -> Result<String, SyntaxError<'a>> {
|
|
||||||
let trimmed_code_str = code_str.trim_end().trim();
|
let trimmed_code_str = code_str.trim_end().trim();
|
||||||
|
|
||||||
match roc_parse::test_helpers::parse_defs_with(arena, trimmed_code_str) {
|
match roc_parse::test_helpers::parse_defs_with(arena, trimmed_code_str) {
|
||||||
Ok(vec_loc_def) => {
|
Ok(vec_loc_def) => {
|
||||||
let vec_def = vec_loc_def.iter().map(|loc| loc.value).collect();
|
let vec_def = vec_loc_def.iter().map(|loc| loc.value).collect();
|
||||||
|
|
||||||
defs_to_html(buf, vec_def, env_module_id, env_module_ids, interns);
|
defs_to_html(buf, vec_def, env_module_id, interns)?;
|
||||||
|
|
||||||
Ok(buf.to_string())
|
Ok(buf.to_string())
|
||||||
}
|
}
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_module_documentation(
|
fn render_module_documentation(
|
||||||
exposed_values: &[&str],
|
|
||||||
module: &ModuleDocumentation,
|
module: &ModuleDocumentation,
|
||||||
loaded_module: &LoadedModule,
|
loaded_module: &LoadedModule,
|
||||||
) -> String {
|
) -> String {
|
||||||
|
@ -181,6 +168,8 @@ fn render_module_documentation(
|
||||||
.as_str(),
|
.as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let exposed_values = loaded_module.exposed_values_str();
|
||||||
|
|
||||||
for entry in &module.entries {
|
for entry in &module.entries {
|
||||||
let mut should_render_entry = true;
|
let mut should_render_entry = true;
|
||||||
|
|
||||||
|
@ -232,7 +221,7 @@ fn render_module_documentation(
|
||||||
if let Some(docs) = &doc_def.docs {
|
if let Some(docs) = &doc_def.docs {
|
||||||
buf.push_str(
|
buf.push_str(
|
||||||
markdown_to_html(
|
markdown_to_html(
|
||||||
exposed_values,
|
&exposed_values,
|
||||||
&module.scope,
|
&module.scope,
|
||||||
docs.to_string(),
|
docs.to_string(),
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -243,7 +232,7 @@ fn render_module_documentation(
|
||||||
}
|
}
|
||||||
DocEntry::DetachedDoc(docs) => {
|
DocEntry::DetachedDoc(docs) => {
|
||||||
let markdown = markdown_to_html(
|
let markdown = markdown_to_html(
|
||||||
exposed_values,
|
&exposed_values,
|
||||||
&module.scope,
|
&module.scope,
|
||||||
docs.to_string(),
|
docs.to_string(),
|
||||||
loaded_module,
|
loaded_module,
|
||||||
|
@ -972,6 +961,7 @@ fn markdown_to_html(
|
||||||
let code_block_arena = Bump::new();
|
let code_block_arena = Bump::new();
|
||||||
|
|
||||||
let mut code_block_buf = BumpString::new_in(&code_block_arena);
|
let mut code_block_buf = BumpString::new_in(&code_block_arena);
|
||||||
|
|
||||||
match syntax_highlight_expr(
|
match syntax_highlight_expr(
|
||||||
&code_block_arena,
|
&code_block_arena,
|
||||||
&mut code_block_buf,
|
&mut code_block_buf,
|
||||||
|
|
|
@ -13,7 +13,11 @@ mod insert_doc_syntax_highlighting {
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
fn expect_html(code_str: &str, want: &str, use_expr: bool) {
|
fn expect_html(code_str: &str, want: &str, use_expr: bool) {
|
||||||
let loaded_module = make_mock_module();
|
let mut loaded_module = if use_expr {
|
||||||
|
make_mock_module("")
|
||||||
|
} else {
|
||||||
|
make_mock_module(code_str)
|
||||||
|
};
|
||||||
|
|
||||||
let code_block_arena = Bump::new();
|
let code_block_arena = Bump::new();
|
||||||
let mut code_block_buf = BumpString::new_in(&code_block_arena);
|
let mut code_block_buf = BumpString::new_in(&code_block_arena);
|
||||||
|
@ -40,8 +44,7 @@ mod insert_doc_syntax_highlighting {
|
||||||
&mut code_block_buf,
|
&mut code_block_buf,
|
||||||
code_str,
|
code_str,
|
||||||
loaded_module.module_id,
|
loaded_module.module_id,
|
||||||
&loaded_module.interns.module_ids,
|
&mut loaded_module.interns,
|
||||||
&loaded_module.interns,
|
|
||||||
) {
|
) {
|
||||||
Ok(highlighted_code_str) => {
|
Ok(highlighted_code_str) => {
|
||||||
assert_eq!(highlighted_code_str, want);
|
assert_eq!(highlighted_code_str, want);
|
||||||
|
@ -64,7 +67,7 @@ main = "Hello, world!"
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
fn make_mock_module() -> LoadedModule {
|
fn make_mock_module(code_str: &str) -> LoadedModule {
|
||||||
let temp_dir = tempdir().expect("Failed to create temporary directory for test.");
|
let temp_dir = tempdir().expect("Failed to create temporary directory for test.");
|
||||||
let temp_file_path_buf =
|
let temp_file_path_buf =
|
||||||
PathBuf::from([Uuid::new_v4().to_string(), ".roc".to_string()].join(""));
|
PathBuf::from([Uuid::new_v4().to_string(), ".roc".to_string()].join(""));
|
||||||
|
@ -74,7 +77,12 @@ main = "Hello, world!"
|
||||||
"Failed to create temporary file for path {:?}",
|
"Failed to create temporary file for path {:?}",
|
||||||
temp_file_full_path
|
temp_file_full_path
|
||||||
));
|
));
|
||||||
writeln!(file, "{}", HELLO_WORLD).expect(&format!(
|
|
||||||
|
let mut full_code_str = HELLO_WORLD.to_owned();
|
||||||
|
full_code_str.push_str("\n\n");
|
||||||
|
full_code_str.push_str(code_str);
|
||||||
|
|
||||||
|
writeln!(file, "{}", full_code_str).expect(&format!(
|
||||||
"Failed to write {:?} to file: {:?}",
|
"Failed to write {:?} to file: {:?}",
|
||||||
HELLO_WORLD, file
|
HELLO_WORLD, file
|
||||||
));
|
));
|
||||||
|
@ -143,16 +151,25 @@ main = "Hello, world!"
|
||||||
#[test]
|
#[test]
|
||||||
fn top_level_def_value() {
|
fn top_level_def_value() {
|
||||||
expect_html_def(
|
expect_html_def(
|
||||||
r#"main = "Hello, World!""#,
|
r#"myFunction = "Hello, World!""#,
|
||||||
"<span class=\"syntax-variable\">main</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-string\">\"Hello, World!\"</span>\n\n",
|
"<span class=\"syntax-value\">myFunction</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-string\">\"Hello, World!\"</span>\n\n",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tld_list() {
|
fn tld_list() {
|
||||||
expect_html_def(
|
expect_html_def(
|
||||||
r#"main = [ 1, 2, 3 ]"#,
|
r#"myFunction = [ 1, 2, 3 ]"#,
|
||||||
"<span class=\"syntax-variable\">main</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-bracket\">[ </span><span class=\"syntax-number\">1</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">2</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">3</span><span class=\"syntax-bracket\"> ]</span>\n\n",
|
"<span class=\"syntax-value\">myFunction</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-bracket\">[ </span><span class=\"syntax-number\">1</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">2</span><span class=\"syntax-comma\">, </span><span class=\"syntax-number\">3</span><span class=\"syntax-bracket\"> ]</span>\n\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function() {
|
||||||
|
expect_html_def(
|
||||||
|
r#"myId = \something ->
|
||||||
|
something"#,
|
||||||
|
"<span class=\"syntax-value\">myId</span><span class=\"syntax-operator\"> = </span><span class=\"syntax-operator\">\\</span><span class=\"syntax-function-arg-name\">something</span><span class=\"syntax-operator\"> -> </span>\n<span class=\"syntax-indent\"> </span><span class=\"syntax-value\">something</span>\n\n",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ use roc_ast::ast_error::ASTError;
|
||||||
use roc_ast::lang::core::ast::ASTNodeId;
|
use roc_ast::lang::core::ast::ASTNodeId;
|
||||||
use roc_code_markup::markup_error::MarkError;
|
use roc_code_markup::markup_error::MarkError;
|
||||||
use roc_code_markup::slow_pool::MarkNodeId;
|
use roc_code_markup::slow_pool::MarkNodeId;
|
||||||
use snafu::{Backtrace, ErrorCompat, NoneError, ResultExt, Snafu};
|
use roc_module::module_err::ModuleError;
|
||||||
|
use snafu::{Backtrace, ErrorCompat, Snafu};
|
||||||
|
|
||||||
//import errors as follows:
|
//import errors as follows:
|
||||||
// `use crate::error::OutOfBounds;`
|
// `use crate::error::OutOfBounds;`
|
||||||
|
@ -253,7 +254,22 @@ pub enum EdError {
|
||||||
msg: String,
|
msg: String,
|
||||||
backtrace: Backtrace,
|
backtrace: Backtrace,
|
||||||
},
|
},
|
||||||
|
WrapASTError {
|
||||||
|
#[snafu(backtrace)]
|
||||||
|
source: ASTError,
|
||||||
|
},
|
||||||
|
WrapUIError {
|
||||||
|
#[snafu(backtrace)]
|
||||||
|
source: UIError,
|
||||||
|
},
|
||||||
|
WrapMarkError {
|
||||||
|
#[snafu(backtrace)]
|
||||||
|
source: MarkError,
|
||||||
|
},
|
||||||
|
WrapModuleError {
|
||||||
|
#[snafu(backtrace)]
|
||||||
|
source: ModuleError,
|
||||||
|
},
|
||||||
WrapIoError {
|
WrapIoError {
|
||||||
source: std::io::Error,
|
source: std::io::Error,
|
||||||
},
|
},
|
||||||
|
@ -320,31 +336,25 @@ use crate::ui::ui_error::UIError;
|
||||||
|
|
||||||
impl From<UIError> for EdError {
|
impl From<UIError> for EdError {
|
||||||
fn from(ui_err: UIError) -> Self {
|
fn from(ui_err: UIError) -> Self {
|
||||||
let msg = format!("{}", ui_err);
|
Self::WrapUIError { source: ui_err }
|
||||||
|
|
||||||
// hack to handle EdError derive
|
|
||||||
let dummy_res: Result<(), NoneError> = Err(NoneError {});
|
|
||||||
dummy_res.context(UIErrorBacktrace { msg }).unwrap_err()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MarkError> for EdError {
|
impl From<MarkError> for EdError {
|
||||||
fn from(mark_err: MarkError) -> Self {
|
fn from(mark_err: MarkError) -> Self {
|
||||||
let msg = format!("{}", mark_err);
|
Self::WrapMarkError { source: mark_err }
|
||||||
|
|
||||||
// hack to handle EdError derive
|
|
||||||
let dummy_res: Result<(), NoneError> = Err(NoneError {});
|
|
||||||
dummy_res.context(MarkErrorBacktrace { msg }).unwrap_err()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ASTError> for EdError {
|
impl From<ASTError> for EdError {
|
||||||
fn from(ast_err: ASTError) -> Self {
|
fn from(ast_err: ASTError) -> Self {
|
||||||
let msg = format!("{}", ast_err);
|
Self::WrapASTError { source: ast_err }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// hack to handle EdError derive
|
impl From<ModuleError> for EdError {
|
||||||
let dummy_res: Result<(), NoneError> = Err(NoneError {});
|
fn from(module_err: ModuleError) -> Self {
|
||||||
dummy_res.context(ASTErrorBacktrace { msg }).unwrap_err()
|
Self::WrapModuleError { source: module_err }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ fn run_event_loop(project_dir_path_opt: Option<&Path>) -> Result<(), Box<dyn Err
|
||||||
|
|
||||||
let window = winit::window::WindowBuilder::new()
|
let window = winit::window::WindowBuilder::new()
|
||||||
.with_inner_size(PhysicalSize::new(1900.0, 1000.0))
|
.with_inner_size(PhysicalSize::new(1900.0, 1000.0))
|
||||||
.with_title("The Roc Editor - very alpha")
|
.with_title("The Roc Editor - Work In Progress")
|
||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,10 @@ use roc_ast::lang::core::ast::{ASTNodeId, AST};
|
||||||
use roc_ast::lang::env::Env;
|
use roc_ast::lang::env::Env;
|
||||||
use roc_ast::mem_pool::pool_str::PoolStr;
|
use roc_ast::mem_pool::pool_str::PoolStr;
|
||||||
use roc_ast::parse::parse_ast;
|
use roc_ast::parse::parse_ast;
|
||||||
use roc_code_markup::markup::nodes::ast_to_mark_nodes;
|
use roc_code_markup::markup::convert::from_ast::ast_to_mark_nodes;
|
||||||
use roc_code_markup::slow_pool::{MarkNodeId, SlowPool};
|
use roc_code_markup::slow_pool::{MarkNodeId, SlowPool};
|
||||||
use roc_load::file::LoadedModule;
|
use roc_load::file::LoadedModule;
|
||||||
|
use roc_module::symbol::Interns;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -55,7 +56,8 @@ pub fn init_model<'a>(
|
||||||
code_arena: &'a Bump,
|
code_arena: &'a Bump,
|
||||||
caret_pos: CaretPos, // to set caret position
|
caret_pos: CaretPos, // to set caret position
|
||||||
) -> EdResult<EdModel<'a>> {
|
) -> EdResult<EdModel<'a>> {
|
||||||
let mut module = EdModule::new(code_str, env, code_arena)?;
|
let mut owned_loaded_module = loaded_module;
|
||||||
|
let mut module = EdModule::new(code_str, env, &mut owned_loaded_module.interns, code_arena)?;
|
||||||
|
|
||||||
let mut mark_node_pool = SlowPool::default();
|
let mut mark_node_pool = SlowPool::default();
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ pub fn init_model<'a>(
|
||||||
&mut module.env,
|
&mut module.env,
|
||||||
&module.ast,
|
&module.ast,
|
||||||
&mut mark_node_pool,
|
&mut mark_node_pool,
|
||||||
&loaded_module.interns,
|
&owned_loaded_module.interns,
|
||||||
)?)
|
)?)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
@ -104,7 +106,7 @@ pub fn init_model<'a>(
|
||||||
has_focus: true,
|
has_focus: true,
|
||||||
caret_w_select_vec: NonEmpty::new((caret, None)),
|
caret_w_select_vec: NonEmpty::new((caret, None)),
|
||||||
selected_block_opt: None,
|
selected_block_opt: None,
|
||||||
loaded_module,
|
loaded_module: owned_loaded_module,
|
||||||
show_debug_view: false,
|
show_debug_view: false,
|
||||||
dirty: true,
|
dirty: true,
|
||||||
})
|
})
|
||||||
|
@ -178,9 +180,14 @@ pub struct EdModule<'a> {
|
||||||
//use crate::lang::ast::expr2_to_string;
|
//use crate::lang::ast::expr2_to_string;
|
||||||
|
|
||||||
impl<'a> EdModule<'a> {
|
impl<'a> EdModule<'a> {
|
||||||
pub fn new(code_str: &'a str, mut env: Env<'a>, ast_arena: &'a Bump) -> EdResult<EdModule<'a>> {
|
pub fn new(
|
||||||
|
code_str: &'a str,
|
||||||
|
mut env: Env<'a>,
|
||||||
|
interns: &mut Interns,
|
||||||
|
ast_arena: &'a Bump,
|
||||||
|
) -> EdResult<EdModule<'a>> {
|
||||||
if !code_str.is_empty() {
|
if !code_str.is_empty() {
|
||||||
let parse_res = parse_ast::parse_from_string(code_str, &mut env, ast_arena);
|
let parse_res = parse_ast::parse_from_string(code_str, &mut env, ast_arena, interns);
|
||||||
|
|
||||||
match parse_res {
|
match parse_res {
|
||||||
Ok(ast) => Ok(EdModule { env, ast }),
|
Ok(ast) => Ok(EdModule { env, ast }),
|
||||||
|
|
|
@ -53,7 +53,6 @@ use roc_code_markup::markup::nodes::MarkupNode;
|
||||||
use roc_code_markup::markup::nodes::EQUALS;
|
use roc_code_markup::markup::nodes::EQUALS;
|
||||||
use roc_code_markup::slow_pool::MarkNodeId;
|
use roc_code_markup::slow_pool::MarkNodeId;
|
||||||
use roc_code_markup::slow_pool::SlowPool;
|
use roc_code_markup::slow_pool::SlowPool;
|
||||||
use roc_code_markup::syntax_highlight::HighlightStyle;
|
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
|
@ -250,6 +249,7 @@ impl<'a> EdModel<'a> {
|
||||||
mark_node_pool: &SlowPool,
|
mark_node_pool: &SlowPool,
|
||||||
) -> UIResult<()> {
|
) -> UIResult<()> {
|
||||||
let mark_node = mark_node_pool.get(mark_node_id);
|
let mark_node = mark_node_pool.get(mark_node_id);
|
||||||
|
|
||||||
let node_newlines = mark_node.get_newlines_at_end();
|
let node_newlines = mark_node.get_newlines_at_end();
|
||||||
|
|
||||||
if mark_node.is_nested() {
|
if mark_node.is_nested() {
|
||||||
|
@ -277,9 +277,7 @@ impl<'a> EdModel<'a> {
|
||||||
code_lines,
|
code_lines,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if node_newlines == 0 {
|
*col_nr += node_content.len();
|
||||||
*col_nr += node_content.len();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if node_newlines > 0 {
|
if node_newlines > 0 {
|
||||||
|
@ -582,7 +580,6 @@ impl<'a> EdModel<'a> {
|
||||||
let blank_replacement = MarkupNode::Blank {
|
let blank_replacement = MarkupNode::Blank {
|
||||||
ast_node_id: sel_block.ast_node_id,
|
ast_node_id: sel_block.ast_node_id,
|
||||||
attributes: Attributes::default(),
|
attributes: Attributes::default(),
|
||||||
syn_high_style: HighlightStyle::Blank,
|
|
||||||
parent_id_opt: expr2_level_mark_node.get_parent_id_opt(),
|
parent_id_opt: expr2_level_mark_node.get_parent_id_opt(),
|
||||||
newlines_at_end,
|
newlines_at_end,
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,7 +66,7 @@ pub fn start_new_let_value(ed_model: &mut EdModel, new_char: &char) -> EdResult<
|
||||||
let val_name_mark_node = MarkupNode::Text {
|
let val_name_mark_node = MarkupNode::Text {
|
||||||
content: val_name_string,
|
content: val_name_string,
|
||||||
ast_node_id,
|
ast_node_id,
|
||||||
syn_high_style: HighlightStyle::Variable,
|
syn_high_style: HighlightStyle::Value,
|
||||||
attributes: Attributes::default(),
|
attributes: Attributes::default(),
|
||||||
parent_id_opt: Some(curr_mark_node_id),
|
parent_id_opt: Some(curr_mark_node_id),
|
||||||
newlines_at_end: curr_mark_node_nls,
|
newlines_at_end: curr_mark_node_nls,
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
use roc_ast::{
|
use roc_ast::lang::{
|
||||||
lang::{
|
core::{ast::ASTNodeId, def::def2::Def2, expr::expr2::Expr2},
|
||||||
core::{
|
env::Env,
|
||||||
ast::ASTNodeId,
|
|
||||||
def::def2::Def2,
|
|
||||||
expr::expr2::Expr2,
|
|
||||||
pattern::{get_identifier_string, Pattern2},
|
|
||||||
},
|
|
||||||
env::Env,
|
|
||||||
},
|
|
||||||
mem_pool::pool::NodeId,
|
|
||||||
};
|
};
|
||||||
use roc_code_markup::{
|
use roc_code_markup::{
|
||||||
markup::{
|
markup::{
|
||||||
|
@ -19,7 +11,7 @@ use roc_code_markup::{
|
||||||
slow_pool::{MarkNodeId, SlowPool},
|
slow_pool::{MarkNodeId, SlowPool},
|
||||||
syntax_highlight::HighlightStyle,
|
syntax_highlight::HighlightStyle,
|
||||||
};
|
};
|
||||||
use roc_module::symbol::{Interns, Symbol};
|
use roc_module::symbol::IdentId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
editor::ed_error::{EdResult, FailedToUpdateIdentIdName, KeyNotFound},
|
editor::ed_error::{EdResult, FailedToUpdateIdentIdName, KeyNotFound},
|
||||||
|
@ -35,20 +27,18 @@ use super::{
|
||||||
// Top Level Defined Value. example: `main = "Hello, World!"`
|
// Top Level Defined Value. example: `main = "Hello, World!"`
|
||||||
|
|
||||||
pub fn tld_mark_node<'a>(
|
pub fn tld_mark_node<'a>(
|
||||||
identifier_id: NodeId<Pattern2>,
|
identifier_id: IdentId,
|
||||||
expr_mark_node_id: MarkNodeId,
|
expr_mark_node_id: MarkNodeId,
|
||||||
ast_node_id: ASTNodeId,
|
ast_node_id: ASTNodeId,
|
||||||
mark_node_pool: &mut SlowPool,
|
mark_node_pool: &mut SlowPool,
|
||||||
env: &Env<'a>,
|
env: &Env<'a>,
|
||||||
interns: &Interns,
|
|
||||||
) -> EdResult<MarkupNode> {
|
) -> EdResult<MarkupNode> {
|
||||||
let pattern2 = env.pool.get(identifier_id);
|
let val_name = env.ident_ids.get_name_str_res(identifier_id)?;
|
||||||
let val_name = get_identifier_string(pattern2, interns)?;
|
|
||||||
|
|
||||||
let val_name_mn = MarkupNode::Text {
|
let val_name_mn = MarkupNode::Text {
|
||||||
content: val_name,
|
content: val_name.to_owned(),
|
||||||
ast_node_id,
|
ast_node_id,
|
||||||
syn_high_style: HighlightStyle::Variable,
|
syn_high_style: HighlightStyle::Value,
|
||||||
attributes: Attributes::default(),
|
attributes: Attributes::default(),
|
||||||
parent_id_opt: None,
|
parent_id_opt: None,
|
||||||
newlines_at_end: 0,
|
newlines_at_end: 0,
|
||||||
|
@ -107,22 +97,16 @@ pub fn start_new_tld_value(ed_model: &mut EdModel, new_char: &char) -> EdResult<
|
||||||
.fail()?
|
.fail()?
|
||||||
}
|
}
|
||||||
|
|
||||||
let val_symbol = Symbol::new(ed_model.module.env.home, ident_id);
|
|
||||||
|
|
||||||
let patt2 = Pattern2::Identifier(val_symbol);
|
|
||||||
let patt2_id = ed_model.module.env.pool.add(patt2);
|
|
||||||
|
|
||||||
let tld_mark_node = tld_mark_node(
|
let tld_mark_node = tld_mark_node(
|
||||||
patt2_id,
|
ident_id,
|
||||||
val_expr_mn_id,
|
val_expr_mn_id,
|
||||||
ast_node_id,
|
ast_node_id,
|
||||||
&mut ed_model.mark_node_pool,
|
&mut ed_model.mark_node_pool,
|
||||||
&ed_model.module.env,
|
&ed_model.module.env,
|
||||||
&ed_model.loaded_module.interns,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let new_ast_node = Def2::ValueDef {
|
let new_ast_node = Def2::ValueDef {
|
||||||
identifier_id: patt2_id,
|
identifier_id: ident_id,
|
||||||
expr_id: val_expr_id,
|
expr_id: val_expr_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::graphics::primitives::text as gr_text;
|
||||||
use cgmath::Vector2;
|
use cgmath::Vector2;
|
||||||
use roc_code_markup::markup::nodes::{MarkupNode, BLANK_PLACEHOLDER};
|
use roc_code_markup::markup::nodes::{MarkupNode, BLANK_PLACEHOLDER};
|
||||||
use roc_code_markup::slow_pool::{MarkNodeId, SlowPool};
|
use roc_code_markup::slow_pool::{MarkNodeId, SlowPool};
|
||||||
|
use roc_code_markup::syntax_highlight::HighlightStyle;
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
|
|
||||||
use crate::{editor::config::Config, graphics::colors};
|
use crate::{editor::config::Config, graphics::colors};
|
||||||
|
@ -147,7 +148,6 @@ fn markup_to_wgpu_helper<'a>(
|
||||||
MarkupNode::Blank {
|
MarkupNode::Blank {
|
||||||
ast_node_id: _,
|
ast_node_id: _,
|
||||||
attributes: _,
|
attributes: _,
|
||||||
syn_high_style,
|
|
||||||
parent_id_opt: _,
|
parent_id_opt: _,
|
||||||
newlines_at_end,
|
newlines_at_end,
|
||||||
} => {
|
} => {
|
||||||
|
@ -157,7 +157,8 @@ fn markup_to_wgpu_helper<'a>(
|
||||||
.with_color(colors::to_slice(colors::WHITE))
|
.with_color(colors::to_slice(colors::WHITE))
|
||||||
.with_scale(code_style.font_size);
|
.with_scale(code_style.font_size);
|
||||||
|
|
||||||
let highlight_color = map_get(&code_style.ed_theme.syntax_high_map, syn_high_style)?;
|
let highlight_color =
|
||||||
|
map_get(&code_style.ed_theme.syntax_high_map, &HighlightStyle::Blank)?;
|
||||||
|
|
||||||
let char_width = code_style.glyph_dim_rect.width;
|
let char_width = code_style.glyph_dim_rect.width;
|
||||||
let char_height = code_style.glyph_dim_rect.height;
|
let char_height = code_style.glyph_dim_rect.height;
|
||||||
|
@ -184,6 +185,17 @@ fn markup_to_wgpu_helper<'a>(
|
||||||
txt_row_col.1 = 0;
|
txt_row_col.1 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MarkupNode::Indent { .. } => {
|
||||||
|
let full_content: String = markup_node.get_content();
|
||||||
|
|
||||||
|
txt_row_col.1 += full_content.len();
|
||||||
|
|
||||||
|
let glyph_text = glyph_brush::OwnedText::new(full_content)
|
||||||
|
.with_color(colors::to_slice(colors::WHITE))
|
||||||
|
.with_scale(code_style.font_size);
|
||||||
|
|
||||||
|
wgpu_texts.push(glyph_text);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue