fix "weird" behavior with globalinfo not updating

This commit is contained in:
Mark 2024-10-14 01:52:19 +02:00
parent 8868746e17
commit f979100bfb
17 changed files with 147 additions and 86 deletions

View File

@ -15,7 +15,7 @@ default = ["colored-output"]
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
[dependencies]
mers_lib = "0.9.10"
mers_lib = "0.9.12"
# mers_lib = { path = "../mers_lib" }
clap = { version = "4.3.19", features = ["derive"] }
colored = { version = "2.1.0", optional = true }

View File

@ -1,6 +1,6 @@
[package]
name = "mers_lib"
version = "0.9.12"
version = "0.9.13"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "library to use the mers language in other projects"

View File

@ -8,7 +8,7 @@ use mers_lib::{
};
fn main() -> Result<(), CheckError> {
let (_, func) = parse_compile_check_run(
let (_, func, info) = parse_compile_check_run(
// The `[(String -> String)]` type annotation ensures that decorate.mers returns a `String -> String` function.
"[(String -> String)] #include \"examples/decorate.mers\"".to_owned(),
)?;
@ -23,7 +23,10 @@ fn main() -> Result<(), CheckError> {
// use the function to decorate these 3 test strings
for input in ["my test string", "Main Menu", "O.o"] {
let result = func.run_immut(Data::new(data::string::String(input.to_owned())))?;
let result = func.run_immut(
Data::new(data::string::String(input.to_owned())),
info.global.clone(),
)?;
let result = result.get();
let result = &result
.as_any()
@ -37,7 +40,9 @@ fn main() -> Result<(), CheckError> {
}
/// example 00
fn parse_compile_check_run(src: String) -> Result<(Type, Data), CheckError> {
fn parse_compile_check_run(
src: String,
) -> Result<(Type, Data, mers_lib::program::run::Info), CheckError> {
let mut source = Source::new_from_string(src);
let srca = Arc::new(source.clone());
let parsed = parse(&mut source, &srca)?;
@ -45,5 +50,5 @@ fn parse_compile_check_run(src: String) -> Result<(Type, Data), CheckError> {
let compiled = parsed.compile(&mut i1, CompInfo::default())?;
let output_type = compiled.check(&mut i3, None)?;
let output_value = compiled.run(&mut i2)?;
Ok((output_type, output_value))
Ok((output_type, output_value, i2))
}

View File

@ -80,11 +80,25 @@ impl Function {
pub fn check(&self, arg: &Type) -> Result<Type, CheckError> {
self.get_as_type().o(arg)
}
pub fn run_mut(&mut self, arg: Data) -> Result<Data, CheckError> {
pub fn run_mut(
&mut self,
arg: Data,
gi: crate::program::run::RunLocalGlobalInfo,
) -> Result<Data, CheckError> {
self.info.global = gi;
self.run_mut_with_prev_gi(arg)
}
pub fn run_mut_with_prev_gi(&mut self, arg: Data) -> Result<Data, CheckError> {
(self.run)(arg, &mut self.info)
}
pub fn run_immut(&self, arg: Data) -> Result<Data, CheckError> {
(self.run)(arg, &mut self.info.duplicate())
pub fn run_immut(
&self,
arg: Data,
gi: crate::program::run::RunLocalGlobalInfo,
) -> Result<Data, CheckError> {
let mut i = self.info.duplicate();
i.global = gi;
(self.run)(arg, &mut i)
}
pub fn get_as_type(&self) -> FunctionT {
let info = self.info_check.lock().unwrap().clone();
@ -114,13 +128,25 @@ impl MersData for Function {
fn executable(&self) -> Option<crate::data::function::FunctionT> {
Some(self.get_as_type())
}
fn execute(&self, arg: Data) -> Option<Result<Data, CheckError>> {
Some(self.run_immut(arg))
fn execute(
&self,
arg: Data,
gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Result<Data, CheckError>> {
Some(self.run_immut(arg, gi.clone()))
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
fn iterable(
&self,
gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
let mut s = Clone::clone(self);
let mut gi = Some(gi.clone());
Some(Box::new(std::iter::from_fn(move || {
match s.run_mut(Data::empty_tuple()) {
match if let Some(gi) = gi.take() {
s.run_mut(Data::empty_tuple(), gi)
} else {
s.run_mut_with_prev_gi(Data::empty_tuple())
} {
Err(e) => Some(Err(e)),
Ok(v) => {
if let Some(v) = v.one_tuple_content() {

View File

@ -30,16 +30,28 @@ pub trait MersData: Any + Debug + Send + Sync {
None
}
#[allow(unused_variables)]
fn execute(&self, arg: Data) -> Option<Result<Data, CheckError>> {
fn execute(
&self,
arg: Data,
gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Result<Data, CheckError>> {
None
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
#[allow(unused_variables)]
fn iterable(
&self,
gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
None
}
/// By default, uses `iterable` to get an iterator and `nth` to retrieve the nth element.
/// Should have a custom implementation for better performance on most types
fn get(&self, i: usize) -> Option<Result<Data, CheckError>> {
self.iterable()?.nth(i)
fn get(
&self,
i: usize,
gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Result<Data, CheckError>> {
self.iterable(gi)?.nth(i)
}
/// If self and other are different types (`other.as_any().downcast_ref::<Self>().is_none()`),
/// this *must* return false.

View File

@ -27,7 +27,11 @@ impl MersData for Reference {
None
}
}
fn execute(&self, arg: Data) -> Option<Result<Data, CheckError>> {
fn execute(
&self,
arg: Data,
gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Result<Data, CheckError>> {
let mut inner = self.0.write().unwrap();
let mut inner = inner.get_mut();
if let Some(func) = inner
@ -35,13 +39,17 @@ impl MersData for Reference {
.mut_any()
.downcast_mut::<crate::data::function::Function>()
{
Some(func.run_mut(arg))
Some(func.run_mut(arg, gi.clone()))
} else {
None
}
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
fn iterable(
&self,
gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
let inner = Arc::clone(&self.0);
let gi = gi.clone();
Some(Box::new(std::iter::from_fn(move || {
match inner
.write()
@ -50,7 +58,7 @@ impl MersData for Reference {
.mut_any()
.downcast_mut::<crate::data::function::Function>()
.unwrap()
.run_mut(Data::empty_tuple())
.run_mut(Data::empty_tuple(), gi.clone())
{
Err(e) => Some(Err(e)),
Ok(v) => {

View File

@ -35,7 +35,10 @@ impl MersData for Tuple {
false
}
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
fn iterable(
&self,
_gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
Some(Box::new(self.0.clone().into_iter().map(Ok)))
}
fn clone(&self) -> Box<dyn MersData> {

View File

@ -63,14 +63,14 @@ impl Config {
}
Ok(Type::empty_tuple())
})),
run: Arc::new(|a, _i| {
run: Arc::new(|a, i| {
let a = a.get();
let a = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let arg_ref = a.0[0].get();
let arg_ref = arg_ref.as_any().downcast_ref::<data::reference::Reference>().unwrap();
let mut arg = arg_ref.0.write().unwrap();
let func = a.0[1].get();
*arg = func.execute(arg.clone()).unwrap()?;
*arg = func.execute(arg.clone(), &i.global).unwrap()?;
Ok(Data::empty_tuple())
}),
inner_statements: None,
@ -103,12 +103,12 @@ impl Config {
}
Ok(Type::new(data::int::IntT(0, INT_MAX)))
})),
run: Arc::new(|a, _i| {
run: Arc::new(|a, i| {
Ok(Data::new(data::int::Int(if let Some(t) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
t.0.len().try_into().unwrap_or(INT_MAX)
} else if let Some(s) = a.get().as_any().downcast_ref::<data::string::String>() {
s.0.len().try_into().unwrap_or(INT_MAX)
} else if let Some(i) = a.get().iterable() {
} else if let Some(i) = a.get().iterable(&i.global) {
i.count().try_into().unwrap_or(INT_MAX)
} else {
return Err("called len on {a:?}, which isn't a tuple, a string, or something iterable.".into());
@ -130,8 +130,8 @@ impl Config {
}
Ok(bool_type())
})),
run: Arc::new(|a, _i| {
Ok(Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable() {
run: Arc::new(|a, i| {
Ok(Data::new(data::bool::Bool(if let Some(mut i) = a.get().iterable(&i.global) {
if let Some(f) = i.next() {
let f = f?;
let mut o = true;

View File

@ -12,7 +12,6 @@ use crate::{
object::ObjectFieldsMap,
Data, MersData, MersDataWInfo, MersType, Type,
},
errors::CheckError,
info::DisplayInfo,
program::{self, run::CheckInfo},
};
@ -56,7 +55,7 @@ impl Config {
let cmd = cmd.get();
let (cmd, args) = (
cmd.as_any().downcast_ref::<data::string::String>().unwrap(),
args.get().iterable().unwrap(),
args.get().iterable(&i.global).unwrap(),
);
let args = args.map(|v| v.map(|v| v.get().with_info(i).to_string())).collect::<Result<Vec<_>, _>>()?;
match Command::new(&cmd.0)
@ -107,7 +106,7 @@ impl Config {
let cmd = cmd.get();
let (cmd, args) = (
cmd.as_any().downcast_ref::<data::string::String>().unwrap(),
args.get().iterable().unwrap(),
args.get().iterable(&i.global).unwrap(),
);
let args = args.map(|v| v.map(|v| v.get().with_info(i).to_string())).collect::<Result<Vec<_>, _>>()?;
match Command::new(&cmd.0)
@ -203,14 +202,14 @@ impl Config {
return Err(format!("childproc_write_bytes called on non-`(ChildProcess, Iter<Byte>)` type {}", a.with_info(i)).into());
}
})),
run: Arc::new(|a, _i| {
run: Arc::new(|a, i| {
let a = a.get();
let tuple = a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap();
let child = tuple.0[0].get();
let bytes = tuple.0[1].get();
let child = child.as_any().downcast_ref::<ChildProcess>().unwrap();
let mut child = child.0.lock().unwrap();
let buf = bytes.iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::byte::Byte>().unwrap().0)).collect::<Result<Vec<_>, _>>()?;
let buf = bytes.iterable(&i.global).unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::byte::Byte>().unwrap().0)).collect::<Result<Vec<_>, _>>()?;
Ok(if child.1.as_mut().is_some_and(|v| v.write_all(&buf).is_ok() && v.flush().is_ok()) {
Data::new(data::bool::Bool(true))
} else {
@ -385,12 +384,6 @@ impl MersData for ChildProcess {
fn display(&self, _info: &DisplayInfo<'_>, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{self}")
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
None
}
fn get(&self, _i: usize) -> Option<Result<Data, CheckError>> {
None
}
fn is_eq(&self, other: &dyn MersData) -> bool {
other
.as_any()

View File

@ -50,14 +50,14 @@ impl Config {
Arc::new(data::tuple::TupleT(vec![])),
]))
})),
run: Arc::new(|a, _i| {
run: Arc::new(|a, i| {
let a = a.get();
if let (Some(v), Some(i)) = (a.get(0), a.get(1)) {
let (v, i2) = (v?, i?);
let o = if let Some(i3) = i2.get().as_any().downcast_ref::<data::int::Int>()
if let (Some(v), Some(x)) = (a.get(0, &i.global), a.get(1, &i.global)) {
let (v, x2) = (v?, x?);
let o = if let Some(x3) = x2.get().as_any().downcast_ref::<data::int::Int>()
{
if let Ok(i) = i3.0.try_into() {
if let Some(v) = v.get().get(i) {
if let Ok(x) = x3.0.try_into() {
if let Some(v) = v.get().get(x, &i.global) {
Ok(Data::one_tuple(v?))
} else {
Ok(Data::empty_tuple())

View File

@ -30,16 +30,16 @@ impl Config {
/// `all: fn` returns true if all elements of the iterator are true
pub fn with_iters(self) -> Self {
self
.add_var("any", genfunc_iter_in_val_out("all".to_string(), data::bool::bool_type(), data::bool::bool_type(), |a, _i| {
for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) {
.add_var("any", genfunc_iter_in_val_out("all".to_string(), data::bool::bool_type(), data::bool::bool_type(), |a, i| {
for v in a.get().iterable(&i.global).unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) {
if v? {
return Ok(Data::new(data::bool::Bool(true)));
}
}
Ok(Data::new(data::bool::Bool(false)))
}))
.add_var("all", genfunc_iter_in_val_out("all".to_string(), data::bool::bool_type(), data::bool::bool_type(), |a, _i| {
for v in a.get().iterable().unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) {
.add_var("all", genfunc_iter_in_val_out("all".to_string(), data::bool::bool_type(), data::bool::bool_type(), |a, i| {
for v in a.get().iterable(&i.global).unwrap().map(|v| v.map(|v| v.get().as_any().downcast_ref::<data::bool::Bool>().is_some_and(|v| v.0))) {
if !v? {
return Ok(Data::new(data::bool::Bool(false)));
}
@ -88,13 +88,13 @@ impl Config {
}
Ok(Type::empty_tuple())
})),
run: Arc::new(|a, _i| {
run: Arc::new(|a, i| {
if let Some(tuple) = a.get().as_any().downcast_ref::<data::tuple::Tuple>() {
if let (Some(v), Some(f)) = (tuple.get(0), tuple.get(1)) {
if let Some(iter) = v.get().iterable() {
if let Some(iter) = v.get().iterable(&i.global) {
let f = f.get();
for v in iter {
f.execute(v?).unwrap()?;
f.execute(v?, &i.global).unwrap()?;
}
Ok(Data::empty_tuple())
} else {
@ -319,21 +319,25 @@ impl MersData for Iter {
fn is_eq(&self, _other: &dyn MersData) -> bool {
false
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
fn iterable(
&self,
gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
let gi = gi.clone();
Some(match &self.0 {
Iters::Map(f) => {
let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.map(move |v| {
Box::new(self.1.get().iterable(&gi)?.map(move |v| {
f.get()
.execute(v?)
.execute(v?, &gi)
.ok_or_else(|| CheckError::from("called map with non-function argument"))?
}))
}
Iters::Filter(f) => {
let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.filter_map(move |v| {
Box::new(self.1.get().iterable(&gi)?.filter_map(move |v| {
match v {
Ok(v) => match f.get().execute(v.clone()) {
Ok(v) => match f.get().execute(v.clone(), &gi) {
Some(Ok(f)) => {
if f.get()
.as_any()
@ -356,8 +360,8 @@ impl MersData for Iter {
}
Iters::FilterMap(f) => {
let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.filter_map(move |v| match v {
Ok(v) => match f.get().execute(v) {
Box::new(self.1.get().iterable(&gi)?.filter_map(move |v| match v {
Ok(v) => match f.get().execute(v, &gi) {
Some(Ok(r)) => Some(Ok(r.one_tuple_content()?)),
Some(Err(e)) => Some(Err(e)),
None => Some(Err(CheckError::from(
@ -369,8 +373,8 @@ impl MersData for Iter {
}
Iters::MapWhile(f) => {
let f = Clone::clone(f);
Box::new(self.1.get().iterable()?.map_while(move |v| match v {
Ok(v) => match f.get().execute(v) {
Box::new(self.1.get().iterable(&gi)?.map_while(move |v| match v {
Ok(v) => match f.get().execute(v, &gi) {
Some(Ok(r)) => Some(Ok(r.one_tuple_content()?)),
Some(Err(e)) => Some(Err(e)),
None => Some(Err(CheckError::from(
@ -380,22 +384,28 @@ impl MersData for Iter {
Err(e) => Some(Err(e)),
}))
}
Iters::Take(limit) => Box::new(self.1.get().iterable()?.take(*limit)),
Iters::Take(limit) => Box::new(self.1.get().iterable(&gi)?.take(*limit)),
Iters::Enumerate => {
Box::new(self.1.get().iterable()?.enumerate().map(|(i, v)| match v {
Ok(v) => Ok(Data::new(data::tuple::Tuple(vec![
Data::new(data::int::Int(i as _)),
v,
]))),
Err(e) => Err(e),
}))
Box::new(
self.1
.get()
.iterable(&gi)?
.enumerate()
.map(|(i, v)| match v {
Ok(v) => Ok(Data::new(data::tuple::Tuple(vec![
Data::new(data::int::Int(i as _)),
v,
]))),
Err(e) => Err(e),
}),
)
}
Iters::Chained => {
match self
.1
.get()
.iterable()?
.map(|v| Ok(v?.get().iterable()))
.iterable(&gi)?
.map(move |v| Ok(v?.get().iterable(&gi)))
.collect::<Result<Option<Vec<_>>, CheckError>>()
{
Ok(Some(iters)) => Box::new(iters.into_iter().flatten()),

View File

@ -221,9 +221,9 @@ impl Config {
).into())
}
})),
run: Arc::new(|a, _i| {
if let Some(i) = a.get().iterable() {
Ok(Data::new(List(i.map(|v| Ok::<_, CheckError>(Arc::new(RwLock::new(v?)))).collect::<Result<_, _>>()?)))
run: Arc::new(|a, i| {
if let Some(iter) = a.get().iterable(&i.global) {
Ok(Data::new(List(iter.map(|v| Ok::<_, CheckError>(Arc::new(RwLock::new(v?)))).collect::<Result<_, _>>()?)))
} else {
Err("as_list called on non-iterable".into())
}
@ -272,7 +272,10 @@ impl MersData for List {
false
}
}
fn iterable(&self) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
fn iterable(
&self,
_gi: &crate::program::run::RunLocalGlobalInfo,
) -> Option<Box<dyn Iterator<Item = Result<Data, CheckError>>>> {
Some(Box::new(
self.0
.clone()

View File

@ -501,10 +501,10 @@ impl Config {
}
Ok(o)
},
|a, _| {
|a, i| {
let mut min_int = None;
let mut min_float = None;
for a in a.get().iterable().expect("called `min` on non-itereable") {
for a in a.get().iterable(&i.global).expect("called `min` on non-itereable") {
let a = a?;
let a = a.get();
let a = a.as_any().downcast_ref::<data::int::Int>().map(|v| Ok(v.0)).or_else(|| a.as_any().downcast_ref::<data::float::Float>().map(|v| Err(v.0))).expect("found non-Int/Float element in argument to `min`");
@ -581,10 +581,10 @@ impl Config {
}
Ok(o)
},
|a, _| {
|a, i| {
let mut min_int = None;
let mut min_float = None;
for a in a.get().iterable().expect("called `min` on non-itereable") {
for a in a.get().iterable(&i.global).expect("called `min` on non-itereable") {
let a = a?;
let a = a.get();
let a = a.as_any().downcast_ref::<data::int::Int>().map(|v| Ok(v.0)).or_else(|| a.as_any().downcast_ref::<data::float::Float>().map(|v| Err(v.0))).expect("found non-Int/Float element in argument to `min`");
@ -796,7 +796,7 @@ fn func_math_op(
}
Ok(o)
},
move |a, _| {
move |a, i| {
let a = a.get();
Ok(
if let Some(a) = &a
@ -839,7 +839,7 @@ fn func_math_op(
let (mut acc, _) = iter_version
.expect("no iter version for this math op, but argument not a 2-tuple...");
for a in a
.iterable()
.iterable(&i.global)
.expect("math op with iter version called on non-iterable")
{
let a = a?;

View File

@ -47,9 +47,10 @@ impl Config {
}
Ok(Type::new(ThreadT(out)))
})),
run: Arc::new(|a, _i| {
run: Arc::new(|a, i| {
let gi = i.global.clone();
Ok(Data::new(Thread(Arc::new(Mutex::new(Ok(std::thread::spawn(
move || a.get().execute(Data::empty_tuple()).unwrap(),
move || a.get().execute(Data::empty_tuple(), &gi).unwrap(),
)))))))
}),
inner_statements: None,

View File

@ -81,7 +81,7 @@ impl Config {
|a, i| {
Ok(Data::new(data::string::String(
a.get()
.iterable()
.iterable(&i.global)
.unwrap()
.map(|v| v.map(|v| v.get().with_info(i).to_string()))
.collect::<Result<_, _>>()?,

View File

@ -92,7 +92,7 @@ impl MersStatement for Chain {
let f = self.first.run(info)?;
let c = self.chained.run(info)?;
let c = c.get();
match c.execute(f) {
match c.execute(f, &info.global) {
Some(Ok(v)) => Ok(v),
Some(Err(e)) => Err(if let Some(_) = &self.as_part_of_include {
CheckError::new().err_with_diff_src(e).src(vec![(

View File

@ -116,7 +116,7 @@ impl MersStatement for Try {
match func.executable().map(|func| func.o(&arg_type)) {
Some(Ok(_)) => {
drop(ar);
return func.execute(arg).unwrap();
return func.execute(arg, &info.global).unwrap();
}
None | Some(Err(_)) => (),
}