mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-13 19:06:16 +01:00
early prototype of a language server
currently only provides hover info (but that's already quite useful for debugging)
This commit is contained in:
@@ -112,7 +112,8 @@ impl Config {
|
||||
}
|
||||
}
|
||||
unreachable!("try: no function found")
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
}))
|
||||
.add_var("lock_update".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
@@ -160,7 +161,8 @@ impl Config {
|
||||
let func = func.as_any().downcast_ref::<data::function::Function>().unwrap();
|
||||
*arg = func.run(arg.clone());
|
||||
Data::empty_tuple()
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
}))
|
||||
.add_var("sleep".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
@@ -183,7 +185,8 @@ impl Config {
|
||||
unreachable!("sleep called on non-int/non-float")
|
||||
});
|
||||
Data::empty_tuple()
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
}))
|
||||
.add_var("panic".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
@@ -195,7 +198,8 @@ impl Config {
|
||||
}),
|
||||
run: Arc::new(|a, _i| {
|
||||
std::process::exit(a.get().as_any().downcast_ref::<data::int::Int>().map(|i| i.0 as _).unwrap_or(1));
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
}))
|
||||
.add_var(
|
||||
"len".to_string(),
|
||||
@@ -222,6 +226,7 @@ impl Config {
|
||||
unreachable!("called len on {a:?}, which isn't a tuple or a string")
|
||||
}))
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
).add_var(
|
||||
"loop".to_string(),
|
||||
@@ -270,6 +275,7 @@ impl Config {
|
||||
}
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -303,6 +309,7 @@ impl Config {
|
||||
false
|
||||
}))
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -323,6 +330,7 @@ impl Config {
|
||||
unreachable!("called deref on non-reference")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ impl Config {
|
||||
unreachable!("run_command called with non-tuple argument")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ impl Config {
|
||||
unreachable!("get called with less than 2 args")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ impl Config {
|
||||
unreachable!("for_each called on non-tuple")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -133,6 +134,7 @@ impl Config {
|
||||
Ok(Type::new(IterT::new(ItersT::Enumerate, data)?))
|
||||
}),
|
||||
run: Arc::new(|a, _i| Data::new(Iter(Iters::Enumerate, a.clone()))),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -203,6 +205,7 @@ fn genfunc_iter_and_arg<T: MersType, D: MersData>(
|
||||
unreachable!("{name} called on non-tuple")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,5 +411,6 @@ fn genfunc_iter_in_val_out(
|
||||
}
|
||||
}),
|
||||
run: Arc::new(run),
|
||||
inner_statements: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ impl Config {
|
||||
};
|
||||
o
|
||||
}),
|
||||
inner_statements: None,
|
||||
}))
|
||||
.add_var(
|
||||
"pop".to_string(),
|
||||
@@ -140,6 +141,7 @@ impl Config {
|
||||
None => Data::empty_tuple(),
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -202,6 +204,7 @@ impl Config {
|
||||
.push(Arc::new(RwLock::new(tuple.0[1].clone())));
|
||||
Data::empty_tuple()
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -225,6 +228,7 @@ impl Config {
|
||||
unreachable!("as_list called on non-iterable")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,8 @@ impl Config {
|
||||
} else {
|
||||
Data::empty_tuple()
|
||||
}
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
})).add_var("parse_int".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(program::run::Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@@ -95,7 +96,8 @@ impl Config {
|
||||
} else {
|
||||
Data::empty_tuple()
|
||||
}
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
})).add_var("signum".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(program::run::Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@@ -118,7 +120,8 @@ impl Config {
|
||||
} else { 0
|
||||
}
|
||||
} else { unreachable!("called signum on non-number type")}))
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
})) .add_var("div".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(program::run::Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@@ -137,6 +140,7 @@ impl Config {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else { unreachable!() }),
|
||||
inner_statements: None,
|
||||
})).add_var("modulo".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(program::run::Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@@ -155,6 +159,7 @@ impl Config {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else { unreachable!() }),
|
||||
inner_statements: None,
|
||||
}))
|
||||
.add_var(
|
||||
"sum".to_string(),
|
||||
@@ -215,6 +220,7 @@ impl Config {
|
||||
unreachable!("sum called on non-tuple")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -288,6 +294,7 @@ impl Config {
|
||||
unreachable!("sum called on non-tuple")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -349,6 +356,7 @@ impl Config {
|
||||
unreachable!("product called on non-tuple")
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
@@ -428,6 +436,7 @@ fn ltgtoe_function(
|
||||
}
|
||||
Data::new(data::bool::Bool(true))
|
||||
}),
|
||||
inner_statements: None,
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
@@ -58,6 +58,7 @@ impl Config {
|
||||
unreachable!("thread called, but arg wasn't a function");
|
||||
}
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var("thread_finished".to_string(), Data::new(data::function::Function {
|
||||
@@ -78,7 +79,8 @@ impl Config {
|
||||
Ok(t) => t.is_finished(),
|
||||
Err(_d) => true,
|
||||
}))
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
}))
|
||||
.add_var("thread_await".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(program::run::Info::neverused()),
|
||||
@@ -103,7 +105,8 @@ impl Config {
|
||||
};
|
||||
*t = Err(d.clone());
|
||||
d
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ impl Config {
|
||||
_ = std::io::stdin().read_line(&mut line);
|
||||
Data::new(data::string::String(line))
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -55,6 +56,7 @@ impl Config {
|
||||
eprintln!("{} :: {}", a.as_type(), a);
|
||||
Data::empty_tuple()
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -68,6 +70,7 @@ impl Config {
|
||||
_ = std::io::stderr().lock().flush();
|
||||
Data::empty_tuple()
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -80,6 +83,7 @@ impl Config {
|
||||
eprintln!("{}", a.get());
|
||||
Data::empty_tuple()
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -93,6 +97,7 @@ impl Config {
|
||||
_ = std::io::stdout().lock().flush();
|
||||
Data::empty_tuple()
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
.add_var(
|
||||
@@ -105,6 +110,7 @@ impl Config {
|
||||
println!("{}", a.get());
|
||||
Data::empty_tuple()
|
||||
}),
|
||||
inner_statements: None,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ impl Config {
|
||||
}),
|
||||
run: Arc::new(|a, _i| {
|
||||
Data::new(data::string::String(a.get().as_any().downcast_ref::<data::string::String>().unwrap().0.trim().to_owned()))
|
||||
})
|
||||
}),
|
||||
inner_statements: None,
|
||||
})).add_var("concat".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@@ -35,11 +36,13 @@ impl Config {
|
||||
Err(format!("concat called on non-iterable type {a}").into())
|
||||
}),
|
||||
run: Arc::new(|a, _i| Data::new(data::string::String(a.get().iterable().unwrap().map(|v| v.get().to_string()).collect()))),
|
||||
inner_statements: None,
|
||||
})).add_var("to_string".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
out: Arc::new(|_a, _i| Ok(Type::new(data::string::StringT))),
|
||||
run: Arc::new(|a, _i| Data::new(data::string::String(a.get().to_string()))),
|
||||
inner_statements: None,
|
||||
})).add_var("index_of".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@@ -52,6 +55,7 @@ impl Config {
|
||||
Err(format!("wrong args for index_of: must be (string, string)").into())
|
||||
}),
|
||||
run: Arc::new(|a, _i| index_of(a, false)),
|
||||
inner_statements: None,
|
||||
})).add_var("index_of_rev".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@@ -64,6 +68,7 @@ impl Config {
|
||||
Err(format!("wrong args for index_of: must be (string, string)").into())
|
||||
}),
|
||||
run: Arc::new(|a, _i| index_of(a, true)),
|
||||
inner_statements: None,
|
||||
})).add_var("substring".to_string(), Data::new(data::function::Function {
|
||||
info: Arc::new(Info::neverused()),
|
||||
info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
|
||||
@@ -113,6 +118,7 @@ impl Config {
|
||||
Data::new(data::string::String(s[start..end].to_owned()))
|
||||
|
||||
}),
|
||||
inner_statements: None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,4 +35,10 @@ impl MersStatement for AsType {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![self.statement.as_ref()]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,4 +31,10 @@ impl MersStatement for AssignTo {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![self.source.as_ref(), self.target.as_ref()]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,10 @@ impl MersStatement for Block {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
self.statements.iter().map(|v| v.as_ref()).collect()
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,10 @@ impl MersStatement for Chain {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![self.first.as_ref(), self.chained.as_ref()]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,16 @@ impl MersStatement for CustomType {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
if let Err(s) = &self.source {
|
||||
vec![s.as_ref()]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for CustomType {
|
||||
|
||||
@@ -29,8 +29,10 @@ impl MersStatement for Function {
|
||||
let arg_target = Arc::new(self.arg.compile(info, comp)?);
|
||||
comp.is_init = false;
|
||||
let run = Arc::new(self.run.compile(info, comp)?);
|
||||
let arg2: Arc<Box<dyn crate::program::run::MersStatement>> = Arc::clone(&arg_target);
|
||||
let run2: Arc<Box<dyn crate::program::run::MersStatement>> = Arc::clone(&run);
|
||||
let arg2 = Arc::clone(&arg_target);
|
||||
let run2 = Arc::clone(&run);
|
||||
let arg3 = Arc::clone(&arg_target);
|
||||
let run3 = Arc::clone(&run);
|
||||
Ok(Box::new(program::run::function::Function {
|
||||
pos_in_src: self.pos_in_src.clone(),
|
||||
func_no_info: data::function::Function {
|
||||
@@ -44,10 +46,17 @@ impl MersStatement for Function {
|
||||
data::defs::assign(&arg, &arg_target.run(info));
|
||||
run.run(info)
|
||||
}),
|
||||
inner_statements: Some((arg3, run3)),
|
||||
},
|
||||
}))
|
||||
}
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![self.arg.as_ref(), self.run.as_ref()]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,4 +36,18 @@ impl MersStatement for If {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
if let Some(on_false) = &self.on_false {
|
||||
vec![
|
||||
self.condition.as_ref(),
|
||||
self.on_true.as_ref(),
|
||||
on_false.as_ref(),
|
||||
]
|
||||
} else {
|
||||
vec![self.condition.as_ref(), self.on_true.as_ref()]
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ impl MersStatement for IncludeMers {
|
||||
info_check: Arc::new(Mutex::new(info::Info::neverused())),
|
||||
out: Arc::new(move |_, i| compiled.check(&mut i.duplicate(), None)),
|
||||
run: Arc::new(move |_, i| compiled2.run(&mut i.duplicate())),
|
||||
inner_statements: None,
|
||||
},
|
||||
}),
|
||||
as_part_of_include: Some(self.inner_src.clone()),
|
||||
@@ -66,4 +67,10 @@ impl MersStatement for IncludeMers {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,4 +37,10 @@ impl MersStatement for InitTo {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![self.source.as_ref(), self.target.as_ref()]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
use std::{collections::HashMap, fmt::Debug};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Debug,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
errors::{CheckError, SourceRange},
|
||||
@@ -44,21 +48,53 @@ pub trait MersStatement: Debug + Send + Sync {
|
||||
info: &mut Info,
|
||||
comp: CompInfo,
|
||||
) -> Result<Box<dyn super::run::MersStatement>, CheckError> {
|
||||
info.global.depth += 1;
|
||||
if self.has_scope() {
|
||||
info.create_scope();
|
||||
}
|
||||
let o = self.compile_custom(info, comp);
|
||||
if info.global.enable_hooks {
|
||||
// Hooks - keep in sync with run/mod.rs/compile() hooks section
|
||||
{
|
||||
// `save_info_at` hook
|
||||
let mut save_info_at = info.global.save_info_at.try_lock().unwrap();
|
||||
if !save_info_at.is_empty() {
|
||||
let pos_start = self.source_range().start().pos();
|
||||
let pos_end = self.source_range().end().pos();
|
||||
let cloned_info = Arc::new(info.clone());
|
||||
for (save_to, save_at, deepest_statement) in save_info_at.iter_mut() {
|
||||
if info.global.depth >= *deepest_statement
|
||||
&& pos_start <= *save_at
|
||||
&& *save_at < pos_end
|
||||
{
|
||||
if info.global.depth > *deepest_statement {
|
||||
*deepest_statement = info.global.depth;
|
||||
save_to.clear();
|
||||
}
|
||||
save_to.push((
|
||||
self.source_range(),
|
||||
Arc::clone(&cloned_info),
|
||||
o.as_ref().map(|_| ()).map_err(|e| e.clone()),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.has_scope() {
|
||||
info.end_scope();
|
||||
}
|
||||
info.global.depth -= 1;
|
||||
o
|
||||
}
|
||||
fn source_range(&self) -> SourceRange;
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement>;
|
||||
fn as_any(&self) -> &dyn std::any::Any;
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CompInfo {
|
||||
is_init: bool,
|
||||
pub is_init: bool,
|
||||
}
|
||||
impl Default for CompInfo {
|
||||
fn default() -> Self {
|
||||
@@ -70,13 +106,30 @@ pub type Info = info::Info<Local>;
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct Local {
|
||||
vars: HashMap<String, (usize, usize)>,
|
||||
vars_count: usize,
|
||||
pub vars: HashMap<String, (usize, usize)>,
|
||||
pub vars_count: usize,
|
||||
}
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct LocalGlobalInfo {
|
||||
pub depth: usize,
|
||||
pub enable_hooks: bool,
|
||||
/// ((results, byte_pos_in_src, deepest_statement))
|
||||
/// you only have to set `byte_pos_in_src`. `deepest` is used internally.
|
||||
/// These values should be initialized to `(vec![], _, 0)`, but `0` can be replaced by a minimum statement depth, i.e. `2` to exclude the outer scope (which has depth `1`).
|
||||
pub save_info_at: Arc<
|
||||
Mutex<
|
||||
Vec<(
|
||||
Vec<(SourceRange, Arc<Info>, Result<(), CheckError>)>,
|
||||
usize,
|
||||
usize,
|
||||
)>,
|
||||
>,
|
||||
>,
|
||||
}
|
||||
impl info::Local for Local {
|
||||
type VariableIdentifier = String;
|
||||
type VariableData = (usize, usize);
|
||||
type Global = ();
|
||||
type Global = LocalGlobalInfo;
|
||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
||||
self.vars_count += 1;
|
||||
self.vars.insert(id, value);
|
||||
|
||||
@@ -32,4 +32,10 @@ impl MersStatement for Object {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
self.elems.iter().map(|(_, s)| s.as_ref()).collect()
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,10 @@ impl MersStatement for Tuple {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
self.elems.iter().map(|v| v.as_ref()).collect()
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,10 @@ impl MersStatement for Value {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,4 +59,10 @@ impl MersStatement for Variable {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,4 +75,10 @@ impl MersStatement for AsType {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![self.statement.as_ref()]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,4 +83,10 @@ impl MersStatement for AssignTo {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![self.target.as_ref(), self.source.as_ref()]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,4 +38,10 @@ impl MersStatement for Block {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
self.statements.iter().map(|s| s.as_ref()).collect()
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,4 +101,10 @@ impl MersStatement for Chain {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![self.first.as_ref(), self.chained.as_ref()]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,12 @@ impl MersStatement for CustomType {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for CustomType {
|
||||
|
||||
@@ -34,4 +34,14 @@ impl MersStatement for Function {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
if let Some((a, b)) = &self.func_no_info.inner_statements {
|
||||
vec![a.as_ref().as_ref(), b.as_ref().as_ref()]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,4 +73,18 @@ impl MersStatement for If {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
if let Some(on_false) = &self.on_false {
|
||||
vec![
|
||||
self.condition.as_ref(),
|
||||
self.on_true.as_ref(),
|
||||
on_false.as_ref(),
|
||||
]
|
||||
} else {
|
||||
vec![self.condition.as_ref(), self.on_true.as_ref()]
|
||||
}
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Debug,
|
||||
sync::{Arc, RwLock},
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -43,13 +43,50 @@ pub trait MersStatement: Debug + Send + Sync {
|
||||
/// if true, local variables etc. will be contained inside their own scope.
|
||||
fn has_scope(&self) -> bool;
|
||||
fn check(&self, info: &mut CheckInfo, assign: Option<&Type>) -> Result<Type, CheckError> {
|
||||
info.global.depth += 1;
|
||||
if self.has_scope() {
|
||||
info.create_scope();
|
||||
}
|
||||
let o = self.check_custom(info, assign);
|
||||
if info.global.enable_hooks {
|
||||
// Hooks - keep in sync with run/mod.rs/compile() hooks section
|
||||
'hook_save_info_at: {
|
||||
// `save_info_at` hook
|
||||
let mut save_info_at = if let Ok(lock) = info.global.save_info_at.try_lock() {
|
||||
lock
|
||||
} else {
|
||||
eprintln!(
|
||||
"[HOOKS/save_info_at] couldn't acquire lock - result may be incomplete"
|
||||
);
|
||||
break 'hook_save_info_at;
|
||||
};
|
||||
if !save_info_at.is_empty() {
|
||||
let pos_start = self.source_range().start().pos();
|
||||
let pos_end = self.source_range().end().pos();
|
||||
let cloned_info = Arc::new(info.clone());
|
||||
for (save_to, save_at, deepest_statement) in save_info_at.iter_mut() {
|
||||
if info.global.depth >= *deepest_statement
|
||||
&& pos_start <= *save_at
|
||||
&& *save_at < pos_end
|
||||
{
|
||||
if info.global.depth > *deepest_statement {
|
||||
*deepest_statement = info.global.depth;
|
||||
save_to.clear();
|
||||
}
|
||||
save_to.push((
|
||||
self.source_range(),
|
||||
Arc::clone(&cloned_info),
|
||||
o.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.has_scope() {
|
||||
info.end_scope();
|
||||
}
|
||||
info.global.depth -= 1;
|
||||
o
|
||||
}
|
||||
fn run(&self, info: &mut Info) -> Data {
|
||||
@@ -63,6 +100,8 @@ pub trait MersStatement: Debug + Send + Sync {
|
||||
o
|
||||
}
|
||||
fn source_range(&self) -> SourceRange;
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement>;
|
||||
fn as_any(&self) -> &dyn std::any::Any;
|
||||
}
|
||||
|
||||
pub type Info = info::Info<Local>;
|
||||
@@ -70,11 +109,11 @@ pub type CheckInfo = info::Info<CheckLocal>;
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct Local {
|
||||
vars: Vec<Arc<RwLock<Data>>>,
|
||||
pub vars: Vec<Arc<RwLock<Data>>>,
|
||||
}
|
||||
#[derive(Default, Clone)]
|
||||
pub struct CheckLocal {
|
||||
vars: Vec<Type>,
|
||||
pub vars: Vec<Type>,
|
||||
pub types: HashMap<
|
||||
String,
|
||||
Result<
|
||||
@@ -83,6 +122,23 @@ pub struct CheckLocal {
|
||||
>,
|
||||
>,
|
||||
}
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct CheckLocalGlobalInfo {
|
||||
pub depth: usize,
|
||||
pub enable_hooks: bool,
|
||||
/// ((results, byte_pos_in_src, deepest_statement))
|
||||
/// you only have to set `byte_pos_in_src`. `deepest` is used internally.
|
||||
/// These values should be initialized to `(vec![], _, 0)`, but `0` can be replaced by a minimum statement depth, i.e. `2` to exclude the outer scope (which has depth `1`).
|
||||
pub save_info_at: Arc<
|
||||
Mutex<
|
||||
Vec<(
|
||||
Vec<(SourceRange, Arc<CheckInfo>, Result<Type, CheckError>)>,
|
||||
usize,
|
||||
usize,
|
||||
)>,
|
||||
>,
|
||||
>,
|
||||
}
|
||||
impl Debug for CheckLocal {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "CheckLocal {:?}, {:?}", self.vars, self.types.keys())
|
||||
@@ -124,7 +180,7 @@ impl info::Local for Local {
|
||||
impl info::Local for CheckLocal {
|
||||
type VariableIdentifier = usize;
|
||||
type VariableData = Type;
|
||||
type Global = ();
|
||||
type Global = CheckLocalGlobalInfo;
|
||||
fn init_var(&mut self, id: Self::VariableIdentifier, value: Self::VariableData) {
|
||||
while self.vars.len() <= id {
|
||||
self.vars.push(Type::empty());
|
||||
|
||||
@@ -133,4 +133,10 @@ impl MersStatement for Object {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
self.elems.iter().map(|(_, s)| s.as_ref()).collect()
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,4 +93,10 @@ impl MersStatement for Tuple {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
self.elems.iter().map(|s| s.as_ref()).collect()
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,4 +31,10 @@ impl MersStatement for Value {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,4 +79,10 @@ impl MersStatement for Variable {
|
||||
fn source_range(&self) -> SourceRange {
|
||||
self.pos_in_src.clone()
|
||||
}
|
||||
fn inner_statements(&self) -> Vec<&dyn MersStatement> {
|
||||
vec![]
|
||||
}
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user