mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
safety commit because i want to try cargo fix
This commit is contained in:
parent
690a4716fd
commit
8bafe58593
0
iterators.mers
Normal file → Executable file
0
iterators.mers
Normal file → Executable file
0
mers/src/interactive_mode.rs
Normal file → Executable file
0
mers/src/interactive_mode.rs
Normal file → Executable file
0
mers/src/lib.rs
Normal file → Executable file
0
mers/src/lib.rs
Normal file → Executable 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 => {
|
||||||
|
@ -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
0
mers/src/script/code_macro.rs
Normal file → Executable file
10
mers/src/script/code_parsed.rs
Normal file → Executable file
10
mers/src/script/code_parsed.rs
Normal file → Executable 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
53
mers/src/script/code_runnable.rs
Normal file → Executable 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
36
mers/src/script/global_info.rs
Normal file → Executable 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
104
mers/src/script/to_runnable.rs
Normal file → Executable 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,
|
||||||
));
|
));
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
0
mers/src/tutor/base_comments.rs
Normal file → Executable file
0
mers/src/tutor/base_functions.rs
Normal file → Executable file
0
mers/src/tutor/base_functions.rs
Normal file → Executable file
0
mers/src/tutor/base_return.rs
Normal file → Executable file
0
mers/src/tutor/base_return.rs
Normal file → Executable file
0
mers/src/tutor/base_types.rs
Normal file → Executable file
0
mers/src/tutor/base_types.rs
Normal file → Executable file
0
mers/src/tutor/base_values.rs
Normal file → Executable file
0
mers/src/tutor/base_values.rs
Normal file → Executable file
0
mers/src/tutor/base_variables.rs
Normal file → Executable file
0
mers/src/tutor/base_variables.rs
Normal file → Executable file
0
mers/src/tutor/error_handling.rs
Normal file → Executable file
0
mers/src/tutor/error_handling.rs
Normal file → Executable file
0
mers/src/tutor/menu.rs
Normal file → Executable file
0
mers/src/tutor/menu.rs
Normal file → Executable file
0
mers/src/tutor/mod.rs
Normal file → Executable file
0
mers/src/tutor/mod.rs
Normal file → Executable file
0
mersrandr.mers
Normal file → Executable file
0
mersrandr.mers
Normal file → Executable file
0
my_macro.mers
Normal file → Executable file
0
my_macro.mers
Normal file → Executable file
Loading…
Reference in New Issue
Block a user