From 8bafe5859354353b7e0500039d8fcb4bb69c575d Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 29 Apr 2023 16:35:25 +0200 Subject: [PATCH] safety commit because i want to try cargo fix --- iterators.mers | 0 mers/src/interactive_mode.rs | 0 mers/src/lib.rs | 0 mers/src/parse/parse.rs | 33 +++++----- mers/src/script/builtins.rs | 28 ++++----- mers/src/script/code_macro.rs | 0 mers/src/script/code_parsed.rs | 10 +-- mers/src/script/code_runnable.rs | 53 ++++++++-------- mers/src/script/global_info.rs | 36 ++++++++++- mers/src/script/to_runnable.rs | 104 +++++++++---------------------- mers/src/script/val_data.rs | 8 +-- mers/src/script/val_type.rs | 62 ++++++++++-------- mers/src/tutor/base_comments.rs | 0 mers/src/tutor/base_functions.rs | 0 mers/src/tutor/base_return.rs | 0 mers/src/tutor/base_types.rs | 0 mers/src/tutor/base_values.rs | 0 mers/src/tutor/base_variables.rs | 0 mers/src/tutor/error_handling.rs | 0 mers/src/tutor/menu.rs | 0 mers/src/tutor/mod.rs | 0 mersrandr.mers | 0 my_macro.mers | 0 23 files changed, 167 insertions(+), 167 deletions(-) mode change 100644 => 100755 iterators.mers mode change 100644 => 100755 mers/src/interactive_mode.rs mode change 100644 => 100755 mers/src/lib.rs mode change 100644 => 100755 mers/src/script/code_macro.rs mode change 100644 => 100755 mers/src/script/code_parsed.rs mode change 100644 => 100755 mers/src/script/code_runnable.rs mode change 100644 => 100755 mers/src/script/global_info.rs mode change 100644 => 100755 mers/src/script/to_runnable.rs mode change 100644 => 100755 mers/src/tutor/base_comments.rs mode change 100644 => 100755 mers/src/tutor/base_functions.rs mode change 100644 => 100755 mers/src/tutor/base_return.rs mode change 100644 => 100755 mers/src/tutor/base_types.rs mode change 100644 => 100755 mers/src/tutor/base_values.rs mode change 100644 => 100755 mers/src/tutor/base_variables.rs mode change 100644 => 100755 mers/src/tutor/error_handling.rs mode change 100644 => 100755 mers/src/tutor/menu.rs mode change 100644 => 100755 mers/src/tutor/mod.rs mode change 100644 => 100755 mersrandr.mers mode change 100644 => 100755 my_macro.mers diff --git a/iterators.mers b/iterators.mers old mode 100644 new mode 100755 diff --git a/mers/src/interactive_mode.rs b/mers/src/interactive_mode.rs old mode 100644 new mode 100755 diff --git a/mers/src/lib.rs b/mers/src/lib.rs old mode 100644 new mode 100755 diff --git a/mers/src/parse/parse.rs b/mers/src/parse/parse.rs index 1b8bb70..fcb795b 100755 --- a/mers/src/parse/parse.rs +++ b/mers/src/parse/parse.rs @@ -6,8 +6,8 @@ use crate::{ code_macro::MacroError, code_parsed::*, code_runnable::RScript, - global_info::GSInfo, - to_runnable::{self, GInfo, ToRunnableError}, + global_info::{GlobalScriptInfo}, + to_runnable::{self, ToRunnableError}, val_data::VDataEnum, val_type::{VSingleType, VType}, }, @@ -74,7 +74,7 @@ pub const PARSE_VERSION: u64 = 0; /// executes the 4 parse_steps in order: lib_paths => interpret => libs_load => compile pub fn parse(file: &mut File) -> Result { - let mut ginfo = GInfo::default(); + let mut ginfo = GlobalScriptInfo::default(); let libs = parse_step_lib_paths(file)?; let func = parse_step_interpret(file)?; ginfo.libs = parse_step_libs_load(libs, &mut ginfo)?; @@ -135,7 +135,7 @@ impl std::fmt::Display for UnableToLoadLibrary { } pub fn parse_step_libs_load( lib_cmds: Vec, - ginfo: &mut GInfo, + ginfo: &mut GlobalScriptInfo, ) -> Result, UnableToLoadLibrary> { let mut libs = vec![]; for cmd in lib_cmds { @@ -153,7 +153,7 @@ pub fn parse_step_libs_load( Ok(libs) } -pub fn parse_step_compile(main_func: SFunction, ginfo: GInfo) -> Result { +pub fn parse_step_compile(main_func: SFunction, ginfo: GlobalScriptInfo) -> Result { to_runnable::to_runnable(main_func, ginfo) } @@ -177,7 +177,7 @@ pub struct ParseError { String, Option<(super::file::FilePosition, Option)>, )>, - info: Option, + info: Option, } impl ParseError { pub fn fmt_custom( @@ -246,7 +246,7 @@ impl ParseErrors { fn fmtgs( &self, f: &mut std::fmt::Formatter, - info: Option<&GSInfo>, + info: Option<&GlobalScriptInfo>, file: Option<&super::file::File>, ) -> std::fmt::Result { match self { @@ -1150,15 +1150,16 @@ pub mod implementation { "int" => VSingleType::Int, "float" => VSingleType::Float, "string" => VSingleType::String, - _ => { - return Err(ParseError { - err: ParseErrors::InvalidType(name.trim().to_string()), - location: err_start_of_single_type, - location_end: Some(*file.get_pos()), - context: vec![], - info: None, - }); - } + custom => VSingleType::CustomTypeS(custom.to_owned()), + // _ => { + // return Err(ParseError { + // err: ParseErrors::InvalidType(name.trim().to_string()), + // location: err_start_of_single_type, + // location_end: Some(*file.get_pos()), + // context: vec![], + // info: None, + // }); + // } } } None => { diff --git a/mers/src/script/builtins.rs b/mers/src/script/builtins.rs index 207c076..791ecdd 100755 --- a/mers/src/script/builtins.rs +++ b/mers/src/script/builtins.rs @@ -8,7 +8,7 @@ use crate::libs; use super::{ code_runnable::RStatement, - global_info::GSInfo, + global_info::{GlobalScriptInfo, GSInfo}, val_data::{thread::VDataThreadEnum, VData, VDataEnum}, val_type::{VSingleType, VType}, }; @@ -148,7 +148,7 @@ impl BuiltinFunction { _ => return None, }) } - pub fn can_take(&self, input: &Vec) -> bool { + pub fn can_take(&self, input: &Vec, info: &GlobalScriptInfo) -> bool { match self { Self::Assume1 => { if input.len() >= 1 { @@ -172,7 +172,7 @@ impl BuiltinFunction { } if input.len() >= 2 { if input.len() == 2 { - input[1].fits_in(&VSingleType::String.to()).is_empty() + input[1].fits_in(&VSingleType::String.to(), info).is_empty() } else { false } @@ -203,7 +203,7 @@ impl BuiltinFunction { } if input.len() >= 2 { if input.len() == 2 { - input[1].fits_in(&VSingleType::String.to()).is_empty() + input[1].fits_in(&VSingleType::String.to(), info).is_empty() } else { false } @@ -219,7 +219,7 @@ impl BuiltinFunction { Self::Clone => input.len() == 1 && matches!(input[0].is_reference(), Some(true)), Self::Print | Self::Println => { if input.len() == 1 { - input[0].fits_in(&VSingleType::String.to()).is_empty() + input[0].fits_in(&VSingleType::String.to(), info).is_empty() } else { false } @@ -230,11 +230,11 @@ impl BuiltinFunction { !input.is_empty() && input .iter() - .all(|v| v.fits_in(&VSingleType::String.to()).is_empty()) + .all(|v| v.fits_in(&VSingleType::String.to(), info).is_empty()) } Self::StdinReadLine => input.is_empty(), Self::ParseInt | Self::ParseFloat => { - input.len() == 1 && input[0].fits_in(&VSingleType::String.to()).is_empty() + input.len() == 1 && input[0].fits_in(&VSingleType::String.to(), info).is_empty() } Self::Run | Self::Thread => { if input.len() >= 1 { @@ -364,7 +364,7 @@ impl BuiltinFunction { let (vec, el) = (&input[0], &input[1]); // if vec.is_reference().is_some_and(|v| v) { // unstable if let Some(true) = vec.is_reference() { - if let Some(t) = vec.get_any() { + if let Some(t) = vec.get_any(info) { el.fits_in(&t).is_empty() } else { false @@ -380,7 +380,7 @@ impl BuiltinFunction { if input.len() == 3 { let (vec, el) = (&input[0], &input[1]); if let Some(true) = vec.is_reference() { - if let Some(t) = vec.get_any() { + if let Some(t) = vec.get_any(info) { el.fits_in(&t).is_empty() } else { false @@ -397,7 +397,7 @@ impl BuiltinFunction { let vec = &input[0]; if let Some(true) = vec.is_reference() { // TODO! this also returns true for tuples. what should we do for tuples? should pop return (first_val rest_of_tuple) and not take a reference? - if let Some(_) = vec.get_any() { + if let Some(_) = vec.get_any(info) { true } else { false @@ -414,7 +414,7 @@ impl BuiltinFunction { let (vec, index) = (&input[0], &input[1]); if let Some(true) = vec.is_reference() { // TODO! same issue as in pop - if let Some(_) = vec.get_any() { + if let Some(_) = vec.get_any(info) { if index.fits_in(&VSingleType::Int.to()).is_empty() { true } else { @@ -477,7 +477,7 @@ impl BuiltinFunction { } } /// for invalid inputs, may panic - pub fn returns(&self, input: Vec) -> VType { + pub fn returns(&self, input: Vec, info: &GlobalScriptInfo) -> VType { match self { Self::Assume1 => { let mut out = VType { types: vec![] }; @@ -569,7 +569,7 @@ impl BuiltinFunction { types: vec![ VSingleType::Tuple(vec![]), VSingleType::Tuple(vec![v - .get_any() + .get_any(info) .expect("cannot use get on this type")]), ], } @@ -783,7 +783,7 @@ impl BuiltinFunction { let val = args[0].run(vars, info); println!( "{} :: {} :: {}", - args[0].out().gsi(info.clone()), + args[0].out(info).gsi(info.clone()), val.out().gsi(info.clone()), val.gsi(info.clone()) ); diff --git a/mers/src/script/code_macro.rs b/mers/src/script/code_macro.rs old mode 100644 new mode 100755 diff --git a/mers/src/script/code_parsed.rs b/mers/src/script/code_parsed.rs old mode 100644 new mode 100755 index 665d8b8..51d28de --- a/mers/src/script/code_parsed.rs +++ b/mers/src/script/code_parsed.rs @@ -1,6 +1,6 @@ use std::fmt::{self, Display, Formatter, Pointer}; -use super::{code_macro::Macro, global_info::GSInfo, val_data::VData, val_type::VType}; +use super::{code_macro::Macro, global_info::GlobalScriptInfo, val_data::VData, val_type::VType}; pub enum SStatementEnum { Value(VData), @@ -78,7 +78,7 @@ impl SFunction { // impl SStatementEnum { - pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GSInfo>) -> fmt::Result { + pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result { match self { Self::Value(v) => v.fmtgs(f, info), Self::Tuple(v) => { @@ -186,7 +186,7 @@ impl Display for SStatementEnum { } impl SStatement { - pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GSInfo>) -> fmt::Result { + pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result { if let Some((opt, derefs)) = &self.output_to { if let Some(forced_type) = &self.force_output_type { write!(f, "{}{}::", "*".repeat(*derefs), opt)?; @@ -206,7 +206,7 @@ impl Display for SStatement { } impl SFunction { - pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GSInfo>) -> fmt::Result { + pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result { write!(f, "(")?; for (i, (name, t)) in self.inputs.iter().enumerate() { if i > 0 { @@ -222,7 +222,7 @@ impl SFunction { } impl SBlock { - pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GSInfo>) -> fmt::Result { + pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result { match self.statements.len() { 0 => write!(f, "{{}}"), 1 => self.statements[0].fmtgs(f, info), diff --git a/mers/src/script/code_runnable.rs b/mers/src/script/code_runnable.rs old mode 100644 new mode 100755 index 9465e69..bb2a16a --- a/mers/src/script/code_runnable.rs +++ b/mers/src/script/code_runnable.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex}; use super::{ builtins::BuiltinFunction, - global_info::GSInfo, + global_info::{GlobalScriptInfo, GSInfo}, to_runnable::ToRunnableError, val_data::{VData, VDataEnum}, val_type::{VSingleType, VType}, @@ -29,9 +29,9 @@ impl RBlock { VDataEnum::Tuple(vec![]).to() } } - pub fn out(&self) -> VType { + pub fn out(&self, info: &GlobalScriptInfo) -> VType { if let Some(last) = self.statements.last() { - last.out() + last.out(info) } else { VType { types: vec![VSingleType::Tuple(vec![])], @@ -76,8 +76,8 @@ impl RFunction { } out } - pub fn out_all(&self) -> VType { - self.block.out() + pub fn out_all(&self, info: &GlobalScriptInfo) -> VType { + self.block.out(info) } pub fn in_types(&self) -> &Vec { &self.input_types @@ -109,7 +109,7 @@ impl RStatement { out } } - pub fn out(&self) -> VType { + pub fn out(&self, info: &GlobalScriptInfo) -> VType { // `a = b` evaluates to [] if self.output_to.is_some() { return VType { @@ -119,7 +119,7 @@ impl RStatement { if let Some(t) = &self.force_output_type { return t.clone(); } - self.statement.out() + self.statement.out(info) } } @@ -283,14 +283,14 @@ impl RStatementEnum { Self::EnumVariant(e, v) => VDataEnum::EnumVariant(*e, Box::new(v.run(vars, info))).to(), } } - pub fn out(&self) -> VType { + pub fn out(&self, info: &GlobalScriptInfo) -> VType { match self { Self::Value(v) => v.out(), - Self::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out()).collect()).into(), + Self::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out(info)).collect()).into(), Self::List(v) => VSingleType::List({ let mut types = VType { types: vec![] }; for t in v { - types = types | t.out(); + types = types | t.out(info); } types }) @@ -308,21 +308,21 @@ impl RStatementEnum { t.clone() } } - Self::FunctionCall(f, args) => f.out_vt(&args.iter().map(|v| v.out()).collect()), + Self::FunctionCall(f, args) => f.out_vt(&args.iter().map(|v| v.out(info)).collect()), Self::LibFunction(.., out) => out.clone(), - Self::Block(b) => b.out(), + Self::Block(b) => b.out(info), Self::If(_, a, b) => { if let Some(b) = b { - a.out() | b.out() + a.out(info) | b.out(info) } else { - a.out() | VSingleType::Tuple(vec![]).to() + a.out(info) | VSingleType::Tuple(vec![]).to() } } - Self::Loop(c) => c.out().matches().1, - Self::For(_, _, b) => VSingleType::Tuple(vec![]).to() | b.out().matches().1, - Self::BuiltinFunction(f, args) => f.returns(args.iter().map(|rs| rs.out()).collect()), + Self::Loop(c) => c.out(info).matches().1, + Self::For(_, _, b) => VSingleType::Tuple(vec![]).to() | b.out(info).matches().1, + Self::BuiltinFunction(f, args) => f.returns(args.iter().map(|rs| rs.out(info)).collect(), info), Self::Switch(switch_on, cases) => { - let switch_on = switch_on.out().types; + let switch_on = switch_on.out(info).types; let mut might_return_empty = switch_on.is_empty(); let mut out = VType { types: vec![] }; // if nothing is executed for switch_on in switch_on { @@ -330,7 +330,7 @@ impl RStatementEnum { 'search: { for (on_type, case) in cases.iter() { if switch_on.fits_in(&on_type).is_empty() { - out = out | case.out(); + out = out | case.out(info); break 'search; } } @@ -345,12 +345,12 @@ impl RStatementEnum { Self::Match(_, cases) => { let mut out = VSingleType::Tuple(vec![]).to(); for case in cases { - out = out | case.1.out(); + out = out | case.1.out(info); } out } - Self::IndexFixed(st, i) => st.out().get(*i).unwrap(), - Self::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out()).to(), + Self::IndexFixed(st, i) => st.out(info).get(*i, info).unwrap(), + Self::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out(info)).to(), } } pub fn to(self) -> RStatement { @@ -364,18 +364,17 @@ impl RStatementEnum { pub struct RScript { main: RFunction, - vars: usize, info: GSInfo, } impl RScript { - pub fn new(main: RFunction, vars: usize, info: GSInfo) -> Result { + pub fn new(main: RFunction, info: GSInfo) -> Result { if main.inputs.len() != 1 { return Err(ToRunnableError::MainWrongInput); } - Ok(Self { main, vars, info }) + Ok(Self { main, info: info }) } pub fn run(&self, args: Vec) -> VData { - let mut vars = Vec::with_capacity(self.vars); + let mut vars = Vec::with_capacity(self.info.vars); vars.push(am(VDataEnum::List( VSingleType::String.into(), args.into_iter() @@ -383,7 +382,7 @@ impl RScript { .collect(), ) .to())); - for _i in 1..self.vars { + for _i in 1..self.info.vars { vars.push(am(VDataEnum::Tuple(vec![]).to())); } self.main.run(&vars, &self.info) diff --git a/mers/src/script/global_info.rs b/mers/src/script/global_info.rs old mode 100644 new mode 100755 index 090b2b3..a838421 --- a/mers/src/script/global_info.rs +++ b/mers/src/script/global_info.rs @@ -2,14 +2,46 @@ use std::{collections::HashMap, sync::Arc}; use crate::libs; +use super::{val_type::VType, builtins}; + pub type GSInfo = Arc; -// pub type GSMInfo = Arc>; + pub struct GlobalScriptInfo { + pub vars: usize, + pub libs: Vec, - pub enums: HashMap, + pub lib_fns: HashMap, + + pub enum_variants: HashMap, + + pub custom_type_names: HashMap, + pub custom_types: Vec, } + impl GlobalScriptInfo { pub fn to_arc(self) -> GSInfo { Arc::new(self) } } + +impl Default for GlobalScriptInfo { + fn default() -> Self { + Self { + vars: 0, + libs: vec![], + lib_fns: HashMap::new(), + enum_variants: Self::default_enum_variants(), + custom_type_names: HashMap::new(), + custom_types: vec![], + } + } +} +impl GlobalScriptInfo { + pub fn default_enum_variants() -> HashMap { + builtins::EVS + .iter() + .enumerate() + .map(|(i, v)| (v.to_string(), i)) + .collect() + } +} \ No newline at end of file diff --git a/mers/src/script/to_runnable.rs b/mers/src/script/to_runnable.rs old mode 100644 new mode 100755 index 92fadab..b47de58 --- a/mers/src/script/to_runnable.rs +++ b/mers/src/script/to_runnable.rs @@ -97,46 +97,6 @@ impl Display for ToRunnableError { } } -// Global, shared between all -pub struct GInfo { - vars: usize, - pub libs: Vec, - pub lib_fns: HashMap, - pub enum_variants: HashMap, -} -impl Default for GInfo { - fn default() -> Self { - Self { - vars: 0, - libs: vec![], - lib_fns: HashMap::new(), - enum_variants: Self::default_enum_variants(), - } - } -} -impl GInfo { - pub fn default_enum_variants() -> HashMap { - builtins::EVS - .iter() - .enumerate() - .map(|(i, v)| (v.to_string(), i)) - .collect() - } - pub fn new(libs: Vec, enum_variants: HashMap) -> Self { - let mut lib_fns = HashMap::new(); - for (libid, lib) in libs.iter().enumerate() { - for (fnid, (name, ..)) in lib.registered_fns.iter().enumerate() { - lib_fns.insert(name.to_string(), (libid, fnid)); - } - } - Self { - vars: 0, - libs, - lib_fns, - enum_variants, - } - } -} // Local, used to keep local variables separated #[derive(Clone)] struct LInfo { @@ -144,7 +104,7 @@ struct LInfo { fns: HashMap>, } -pub fn to_runnable(s: SFunction, mut ginfo: GInfo) -> Result { +pub fn to_runnable(s: SFunction, mut ginfo: GlobalScriptInfo) -> Result { if s.inputs.len() != 1 || s.inputs[0].0 != "args" { return Err(ToRunnableError::MainWrongInput); } @@ -166,19 +126,14 @@ pub fn to_runnable(s: SFunction, mut ginfo: GInfo) -> Result, inputs: &mut Vec, @@ -197,13 +152,13 @@ fn get_all_functions( for (varid, vartype) in s.inputs.iter().zip(inputs.iter()) { linfo.vars.get_mut(&varid.0).unwrap().1 = vartype.clone().into(); } - out.push((inputs.clone(), block(&s.block, ginfo, linfo.clone())?.out())); + out.push((inputs.clone(), block(&s.block, ginfo, linfo.clone())?.out(ginfo))); Ok(()) } } fn function( s: &SFunction, - ginfo: &mut GInfo, + ginfo: &mut GlobalScriptInfo, mut linfo: LInfo, ) -> Result { let mut input_vars = vec![]; @@ -237,7 +192,7 @@ fn function( }) } -fn block(s: &SBlock, ginfo: &mut GInfo, mut linfo: LInfo) -> Result { +fn block(s: &SBlock, ginfo: &mut GlobalScriptInfo, mut linfo: LInfo) -> Result { let mut statements = Vec::new(); for st in &s.statements { statements.push(statement(st, ginfo, &mut linfo)?); @@ -245,12 +200,12 @@ fn block(s: &SBlock, ginfo: &mut GInfo, mut linfo: LInfo) -> Result { for t in v { @@ -279,7 +234,7 @@ fn stype(t: &mut VSingleType, ginfo: &mut GInfo) { } fn statement( s: &SStatement, - ginfo: &mut GInfo, + ginfo: &mut GlobalScriptInfo, linfo: &mut LInfo, ) -> Result { let mut statement = match &*s.statement { @@ -317,7 +272,7 @@ fn statement( )); } for (i, rarg) in rargs.iter().enumerate() { - let rarg = rarg.out(); + let rarg = rarg.out(ginfo); let out = rarg.fits_in(&func.input_types[i]); if !out.is_empty() { return Err(ToRunnableError::InvalidType { @@ -331,8 +286,8 @@ fn statement( } else { // TODO: type-checking for builtins if let Some(builtin) = BuiltinFunction::get(v) { - let arg_types = rargs.iter().map(|v| v.out()).collect(); - if builtin.can_take(&arg_types) { + let arg_types = rargs.iter().map(|v| v.out(ginfo)).collect(); + if builtin.can_take(&arg_types, ginfo) { RStatementEnum::BuiltinFunction(builtin, rargs) } else { return Err(ToRunnableError::WrongInputsForBuiltinFunction(builtin, v.to_string(), arg_types)); @@ -341,12 +296,12 @@ fn statement( // LIBRARY FUNCTION? if let Some((libid, fnid)) = ginfo.lib_fns.get(v) { let (_name, fn_in, fn_out) = &ginfo.libs[*libid].registered_fns[*fnid]; - if fn_in.len() == rargs.len() && fn_in.iter().zip(rargs.iter()).all(|(fn_in, arg)| arg.out().fits_in(fn_in).is_empty()) { + if fn_in.len() == rargs.len() && fn_in.iter().zip(rargs.iter()).all(|(fn_in, arg)| arg.out(ginfo).fits_in(fn_in).is_empty()) { RStatementEnum::LibFunction(*libid, *fnid, rargs, fn_out.clone()) } else { // TODO! better error here return Err(if fn_in.len() == rargs.len() { - ToRunnableError::WrongArgsForLibFunction(v.to_string(), rargs.iter().map(|v| v.out()).collect()) + ToRunnableError::WrongArgsForLibFunction(v.to_string(), rargs.iter().map(|v| v.out(ginfo)).collect()) } else { ToRunnableError::FunctionWrongArgCount(v.to_string(), fn_in.len(), rargs.len()) }); @@ -375,7 +330,7 @@ fn statement( SStatementEnum::If(c, t, e) => RStatementEnum::If( { let condition = statement(&c, ginfo, linfo)?; - let out = condition.out().fits_in(&VType { + let out = condition.out(ginfo).fits_in(&VType { types: vec![VSingleType::Bool], }); if out.is_empty() { @@ -383,7 +338,7 @@ fn statement( } else { return Err(ToRunnableError::InvalidType { expected: VSingleType::Bool.into(), - found: condition.out(), + found: condition.out(ginfo), problematic: VType { types: out }, }); } @@ -400,7 +355,7 @@ fn statement( SStatementEnum::For(v, c, b) => { let mut linfo = linfo.clone(); let container = statement(&c, ginfo, &mut linfo)?; - let inner = container.out().inner_types(); + let inner = container.out(ginfo).inner_types(); if inner.types.is_empty() { return Err(ToRunnableError::ForLoopContainerHasNoInnerTypes); } @@ -444,7 +399,8 @@ fn statement( types_not_covered_req_error = true; types_not_covered = types_not_covered | { let mut v = val_type; - fn make_readable(v: &mut VType, ginfo: &GInfo) { + /// converts the VType to one that is human-readable (changes enum from usize to String, ...) + fn make_readable(v: &mut VType, ginfo: &GlobalScriptInfo) { for t in v.types.iter_mut() { match t { VSingleType::EnumVariant(i, v) => { @@ -452,18 +408,20 @@ fn statement( make_readable(&mut v, ginfo); *t = VSingleType::EnumVariantS(ginfo.enum_variants.iter().find_map(|(st, us)| if *us == *i { Some(st.clone()) } else { None }).unwrap(), v); }, - VSingleType::EnumVariantS(_, v) => make_readable(v, ginfo), + VSingleType::CustomType(i) => { + *t = VSingleType::CustomTypeS(ginfo.custom_type_names.iter().find_map(|(st, us)| if *us == *i { Some(st.clone()) } else { None }).unwrap()); + } VSingleType::Tuple(v) => for t in v.iter_mut() { make_readable(t, ginfo) } - VSingleType::List(t) => make_readable(t, ginfo), + VSingleType::List(t) | VSingleType::EnumVariantS(_, t) => make_readable(t, ginfo), VSingleType::Reference(v) => { let mut v = v.clone().to(); make_readable(&mut v, ginfo); assert_eq!(v.types.len(), 1); *t = VSingleType::Reference(Box::new(v.types.remove(0))); } - VSingleType::Bool | VSingleType::Int | VSingleType::Float | VSingleType::String | VSingleType::Function(..) | VSingleType::Thread(..) => (), + VSingleType::Bool | VSingleType::Int | VSingleType::Float | VSingleType::String | VSingleType::Function(..) | VSingleType::Thread(..) | VSingleType::CustomTypeS(_) => (), } } } @@ -490,7 +448,7 @@ fn statement( let og_type = switch_on_v.1.clone(); // linfo.vars.get(match_on).unwrap().1.clone(); for case in cases { let case_condition = statement(&case.0, ginfo, linfo)?; - let case_condition_out = case_condition.out(); + let case_condition_out = case_condition.out(ginfo); let mut refutable = false; let mut success_output = VType { types: vec![] }; for case_type in case_condition_out.types.iter() { @@ -537,7 +495,7 @@ fn statement( let st = statement(st, ginfo, linfo)?; let ok = 'ok: { let mut one = false; - for t in st.out().types { + for t in st.out(ginfo).types { one = true; // only if all types are indexable by i match t { @@ -554,7 +512,7 @@ fn statement( if ok { RStatementEnum::IndexFixed(st, *i) } else { - return Err(ToRunnableError::NotIndexableFixed(st.out(), *i)); + return Err(ToRunnableError::NotIndexableFixed(st.out(ginfo), *i)); } } SStatementEnum::EnumVariant(variant, s) => RStatementEnum::EnumVariant({ @@ -573,7 +531,7 @@ fn statement( .to(); // if force_output_type is set, verify that the real output type actually fits in the forced one. if let Some(force_opt) = &s.force_output_type { - let real_output_type = statement.out(); + let real_output_type = statement.out(ginfo); let problematic_types = real_output_type.fits_in(force_opt); if problematic_types.is_empty() { statement.force_output_type = Some(force_opt.clone()); @@ -583,7 +541,7 @@ fn statement( } if let Some((opt, derefs)) = &s.output_to { if let Some((var_id, var_out)) = linfo.vars.get(opt) { - let out = statement.out(); + let out = statement.out(ginfo); let mut var_derefd = var_out.clone(); for _ in 0..*derefs { var_derefd = if let Some(v) = var_derefd.dereference() { @@ -612,13 +570,13 @@ fn statement( statement.output_to = Some((*var_id, *derefs)); } } else { - let mut out = statement.out(); + let mut out = statement.out(ginfo); for _ in 0..*derefs { out = if let Some(v) = out.dereference() { v } else { return Err(ToRunnableError::CannotDereferenceTypeNTimes( - statement.out(), + statement.out(ginfo), *derefs, out, )); diff --git a/mers/src/script/val_data.rs b/mers/src/script/val_data.rs index a2cfc41..c1b06c6 100755 --- a/mers/src/script/val_data.rs +++ b/mers/src/script/val_data.rs @@ -5,7 +5,7 @@ use std::{ use super::{ code_runnable::RFunction, - global_info::GSInfo, + global_info::{GlobalScriptInfo, GSInfo}, val_type::{VSingleType, VType}, }; @@ -255,7 +255,7 @@ impl VData { } impl VDataEnum { - pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GSInfo>) -> fmt::Result { + pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result { match self { Self::Bool(true) => write!(f, "true"), Self::Bool(false) => write!(f, "false"), @@ -290,7 +290,7 @@ impl VDataEnum { } Self::EnumVariant(variant, inner) => { if let Some(name) = if let Some(info) = info { - info.enums + info.enum_variants .iter() .find_map(|(name, id)| if id == variant { Some(name) } else { None }) } else { @@ -312,7 +312,7 @@ impl Display for VDataEnum { } impl VData { - pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GSInfo>) -> fmt::Result { + pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result { self.data.fmtgs(f, info) } } diff --git a/mers/src/script/val_type.rs b/mers/src/script/val_type.rs index ae46845..e720353 100755 --- a/mers/src/script/val_type.rs +++ b/mers/src/script/val_type.rs @@ -4,7 +4,7 @@ use std::{ ops::BitOr, }; -use super::global_info::GSInfo; +use super::global_info::{GlobalScriptInfo, GSInfo}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct VType { @@ -24,20 +24,22 @@ pub enum VSingleType { Reference(Box), EnumVariant(usize, VType), EnumVariantS(String, VType), - // CustomType(usize), - // CustomTypeS(String), + CustomType(usize), + CustomTypeS(String), } impl VSingleType { // None => Cannot get, Some(t) => getting can return t or nothing - pub fn get(&self, i: usize) -> Option { + pub fn get(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option { match self { Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None, Self::String => Some(VSingleType::String.into()), Self::Tuple(t) => t.get(i).cloned(), Self::List(t) => Some(t.clone()), - Self::Reference(r) => r.get(i), - Self::EnumVariant(_, t) | Self::EnumVariantS(_, t) => t.get(i), + Self::Reference(r) => r.get(i, gsinfo), + Self::EnumVariant(_, t) | Self::EnumVariantS(_, t) => t.get(i, gsinfo), + Self::CustomType(t) => gsinfo.custom_types[*t].get(i, gsinfo), + &Self::CustomTypeS(_) => unreachable!("CustomTypeS instead of CustomType, compiler error?"), } } } @@ -45,10 +47,10 @@ impl VType { pub fn empty() -> Self { Self { types: vec![] } } - pub fn get(&self, i: usize) -> Option { + pub fn get(&self, i: usize, info: &GlobalScriptInfo) -> Option { let mut out = VType { types: vec![] }; for t in &self.types { - out = out | t.get(i)?; // if we can't use *get* on one type, we can't use it at all. + out = out | t.get(i, info)?; // if we can't use *get* on one type, we can't use it at all. } Some(out) } @@ -80,15 +82,17 @@ impl VType { } impl VSingleType { - pub fn get_any(&self) -> Option { + pub fn get_any(&self, info: &GlobalScriptInfo) -> Option { match self { Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None, Self::String => Some(VSingleType::String.into()), Self::Tuple(t) => Some(t.iter().fold(VType { types: vec![] }, |a, b| a | b)), Self::List(t) => Some(t.clone()), - Self::Reference(r) => r.get_any(), - Self::EnumVariant(_, t) => t.get_any(), + Self::Reference(r) => r.get_any(info), + Self::EnumVariant(_, t) => t.get_any(info), Self::EnumVariantS(..) => unreachable!(), + Self::CustomType(t) => info.custom_types[*t].get_any(info), + Self::CustomTypeS(_) => unreachable!(), } } pub fn is_reference(&self) -> bool { @@ -106,10 +110,10 @@ impl VSingleType { } } impl VType { - pub fn get_any(&self) -> Option { + pub fn get_any(&self, info: &GlobalScriptInfo) -> Option { let mut out = VType { types: vec![] }; for t in &self.types { - out = out | t.get_any()?; // if we can't use *get* on one type, we can't use it at all. + out = out | t.get_any(info)?; // if we can't use *get* on one type, we can't use it at all. } Some(out) } @@ -117,11 +121,11 @@ impl VType { impl VType { /// Returns a vec with all types in self that aren't covered by rhs. If the returned vec is empty, self fits in rhs. - pub fn fits_in(&self, rhs: &Self) -> Vec { + pub fn fits_in(&self, rhs: &Self, info: &GlobalScriptInfo) -> Vec { let mut no = vec![]; for t in &self.types { // if t doesnt fit in any of rhs's types - if !rhs.types.iter().any(|r| t.fits_in(r)) { + if !rhs.types.iter().any(|r| t.fits_in(r, info)) { no.push(t.clone()) } } @@ -223,6 +227,7 @@ impl VSingleType { v => v.to(), } } + /// converts all Self::EnumVariantS to Self::EnumVariant pub fn enum_variants(&mut self, enum_variants: &mut HashMap) { match self { Self::Bool | Self::Int | Self::Float | Self::String => (), @@ -254,15 +259,20 @@ impl VSingleType { v.enum_variants(enum_variants); *self = Self::EnumVariant(e, v.clone()); } + Self::CustomType(_) | Self::CustomTypeS(_) => (), } } - pub fn fits_in(&self, rhs: &Self) -> bool { + pub fn fits_in(&self, rhs: &Self, info: &GlobalScriptInfo) -> bool { match (self, rhs) { - (Self::Reference(r), Self::Reference(b)) => r.fits_in(b), + (Self::Reference(r), Self::Reference(b)) => r.fits_in(b, info), (Self::Reference(_), _) | (_, Self::Reference(_)) => false, (Self::EnumVariant(v1, t1), Self::EnumVariant(v2, t2)) => { - *v1 == *v2 && t1.fits_in(&t2).is_empty() - } + *v1 == *v2 && t1.fits_in(&t2, info).is_empty() + }, + (Self::CustomType(a), b) => info.custom_types[*a].fits_in(&b.clone().to(), info).is_empty(), + (a, Self::CustomType(b)) => a.clone().to().fits_in(&info.custom_types[*b], info).is_empty(), + (Self::CustomType(a), Self::CustomType(b)) => info.custom_types[*a].fits_in(&info.custom_types[*b], info).is_empty(), + (Self::CustomTypeS(_), _) | (_, Self::CustomTypeS(_)) => unreachable!(), (Self::EnumVariant(..), _) | (_, Self::EnumVariant(..)) => false, (Self::EnumVariantS(..), _) | (_, Self::EnumVariantS(..)) => unreachable!(), (Self::Bool, Self::Bool) @@ -272,19 +282,19 @@ impl VSingleType { (Self::Bool | Self::Int | Self::Float | Self::String, _) => false, (Self::Tuple(a), Self::Tuple(b)) => { if a.len() == b.len() { - a.iter().zip(b.iter()).all(|(a, b)| a.fits_in(b).is_empty()) + a.iter().zip(b.iter()).all(|(a, b)| a.fits_in(b, info).is_empty()) } else { false } } (Self::Tuple(_), _) => false, - (Self::List(a), Self::List(b)) => a.fits_in(b).is_empty(), + (Self::List(a), Self::List(b)) => a.fits_in(b, info).is_empty(), (Self::List(_), _) => false, (Self::Function(a), Self::Function(b)) => 'func_out: { for a in a { 'search: { for b in b { - if a.1.fits_in(&b.1).is_empty() + if a.1.fits_in(&b.1, info).is_empty() && a.0.iter().zip(b.0.iter()).all(|(a, b)| *a == *b) { break 'search; @@ -296,7 +306,7 @@ impl VSingleType { true } (Self::Function(..), _) => false, - (Self::Thread(a), Self::Thread(b)) => a.fits_in(b).is_empty(), + (Self::Thread(a), Self::Thread(b)) => a.fits_in(b, info).is_empty(), (Self::Thread(..), _) => false, } } @@ -323,7 +333,7 @@ impl VType { } impl VSingleType { - pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GSInfo>) -> fmt::Result { + pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result { match self { Self::Bool => write!(f, "bool"), Self::Int => write!(f, "int"), @@ -368,7 +378,7 @@ impl VSingleType { } Self::EnumVariant(variant, inner) => { if let Some(name) = if let Some(info) = info { - info.enums + info.enum_variants .iter() .find_map(|(name, id)| if id == variant { Some(name) } else { None }) } else { @@ -396,7 +406,7 @@ impl Display for VSingleType { } impl VType { - pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GSInfo>) -> fmt::Result { + pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result { for (i, t) in self.types.iter().enumerate() { if i > 0 { write!(f, "/")?; diff --git a/mers/src/tutor/base_comments.rs b/mers/src/tutor/base_comments.rs old mode 100644 new mode 100755 diff --git a/mers/src/tutor/base_functions.rs b/mers/src/tutor/base_functions.rs old mode 100644 new mode 100755 diff --git a/mers/src/tutor/base_return.rs b/mers/src/tutor/base_return.rs old mode 100644 new mode 100755 diff --git a/mers/src/tutor/base_types.rs b/mers/src/tutor/base_types.rs old mode 100644 new mode 100755 diff --git a/mers/src/tutor/base_values.rs b/mers/src/tutor/base_values.rs old mode 100644 new mode 100755 diff --git a/mers/src/tutor/base_variables.rs b/mers/src/tutor/base_variables.rs old mode 100644 new mode 100755 diff --git a/mers/src/tutor/error_handling.rs b/mers/src/tutor/error_handling.rs old mode 100644 new mode 100755 diff --git a/mers/src/tutor/menu.rs b/mers/src/tutor/menu.rs old mode 100644 new mode 100755 diff --git a/mers/src/tutor/mod.rs b/mers/src/tutor/mod.rs old mode 100644 new mode 100755 diff --git a/mersrandr.mers b/mersrandr.mers old mode 100644 new mode 100755 diff --git a/my_macro.mers b/my_macro.mers old mode 100644 new mode 100755