safety commit because i want to try cargo fix

This commit is contained in:
mark 2023-04-29 16:35:25 +02:00
parent 690a4716fd
commit 8bafe58593
23 changed files with 167 additions and 167 deletions

0
iterators.mers Normal file → Executable file
View File

0
mers/src/interactive_mode.rs Normal file → Executable file
View File

0
mers/src/lib.rs Normal file → Executable file
View File

View File

@ -6,8 +6,8 @@ use crate::{
code_macro::MacroError, code_macro::MacroError,
code_parsed::*, code_parsed::*,
code_runnable::RScript, code_runnable::RScript,
global_info::GSInfo, global_info::{GlobalScriptInfo},
to_runnable::{self, GInfo, ToRunnableError}, to_runnable::{self, ToRunnableError},
val_data::VDataEnum, val_data::VDataEnum,
val_type::{VSingleType, VType}, 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 /// executes the 4 parse_steps in order: lib_paths => interpret => libs_load => compile
pub fn parse(file: &mut File) -> Result<RScript, ScriptError> { pub fn parse(file: &mut File) -> Result<RScript, ScriptError> {
let mut ginfo = GInfo::default(); let mut ginfo = GlobalScriptInfo::default();
let libs = parse_step_lib_paths(file)?; let libs = parse_step_lib_paths(file)?;
let func = parse_step_interpret(file)?; let func = parse_step_interpret(file)?;
ginfo.libs = parse_step_libs_load(libs, &mut ginfo)?; 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( pub fn parse_step_libs_load(
lib_cmds: Vec<Command>, lib_cmds: Vec<Command>,
ginfo: &mut GInfo, ginfo: &mut GlobalScriptInfo,
) -> Result<Vec<libs::Lib>, UnableToLoadLibrary> { ) -> Result<Vec<libs::Lib>, UnableToLoadLibrary> {
let mut libs = vec![]; let mut libs = vec![];
for cmd in lib_cmds { for cmd in lib_cmds {
@ -153,7 +153,7 @@ pub fn parse_step_libs_load(
Ok(libs) Ok(libs)
} }
pub fn parse_step_compile(main_func: SFunction, ginfo: GInfo) -> Result<RScript, ToRunnableError> { pub fn parse_step_compile(main_func: SFunction, ginfo: GlobalScriptInfo) -> Result<RScript, ToRunnableError> {
to_runnable::to_runnable(main_func, ginfo) to_runnable::to_runnable(main_func, ginfo)
} }
@ -177,7 +177,7 @@ pub struct ParseError {
String, String,
Option<(super::file::FilePosition, Option<super::file::FilePosition>)>, Option<(super::file::FilePosition, Option<super::file::FilePosition>)>,
)>, )>,
info: Option<GSInfo>, info: Option<GlobalScriptInfo>,
} }
impl ParseError { impl ParseError {
pub fn fmt_custom( pub fn fmt_custom(
@ -246,7 +246,7 @@ impl ParseErrors {
fn fmtgs( fn fmtgs(
&self, &self,
f: &mut std::fmt::Formatter, f: &mut std::fmt::Formatter,
info: Option<&GSInfo>, info: Option<&GlobalScriptInfo>,
file: Option<&super::file::File>, file: Option<&super::file::File>,
) -> std::fmt::Result { ) -> std::fmt::Result {
match self { match self {
@ -1150,15 +1150,16 @@ pub mod implementation {
"int" => VSingleType::Int, "int" => VSingleType::Int,
"float" => VSingleType::Float, "float" => VSingleType::Float,
"string" => VSingleType::String, "string" => VSingleType::String,
_ => { custom => VSingleType::CustomTypeS(custom.to_owned()),
return Err(ParseError { // _ => {
err: ParseErrors::InvalidType(name.trim().to_string()), // return Err(ParseError {
location: err_start_of_single_type, // err: ParseErrors::InvalidType(name.trim().to_string()),
location_end: Some(*file.get_pos()), // location: err_start_of_single_type,
context: vec![], // location_end: Some(*file.get_pos()),
info: None, // context: vec![],
}); // info: None,
} // });
// }
} }
} }
None => { None => {

View File

@ -8,7 +8,7 @@ use crate::libs;
use super::{ use super::{
code_runnable::RStatement, code_runnable::RStatement,
global_info::GSInfo, global_info::{GlobalScriptInfo, GSInfo},
val_data::{thread::VDataThreadEnum, VData, VDataEnum}, val_data::{thread::VDataThreadEnum, VData, VDataEnum},
val_type::{VSingleType, VType}, val_type::{VSingleType, VType},
}; };
@ -148,7 +148,7 @@ impl BuiltinFunction {
_ => return None, _ => return None,
}) })
} }
pub fn can_take(&self, input: &Vec<VType>) -> bool { pub fn can_take(&self, input: &Vec<VType>, info: &GlobalScriptInfo) -> bool {
match self { match self {
Self::Assume1 => { Self::Assume1 => {
if input.len() >= 1 { if input.len() >= 1 {
@ -172,7 +172,7 @@ impl BuiltinFunction {
} }
if input.len() >= 2 { if input.len() >= 2 {
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 { } else {
false false
} }
@ -203,7 +203,7 @@ impl BuiltinFunction {
} }
if input.len() >= 2 { if input.len() >= 2 {
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 { } else {
false false
} }
@ -219,7 +219,7 @@ impl BuiltinFunction {
Self::Clone => input.len() == 1 && matches!(input[0].is_reference(), Some(true)), Self::Clone => input.len() == 1 && matches!(input[0].is_reference(), Some(true)),
Self::Print | Self::Println => { Self::Print | Self::Println => {
if input.len() == 1 { if input.len() == 1 {
input[0].fits_in(&VSingleType::String.to()).is_empty() input[0].fits_in(&VSingleType::String.to(), info).is_empty()
} else { } else {
false false
} }
@ -230,11 +230,11 @@ impl BuiltinFunction {
!input.is_empty() !input.is_empty()
&& input && input
.iter() .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::StdinReadLine => input.is_empty(),
Self::ParseInt | Self::ParseFloat => { 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 => { Self::Run | Self::Thread => {
if input.len() >= 1 { if input.len() >= 1 {
@ -364,7 +364,7 @@ impl BuiltinFunction {
let (vec, el) = (&input[0], &input[1]); let (vec, el) = (&input[0], &input[1]);
// if vec.is_reference().is_some_and(|v| v) { // unstable // if vec.is_reference().is_some_and(|v| v) { // unstable
if let Some(true) = vec.is_reference() { 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() el.fits_in(&t).is_empty()
} else { } else {
false false
@ -380,7 +380,7 @@ impl BuiltinFunction {
if input.len() == 3 { if input.len() == 3 {
let (vec, el) = (&input[0], &input[1]); let (vec, el) = (&input[0], &input[1]);
if let Some(true) = vec.is_reference() { 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() el.fits_in(&t).is_empty()
} else { } else {
false false
@ -397,7 +397,7 @@ impl BuiltinFunction {
let vec = &input[0]; let vec = &input[0];
if let Some(true) = vec.is_reference() { 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? // 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 true
} else { } else {
false false
@ -414,7 +414,7 @@ impl BuiltinFunction {
let (vec, index) = (&input[0], &input[1]); let (vec, index) = (&input[0], &input[1]);
if let Some(true) = vec.is_reference() { if let Some(true) = vec.is_reference() {
// TODO! same issue as in pop // 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() { if index.fits_in(&VSingleType::Int.to()).is_empty() {
true true
} else { } else {
@ -477,7 +477,7 @@ impl BuiltinFunction {
} }
} }
/// for invalid inputs, may panic /// for invalid inputs, may panic
pub fn returns(&self, input: Vec<VType>) -> VType { pub fn returns(&self, input: Vec<VType>, info: &GlobalScriptInfo) -> VType {
match self { match self {
Self::Assume1 => { Self::Assume1 => {
let mut out = VType { types: vec![] }; let mut out = VType { types: vec![] };
@ -569,7 +569,7 @@ impl BuiltinFunction {
types: vec![ types: vec![
VSingleType::Tuple(vec![]), VSingleType::Tuple(vec![]),
VSingleType::Tuple(vec![v VSingleType::Tuple(vec![v
.get_any() .get_any(info)
.expect("cannot use get on this type")]), .expect("cannot use get on this type")]),
], ],
} }
@ -783,7 +783,7 @@ impl BuiltinFunction {
let val = args[0].run(vars, info); let val = args[0].run(vars, info);
println!( println!(
"{} :: {} :: {}", "{} :: {} :: {}",
args[0].out().gsi(info.clone()), args[0].out(info).gsi(info.clone()),
val.out().gsi(info.clone()), val.out().gsi(info.clone()),
val.gsi(info.clone()) val.gsi(info.clone())
); );

0
mers/src/script/code_macro.rs Normal file → Executable file
View File

10
mers/src/script/code_parsed.rs Normal file → Executable file
View File

@ -1,6 +1,6 @@
use std::fmt::{self, Display, Formatter, Pointer}; 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 { pub enum SStatementEnum {
Value(VData), Value(VData),
@ -78,7 +78,7 @@ impl SFunction {
// //
impl SStatementEnum { 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 { match self {
Self::Value(v) => v.fmtgs(f, info), Self::Value(v) => v.fmtgs(f, info),
Self::Tuple(v) => { Self::Tuple(v) => {
@ -186,7 +186,7 @@ impl Display for SStatementEnum {
} }
impl SStatement { 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((opt, derefs)) = &self.output_to {
if let Some(forced_type) = &self.force_output_type { if let Some(forced_type) = &self.force_output_type {
write!(f, "{}{}::", "*".repeat(*derefs), opt)?; write!(f, "{}{}::", "*".repeat(*derefs), opt)?;
@ -206,7 +206,7 @@ impl Display for SStatement {
} }
impl SFunction { 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, "(")?; write!(f, "(")?;
for (i, (name, t)) in self.inputs.iter().enumerate() { for (i, (name, t)) in self.inputs.iter().enumerate() {
if i > 0 { if i > 0 {
@ -222,7 +222,7 @@ impl SFunction {
} }
impl SBlock { 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() { match self.statements.len() {
0 => write!(f, "{{}}"), 0 => write!(f, "{{}}"),
1 => self.statements[0].fmtgs(f, info), 1 => self.statements[0].fmtgs(f, info),

53
mers/src/script/code_runnable.rs Normal file → Executable file
View File

@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex};
use super::{ use super::{
builtins::BuiltinFunction, builtins::BuiltinFunction,
global_info::GSInfo, global_info::{GlobalScriptInfo, GSInfo},
to_runnable::ToRunnableError, to_runnable::ToRunnableError,
val_data::{VData, VDataEnum}, val_data::{VData, VDataEnum},
val_type::{VSingleType, VType}, val_type::{VSingleType, VType},
@ -29,9 +29,9 @@ impl RBlock {
VDataEnum::Tuple(vec![]).to() VDataEnum::Tuple(vec![]).to()
} }
} }
pub fn out(&self) -> VType { pub fn out(&self, info: &GlobalScriptInfo) -> VType {
if let Some(last) = self.statements.last() { if let Some(last) = self.statements.last() {
last.out() last.out(info)
} else { } else {
VType { VType {
types: vec![VSingleType::Tuple(vec![])], types: vec![VSingleType::Tuple(vec![])],
@ -76,8 +76,8 @@ impl RFunction {
} }
out out
} }
pub fn out_all(&self) -> VType { pub fn out_all(&self, info: &GlobalScriptInfo) -> VType {
self.block.out() self.block.out(info)
} }
pub fn in_types(&self) -> &Vec<VType> { pub fn in_types(&self) -> &Vec<VType> {
&self.input_types &self.input_types
@ -109,7 +109,7 @@ impl RStatement {
out out
} }
} }
pub fn out(&self) -> VType { pub fn out(&self, info: &GlobalScriptInfo) -> VType {
// `a = b` evaluates to [] // `a = b` evaluates to []
if self.output_to.is_some() { if self.output_to.is_some() {
return VType { return VType {
@ -119,7 +119,7 @@ impl RStatement {
if let Some(t) = &self.force_output_type { if let Some(t) = &self.force_output_type {
return t.clone(); 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(), 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 { match self {
Self::Value(v) => v.out(), 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({ Self::List(v) => VSingleType::List({
let mut types = VType { types: vec![] }; let mut types = VType { types: vec![] };
for t in v { for t in v {
types = types | t.out(); types = types | t.out(info);
} }
types types
}) })
@ -308,21 +308,21 @@ impl RStatementEnum {
t.clone() 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::LibFunction(.., out) => out.clone(),
Self::Block(b) => b.out(), Self::Block(b) => b.out(info),
Self::If(_, a, b) => { Self::If(_, a, b) => {
if let Some(b) = b { if let Some(b) = b {
a.out() | b.out() a.out(info) | b.out(info)
} else { } else {
a.out() | VSingleType::Tuple(vec![]).to() a.out(info) | VSingleType::Tuple(vec![]).to()
} }
} }
Self::Loop(c) => c.out().matches().1, Self::Loop(c) => c.out(info).matches().1,
Self::For(_, _, b) => VSingleType::Tuple(vec![]).to() | b.out().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()).collect()), Self::BuiltinFunction(f, args) => f.returns(args.iter().map(|rs| rs.out(info)).collect(), info),
Self::Switch(switch_on, cases) => { 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 might_return_empty = switch_on.is_empty();
let mut out = VType { types: vec![] }; // if nothing is executed let mut out = VType { types: vec![] }; // if nothing is executed
for switch_on in switch_on { for switch_on in switch_on {
@ -330,7 +330,7 @@ impl RStatementEnum {
'search: { 'search: {
for (on_type, case) in cases.iter() { for (on_type, case) in cases.iter() {
if switch_on.fits_in(&on_type).is_empty() { if switch_on.fits_in(&on_type).is_empty() {
out = out | case.out(); out = out | case.out(info);
break 'search; break 'search;
} }
} }
@ -345,12 +345,12 @@ impl RStatementEnum {
Self::Match(_, cases) => { Self::Match(_, cases) => {
let mut out = VSingleType::Tuple(vec![]).to(); let mut out = VSingleType::Tuple(vec![]).to();
for case in cases { for case in cases {
out = out | case.1.out(); out = out | case.1.out(info);
} }
out out
} }
Self::IndexFixed(st, i) => st.out().get(*i).unwrap(), Self::IndexFixed(st, i) => st.out(info).get(*i, info).unwrap(),
Self::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out()).to(), Self::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out(info)).to(),
} }
} }
pub fn to(self) -> RStatement { pub fn to(self) -> RStatement {
@ -364,18 +364,17 @@ impl RStatementEnum {
pub struct RScript { pub struct RScript {
main: RFunction, main: RFunction,
vars: usize,
info: GSInfo, info: GSInfo,
} }
impl RScript { impl RScript {
pub fn new(main: RFunction, vars: usize, info: GSInfo) -> Result<Self, ToRunnableError> { pub fn new(main: RFunction, info: GSInfo) -> Result<Self, ToRunnableError> {
if main.inputs.len() != 1 { if main.inputs.len() != 1 {
return Err(ToRunnableError::MainWrongInput); return Err(ToRunnableError::MainWrongInput);
} }
Ok(Self { main, vars, info }) Ok(Self { main, info: info })
} }
pub fn run(&self, args: Vec<String>) -> VData { pub fn run(&self, args: Vec<String>) -> VData {
let mut vars = Vec::with_capacity(self.vars); let mut vars = Vec::with_capacity(self.info.vars);
vars.push(am(VDataEnum::List( vars.push(am(VDataEnum::List(
VSingleType::String.into(), VSingleType::String.into(),
args.into_iter() args.into_iter()
@ -383,7 +382,7 @@ impl RScript {
.collect(), .collect(),
) )
.to())); .to()));
for _i in 1..self.vars { for _i in 1..self.info.vars {
vars.push(am(VDataEnum::Tuple(vec![]).to())); vars.push(am(VDataEnum::Tuple(vec![]).to()));
} }
self.main.run(&vars, &self.info) self.main.run(&vars, &self.info)

36
mers/src/script/global_info.rs Normal file → Executable file
View File

@ -2,14 +2,46 @@ use std::{collections::HashMap, sync::Arc};
use crate::libs; use crate::libs;
use super::{val_type::VType, builtins};
pub type GSInfo = Arc<GlobalScriptInfo>; pub type GSInfo = Arc<GlobalScriptInfo>;
// pub type GSMInfo = Arc<Mutex<GlobalScriptInfo>>;
pub struct GlobalScriptInfo { pub struct GlobalScriptInfo {
pub vars: usize,
pub libs: Vec<libs::Lib>, pub libs: Vec<libs::Lib>,
pub enums: HashMap<String, usize>, pub lib_fns: HashMap<String, (usize, usize)>,
pub enum_variants: HashMap<String, usize>,
pub custom_type_names: HashMap<String, usize>,
pub custom_types: Vec<VType>,
} }
impl GlobalScriptInfo { impl GlobalScriptInfo {
pub fn to_arc(self) -> GSInfo { pub fn to_arc(self) -> GSInfo {
Arc::new(self) 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<String, usize> {
builtins::EVS
.iter()
.enumerate()
.map(|(i, v)| (v.to_string(), i))
.collect()
}
}

104
mers/src/script/to_runnable.rs Normal file → Executable file
View File

@ -97,46 +97,6 @@ impl Display for ToRunnableError {
} }
} }
// Global, shared between all
pub struct GInfo {
vars: usize,
pub libs: Vec<libs::Lib>,
pub lib_fns: HashMap<String, (usize, usize)>,
pub enum_variants: HashMap<String, usize>,
}
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<String, usize> {
builtins::EVS
.iter()
.enumerate()
.map(|(i, v)| (v.to_string(), i))
.collect()
}
pub fn new(libs: Vec<libs::Lib>, enum_variants: HashMap<String, usize>) -> 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 // Local, used to keep local variables separated
#[derive(Clone)] #[derive(Clone)]
struct LInfo { struct LInfo {
@ -144,7 +104,7 @@ struct LInfo {
fns: HashMap<String, Arc<RFunction>>, fns: HashMap<String, Arc<RFunction>>,
} }
pub fn to_runnable(s: SFunction, mut ginfo: GInfo) -> Result<RScript, ToRunnableError> { pub fn to_runnable(s: SFunction, mut ginfo: GlobalScriptInfo) -> Result<RScript, ToRunnableError> {
if s.inputs.len() != 1 || s.inputs[0].0 != "args" { if s.inputs.len() != 1 || s.inputs[0].0 != "args" {
return Err(ToRunnableError::MainWrongInput); return Err(ToRunnableError::MainWrongInput);
} }
@ -166,19 +126,14 @@ pub fn to_runnable(s: SFunction, mut ginfo: GInfo) -> Result<RScript, ToRunnable
)?; )?;
Ok(RScript::new( Ok(RScript::new(
func, func,
ginfo.vars, ginfo.to_arc(),
GlobalScriptInfo {
libs: ginfo.libs,
enums: ginfo.enum_variants,
}
.to_arc(),
)?) )?)
} }
// go over every possible known-type input for the given function, returning all possible RFunctions. // go over every possible known-type input for the given function, returning all possible RFunctions.
fn get_all_functions( fn get_all_functions(
s: &SFunction, s: &SFunction,
ginfo: &mut GInfo, ginfo: &mut GlobalScriptInfo,
linfo: &mut LInfo, linfo: &mut LInfo,
input_vars: &Vec<usize>, input_vars: &Vec<usize>,
inputs: &mut Vec<VSingleType>, inputs: &mut Vec<VSingleType>,
@ -197,13 +152,13 @@ fn get_all_functions(
for (varid, vartype) in s.inputs.iter().zip(inputs.iter()) { for (varid, vartype) in s.inputs.iter().zip(inputs.iter()) {
linfo.vars.get_mut(&varid.0).unwrap().1 = vartype.clone().into(); 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(()) Ok(())
} }
} }
fn function( fn function(
s: &SFunction, s: &SFunction,
ginfo: &mut GInfo, ginfo: &mut GlobalScriptInfo,
mut linfo: LInfo, mut linfo: LInfo,
) -> Result<RFunction, ToRunnableError> { ) -> Result<RFunction, ToRunnableError> {
let mut input_vars = vec![]; let mut input_vars = vec![];
@ -237,7 +192,7 @@ fn function(
}) })
} }
fn block(s: &SBlock, ginfo: &mut GInfo, mut linfo: LInfo) -> Result<RBlock, ToRunnableError> { fn block(s: &SBlock, ginfo: &mut GlobalScriptInfo, mut linfo: LInfo) -> Result<RBlock, ToRunnableError> {
let mut statements = Vec::new(); let mut statements = Vec::new();
for st in &s.statements { for st in &s.statements {
statements.push(statement(st, ginfo, &mut linfo)?); statements.push(statement(st, ginfo, &mut linfo)?);
@ -245,12 +200,12 @@ fn block(s: &SBlock, ginfo: &mut GInfo, mut linfo: LInfo) -> Result<RBlock, ToRu
Ok(RBlock { statements }) Ok(RBlock { statements })
} }
fn stypes(t: &mut VType, ginfo: &mut GInfo) { fn stypes(t: &mut VType, ginfo: &mut GlobalScriptInfo) {
for t in &mut t.types { for t in &mut t.types {
stype(t, ginfo); stype(t, ginfo);
} }
} }
fn stype(t: &mut VSingleType, ginfo: &mut GInfo) { fn stype(t: &mut VSingleType, ginfo: &mut GlobalScriptInfo) {
match t { match t {
VSingleType::Tuple(v) => { VSingleType::Tuple(v) => {
for t in v { for t in v {
@ -279,7 +234,7 @@ fn stype(t: &mut VSingleType, ginfo: &mut GInfo) {
} }
fn statement( fn statement(
s: &SStatement, s: &SStatement,
ginfo: &mut GInfo, ginfo: &mut GlobalScriptInfo,
linfo: &mut LInfo, linfo: &mut LInfo,
) -> Result<RStatement, ToRunnableError> { ) -> Result<RStatement, ToRunnableError> {
let mut statement = match &*s.statement { let mut statement = match &*s.statement {
@ -317,7 +272,7 @@ fn statement(
)); ));
} }
for (i, rarg) in rargs.iter().enumerate() { 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]); let out = rarg.fits_in(&func.input_types[i]);
if !out.is_empty() { if !out.is_empty() {
return Err(ToRunnableError::InvalidType { return Err(ToRunnableError::InvalidType {
@ -331,8 +286,8 @@ fn statement(
} else { } else {
// TODO: type-checking for builtins // TODO: type-checking for builtins
if let Some(builtin) = BuiltinFunction::get(v) { if let Some(builtin) = BuiltinFunction::get(v) {
let arg_types = rargs.iter().map(|v| v.out()).collect(); let arg_types = rargs.iter().map(|v| v.out(ginfo)).collect();
if builtin.can_take(&arg_types) { if builtin.can_take(&arg_types, ginfo) {
RStatementEnum::BuiltinFunction(builtin, rargs) RStatementEnum::BuiltinFunction(builtin, rargs)
} else { } else {
return Err(ToRunnableError::WrongInputsForBuiltinFunction(builtin, v.to_string(), arg_types)); return Err(ToRunnableError::WrongInputsForBuiltinFunction(builtin, v.to_string(), arg_types));
@ -341,12 +296,12 @@ fn statement(
// LIBRARY FUNCTION? // LIBRARY FUNCTION?
if let Some((libid, fnid)) = ginfo.lib_fns.get(v) { if let Some((libid, fnid)) = ginfo.lib_fns.get(v) {
let (_name, fn_in, fn_out) = &ginfo.libs[*libid].registered_fns[*fnid]; 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()) RStatementEnum::LibFunction(*libid, *fnid, rargs, fn_out.clone())
} else { } else {
// TODO! better error here // TODO! better error here
return Err(if fn_in.len() == rargs.len() { 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 { } else {
ToRunnableError::FunctionWrongArgCount(v.to_string(), fn_in.len(), rargs.len()) ToRunnableError::FunctionWrongArgCount(v.to_string(), fn_in.len(), rargs.len())
}); });
@ -375,7 +330,7 @@ fn statement(
SStatementEnum::If(c, t, e) => RStatementEnum::If( SStatementEnum::If(c, t, e) => RStatementEnum::If(
{ {
let condition = statement(&c, ginfo, linfo)?; 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], types: vec![VSingleType::Bool],
}); });
if out.is_empty() { if out.is_empty() {
@ -383,7 +338,7 @@ fn statement(
} else { } else {
return Err(ToRunnableError::InvalidType { return Err(ToRunnableError::InvalidType {
expected: VSingleType::Bool.into(), expected: VSingleType::Bool.into(),
found: condition.out(), found: condition.out(ginfo),
problematic: VType { types: out }, problematic: VType { types: out },
}); });
} }
@ -400,7 +355,7 @@ fn statement(
SStatementEnum::For(v, c, b) => { SStatementEnum::For(v, c, b) => {
let mut linfo = linfo.clone(); let mut linfo = linfo.clone();
let container = statement(&c, ginfo, &mut linfo)?; 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() { if inner.types.is_empty() {
return Err(ToRunnableError::ForLoopContainerHasNoInnerTypes); return Err(ToRunnableError::ForLoopContainerHasNoInnerTypes);
} }
@ -444,7 +399,8 @@ fn statement(
types_not_covered_req_error = true; types_not_covered_req_error = true;
types_not_covered = types_not_covered | { types_not_covered = types_not_covered | {
let mut v = val_type; 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() { for t in v.types.iter_mut() {
match t { match t {
VSingleType::EnumVariant(i, v) => { VSingleType::EnumVariant(i, v) => {
@ -452,18 +408,20 @@ fn statement(
make_readable(&mut v, ginfo); 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); *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() { VSingleType::Tuple(v) => for t in v.iter_mut() {
make_readable(t, ginfo) make_readable(t, ginfo)
} }
VSingleType::List(t) => make_readable(t, ginfo), VSingleType::List(t) | VSingleType::EnumVariantS(_, t) => make_readable(t, ginfo),
VSingleType::Reference(v) => { VSingleType::Reference(v) => {
let mut v = v.clone().to(); let mut v = v.clone().to();
make_readable(&mut v, ginfo); make_readable(&mut v, ginfo);
assert_eq!(v.types.len(), 1); assert_eq!(v.types.len(), 1);
*t = VSingleType::Reference(Box::new(v.types.remove(0))); *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(); let og_type = switch_on_v.1.clone(); // linfo.vars.get(match_on).unwrap().1.clone();
for case in cases { for case in cases {
let case_condition = statement(&case.0, ginfo, linfo)?; 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 refutable = false;
let mut success_output = VType { types: vec![] }; let mut success_output = VType { types: vec![] };
for case_type in case_condition_out.types.iter() { for case_type in case_condition_out.types.iter() {
@ -537,7 +495,7 @@ fn statement(
let st = statement(st, ginfo, linfo)?; let st = statement(st, ginfo, linfo)?;
let ok = 'ok: { let ok = 'ok: {
let mut one = false; let mut one = false;
for t in st.out().types { for t in st.out(ginfo).types {
one = true; one = true;
// only if all types are indexable by i // only if all types are indexable by i
match t { match t {
@ -554,7 +512,7 @@ fn statement(
if ok { if ok {
RStatementEnum::IndexFixed(st, *i) RStatementEnum::IndexFixed(st, *i)
} else { } else {
return Err(ToRunnableError::NotIndexableFixed(st.out(), *i)); return Err(ToRunnableError::NotIndexableFixed(st.out(ginfo), *i));
} }
} }
SStatementEnum::EnumVariant(variant, s) => RStatementEnum::EnumVariant({ SStatementEnum::EnumVariant(variant, s) => RStatementEnum::EnumVariant({
@ -573,7 +531,7 @@ fn statement(
.to(); .to();
// if force_output_type is set, verify that the real output type actually fits in the forced one. // 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 { 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); let problematic_types = real_output_type.fits_in(force_opt);
if problematic_types.is_empty() { if problematic_types.is_empty() {
statement.force_output_type = Some(force_opt.clone()); 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((opt, derefs)) = &s.output_to {
if let Some((var_id, var_out)) = linfo.vars.get(opt) { 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(); let mut var_derefd = var_out.clone();
for _ in 0..*derefs { for _ in 0..*derefs {
var_derefd = if let Some(v) = var_derefd.dereference() { var_derefd = if let Some(v) = var_derefd.dereference() {
@ -612,13 +570,13 @@ fn statement(
statement.output_to = Some((*var_id, *derefs)); statement.output_to = Some((*var_id, *derefs));
} }
} else { } else {
let mut out = statement.out(); let mut out = statement.out(ginfo);
for _ in 0..*derefs { for _ in 0..*derefs {
out = if let Some(v) = out.dereference() { out = if let Some(v) = out.dereference() {
v v
} else { } else {
return Err(ToRunnableError::CannotDereferenceTypeNTimes( return Err(ToRunnableError::CannotDereferenceTypeNTimes(
statement.out(), statement.out(ginfo),
*derefs, *derefs,
out, out,
)); ));

View File

@ -5,7 +5,7 @@ use std::{
use super::{ use super::{
code_runnable::RFunction, code_runnable::RFunction,
global_info::GSInfo, global_info::{GlobalScriptInfo, GSInfo},
val_type::{VSingleType, VType}, val_type::{VSingleType, VType},
}; };
@ -255,7 +255,7 @@ impl VData {
} }
impl VDataEnum { 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 { match self {
Self::Bool(true) => write!(f, "true"), Self::Bool(true) => write!(f, "true"),
Self::Bool(false) => write!(f, "false"), Self::Bool(false) => write!(f, "false"),
@ -290,7 +290,7 @@ impl VDataEnum {
} }
Self::EnumVariant(variant, inner) => { Self::EnumVariant(variant, inner) => {
if let Some(name) = if let Some(info) = info { if let Some(name) = if let Some(info) = info {
info.enums info.enum_variants
.iter() .iter()
.find_map(|(name, id)| if id == variant { Some(name) } else { None }) .find_map(|(name, id)| if id == variant { Some(name) } else { None })
} else { } else {
@ -312,7 +312,7 @@ impl Display for VDataEnum {
} }
impl VData { 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) self.data.fmtgs(f, info)
} }
} }

View File

@ -4,7 +4,7 @@ use std::{
ops::BitOr, ops::BitOr,
}; };
use super::global_info::GSInfo; use super::global_info::{GlobalScriptInfo, GSInfo};
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct VType { pub struct VType {
@ -24,20 +24,22 @@ pub enum VSingleType {
Reference(Box<Self>), Reference(Box<Self>),
EnumVariant(usize, VType), EnumVariant(usize, VType),
EnumVariantS(String, VType), EnumVariantS(String, VType),
// CustomType(usize), CustomType(usize),
// CustomTypeS(String), CustomTypeS(String),
} }
impl VSingleType { impl VSingleType {
// None => Cannot get, Some(t) => getting can return t or nothing // None => Cannot get, Some(t) => getting can return t or nothing
pub fn get(&self, i: usize) -> Option<VType> { pub fn get(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> {
match self { match self {
Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None, Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None,
Self::String => Some(VSingleType::String.into()), Self::String => Some(VSingleType::String.into()),
Self::Tuple(t) => t.get(i).cloned(), Self::Tuple(t) => t.get(i).cloned(),
Self::List(t) => Some(t.clone()), Self::List(t) => Some(t.clone()),
Self::Reference(r) => r.get(i), Self::Reference(r) => r.get(i, gsinfo),
Self::EnumVariant(_, t) | Self::EnumVariantS(_, t) => t.get(i), 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 { pub fn empty() -> Self {
Self { types: vec![] } Self { types: vec![] }
} }
pub fn get(&self, i: usize) -> Option<VType> { pub fn get(&self, i: usize, info: &GlobalScriptInfo) -> Option<VType> {
let mut out = VType { types: vec![] }; let mut out = VType { types: vec![] };
for t in &self.types { 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) Some(out)
} }
@ -80,15 +82,17 @@ impl VType {
} }
impl VSingleType { impl VSingleType {
pub fn get_any(&self) -> Option<VType> { pub fn get_any(&self, info: &GlobalScriptInfo) -> Option<VType> {
match self { match self {
Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None, Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None,
Self::String => Some(VSingleType::String.into()), Self::String => Some(VSingleType::String.into()),
Self::Tuple(t) => Some(t.iter().fold(VType { types: vec![] }, |a, b| a | b)), Self::Tuple(t) => Some(t.iter().fold(VType { types: vec![] }, |a, b| a | b)),
Self::List(t) => Some(t.clone()), Self::List(t) => Some(t.clone()),
Self::Reference(r) => r.get_any(), Self::Reference(r) => r.get_any(info),
Self::EnumVariant(_, t) => t.get_any(), Self::EnumVariant(_, t) => t.get_any(info),
Self::EnumVariantS(..) => unreachable!(), Self::EnumVariantS(..) => unreachable!(),
Self::CustomType(t) => info.custom_types[*t].get_any(info),
Self::CustomTypeS(_) => unreachable!(),
} }
} }
pub fn is_reference(&self) -> bool { pub fn is_reference(&self) -> bool {
@ -106,10 +110,10 @@ impl VSingleType {
} }
} }
impl VType { impl VType {
pub fn get_any(&self) -> Option<VType> { pub fn get_any(&self, info: &GlobalScriptInfo) -> Option<VType> {
let mut out = VType { types: vec![] }; let mut out = VType { types: vec![] };
for t in &self.types { 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) Some(out)
} }
@ -117,11 +121,11 @@ impl VType {
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. /// 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<VSingleType> { pub fn fits_in(&self, rhs: &Self, info: &GlobalScriptInfo) -> Vec<VSingleType> {
let mut no = vec![]; let mut no = vec![];
for t in &self.types { for t in &self.types {
// if t doesnt fit in any of rhs's 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()) no.push(t.clone())
} }
} }
@ -223,6 +227,7 @@ impl VSingleType {
v => v.to(), v => v.to(),
} }
} }
/// converts all Self::EnumVariantS to Self::EnumVariant
pub fn enum_variants(&mut self, enum_variants: &mut HashMap<String, usize>) { pub fn enum_variants(&mut self, enum_variants: &mut HashMap<String, usize>) {
match self { match self {
Self::Bool | Self::Int | Self::Float | Self::String => (), Self::Bool | Self::Int | Self::Float | Self::String => (),
@ -254,15 +259,20 @@ impl VSingleType {
v.enum_variants(enum_variants); v.enum_variants(enum_variants);
*self = Self::EnumVariant(e, v.clone()); *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) { 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::Reference(_), _) | (_, Self::Reference(_)) => false,
(Self::EnumVariant(v1, t1), Self::EnumVariant(v2, t2)) => { (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::EnumVariant(..), _) | (_, Self::EnumVariant(..)) => false,
(Self::EnumVariantS(..), _) | (_, Self::EnumVariantS(..)) => unreachable!(), (Self::EnumVariantS(..), _) | (_, Self::EnumVariantS(..)) => unreachable!(),
(Self::Bool, Self::Bool) (Self::Bool, Self::Bool)
@ -272,19 +282,19 @@ impl VSingleType {
(Self::Bool | Self::Int | Self::Float | Self::String, _) => false, (Self::Bool | Self::Int | Self::Float | Self::String, _) => false,
(Self::Tuple(a), Self::Tuple(b)) => { (Self::Tuple(a), Self::Tuple(b)) => {
if a.len() == b.len() { 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 { } else {
false false
} }
} }
(Self::Tuple(_), _) => 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::List(_), _) => false,
(Self::Function(a), Self::Function(b)) => 'func_out: { (Self::Function(a), Self::Function(b)) => 'func_out: {
for a in a { for a in a {
'search: { 'search: {
for b in b { 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) && a.0.iter().zip(b.0.iter()).all(|(a, b)| *a == *b)
{ {
break 'search; break 'search;
@ -296,7 +306,7 @@ impl VSingleType {
true true
} }
(Self::Function(..), _) => false, (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, (Self::Thread(..), _) => false,
} }
} }
@ -323,7 +333,7 @@ impl VType {
} }
impl VSingleType { 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 { match self {
Self::Bool => write!(f, "bool"), Self::Bool => write!(f, "bool"),
Self::Int => write!(f, "int"), Self::Int => write!(f, "int"),
@ -368,7 +378,7 @@ impl VSingleType {
} }
Self::EnumVariant(variant, inner) => { Self::EnumVariant(variant, inner) => {
if let Some(name) = if let Some(info) = info { if let Some(name) = if let Some(info) = info {
info.enums info.enum_variants
.iter() .iter()
.find_map(|(name, id)| if id == variant { Some(name) } else { None }) .find_map(|(name, id)| if id == variant { Some(name) } else { None })
} else { } else {
@ -396,7 +406,7 @@ impl Display for VSingleType {
} }
impl VType { 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() { for (i, t) in self.types.iter().enumerate() {
if i > 0 { if i > 0 {
write!(f, "/")?; write!(f, "/")?;

0
mers/src/tutor/base_comments.rs Normal file → Executable file
View File

0
mers/src/tutor/base_functions.rs Normal file → Executable file
View File

0
mers/src/tutor/base_return.rs Normal file → Executable file
View File

0
mers/src/tutor/base_types.rs Normal file → Executable file
View File

0
mers/src/tutor/base_values.rs Normal file → Executable file
View File

0
mers/src/tutor/base_variables.rs Normal file → Executable file
View File

0
mers/src/tutor/error_handling.rs Normal file → Executable file
View File

0
mers/src/tutor/menu.rs Normal file → Executable file
View File

0
mers/src/tutor/mod.rs Normal file → Executable file
View File

0
mersrandr.mers Normal file → Executable file
View File

0
my_macro.mers Normal file → Executable file
View File