mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
added the concept of references: prefix any (single) type or variable with & to get a reference. This is used for List.{push, insert, pop, remove, get} to avoid copying the list unnecessarily.
This commit is contained in:
parent
a4fbb8dd97
commit
d0cf7ab588
@ -141,11 +141,6 @@ fn parse_statement_adv(
|
|||||||
SStatementEnum::Tuple(v).into()
|
SStatementEnum::Tuple(v).into()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Some('$') => {
|
|
||||||
file.next();
|
|
||||||
file.skip_whitespaces();
|
|
||||||
Some(SStatementEnum::Variable(file.take_while(|v| !v.is_whitespace()).collect()).into())
|
|
||||||
}
|
|
||||||
Some('"') => {
|
Some('"') => {
|
||||||
file.next();
|
file.next();
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
@ -280,15 +275,22 @@ fn parse_statement_adv(
|
|||||||
break SStatementEnum::Value(VDataEnum::Bool(false).to()).into()
|
break SStatementEnum::Value(VDataEnum::Bool(false).to()).into()
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
// int, float, var
|
||||||
break {
|
break {
|
||||||
if let Ok(v) = start.parse() {
|
if let Ok(v) = start.parse() {
|
||||||
SStatementEnum::Value(VDataEnum::Int(v).to()).into()
|
SStatementEnum::Value(VDataEnum::Int(v).to()).into()
|
||||||
} else if let Ok(v) = start.replace(",", ".").parse() {
|
} else if let Ok(v) = start.replace(",", ".").parse() {
|
||||||
SStatementEnum::Value(VDataEnum::Float(v).to()).into()
|
SStatementEnum::Value(VDataEnum::Float(v).to()).into()
|
||||||
} else {
|
} else {
|
||||||
SStatementEnum::Variable(start.to_string()).into()
|
if start.starts_with('&') {
|
||||||
|
SStatementEnum::Variable(start[1..].to_string(), true)
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
SStatementEnum::Variable(start.to_string(), false)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,9 +380,7 @@ fn parse_type(file: &mut File) -> Result<VType, ParseError> {
|
|||||||
fn parse_type_adv(file: &mut File, in_fn_args: bool) -> Result<(VType, bool), ParseError> {
|
fn parse_type_adv(file: &mut File, in_fn_args: bool) -> Result<(VType, bool), ParseError> {
|
||||||
let mut types = vec![];
|
let mut types = vec![];
|
||||||
let mut closed_fn_args = false;
|
let mut closed_fn_args = false;
|
||||||
let mut count = 0;
|
|
||||||
loop {
|
loop {
|
||||||
count += 1;
|
|
||||||
let (st, closed_bracket) = parse_single_type_adv(file, in_fn_args)?;
|
let (st, closed_bracket) = parse_single_type_adv(file, in_fn_args)?;
|
||||||
types.push(st);
|
types.push(st);
|
||||||
if closed_bracket {
|
if closed_bracket {
|
||||||
@ -414,6 +414,13 @@ fn parse_single_type_adv(
|
|||||||
let mut closed_bracket_in_fn_args = false;
|
let mut closed_bracket_in_fn_args = false;
|
||||||
Ok((
|
Ok((
|
||||||
match file.next() {
|
match file.next() {
|
||||||
|
Some('&') => {
|
||||||
|
let parse_output = parse_single_type_adv(file, in_fn_args)?;
|
||||||
|
if parse_output.1 {
|
||||||
|
closed_bracket_in_fn_args = true;
|
||||||
|
}
|
||||||
|
VSingleType::Reference(Box::new(parse_output.0))
|
||||||
|
}
|
||||||
// Tuple or Array
|
// Tuple or Array
|
||||||
Some('[') => {
|
Some('[') => {
|
||||||
let mut types = vec![];
|
let mut types = vec![];
|
||||||
@ -439,6 +446,7 @@ fn parse_single_type_adv(
|
|||||||
loop {
|
loop {
|
||||||
match file.peek() {
|
match file.peek() {
|
||||||
Some(']') => break,
|
Some(']') => break,
|
||||||
|
Some('/') => break,
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
match file.next() {
|
match file.next() {
|
||||||
|
@ -59,7 +59,7 @@ pub enum SStatementEnum {
|
|||||||
Value(VData),
|
Value(VData),
|
||||||
Tuple(Vec<SStatement>),
|
Tuple(Vec<SStatement>),
|
||||||
List(Vec<SStatement>),
|
List(Vec<SStatement>),
|
||||||
Variable(String),
|
Variable(String, bool),
|
||||||
FunctionCall(String, Vec<SStatement>),
|
FunctionCall(String, Vec<SStatement>),
|
||||||
FunctionDefinition(Option<String>, SFunction),
|
FunctionDefinition(Option<String>, SFunction),
|
||||||
Block(SBlock),
|
Block(SBlock),
|
||||||
@ -266,9 +266,9 @@ pub mod to_runnable {
|
|||||||
RStatementEnum::Tuple(w)
|
RStatementEnum::Tuple(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SStatementEnum::Variable(v) => {
|
SStatementEnum::Variable(v, is_ref) => {
|
||||||
if let Some(var) = linfo.vars.get(v) {
|
if let Some(var) = linfo.vars.get(v) {
|
||||||
RStatementEnum::Variable(var.0, var.1.clone())
|
RStatementEnum::Variable(var.0, var.1.clone(), *is_ref)
|
||||||
} else {
|
} else {
|
||||||
return Err(ToRunnableError::UseOfUndefinedVariable(v.clone()));
|
return Err(ToRunnableError::UseOfUndefinedVariable(v.clone()));
|
||||||
}
|
}
|
||||||
@ -405,7 +405,7 @@ pub mod to_runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
RStatementEnum::Switch(
|
RStatementEnum::Switch(
|
||||||
RStatementEnum::Variable(switch_on_v.0, switch_on_out).to(),
|
RStatementEnum::Variable(switch_on_v.0, switch_on_out, false).to(),
|
||||||
ncases,
|
ncases,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -554,7 +554,7 @@ pub enum RStatementEnum {
|
|||||||
Value(VData),
|
Value(VData),
|
||||||
Tuple(Vec<RStatement>),
|
Tuple(Vec<RStatement>),
|
||||||
List(Vec<RStatement>),
|
List(Vec<RStatement>),
|
||||||
Variable(usize, VType), // Arc<Mutex<..>> here, because imagine variable in for loop that is used in a different thread -> we need multiple "same" variables
|
Variable(usize, VType, bool), // Arc<Mutex<..>> here, because imagine variable in for loop that is used in a different thread -> we need multiple "same" variables
|
||||||
FunctionCall(Arc<RFunction>, Vec<RStatement>),
|
FunctionCall(Arc<RFunction>, Vec<RStatement>),
|
||||||
BuiltinFunction(BuiltinFunction, Vec<RStatement>),
|
BuiltinFunction(BuiltinFunction, Vec<RStatement>),
|
||||||
Block(RBlock),
|
Block(RBlock),
|
||||||
@ -585,7 +585,13 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
VDataEnum::List(out, w).to()
|
VDataEnum::List(out, w).to()
|
||||||
}
|
}
|
||||||
Self::Variable(v, _) => vars[*v].lock().unwrap().clone(),
|
Self::Variable(v, _, is_ref) => {
|
||||||
|
if *is_ref {
|
||||||
|
VDataEnum::Reference(vars[*v].clone()).to()
|
||||||
|
} else {
|
||||||
|
vars[*v].lock().unwrap().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::FunctionCall(func, args) => {
|
Self::FunctionCall(func, args) => {
|
||||||
for (i, input) in func.inputs.iter().enumerate() {
|
for (i, input) in func.inputs.iter().enumerate() {
|
||||||
*vars[*input].lock().unwrap() = args[i].run(vars);
|
*vars[*input].lock().unwrap() = args[i].run(vars);
|
||||||
@ -627,6 +633,7 @@ impl RStatementEnum {
|
|||||||
vars[*v] = Arc::new(Mutex::new(c));
|
vars[*v] = Arc::new(Mutex::new(c));
|
||||||
b.run(&vars);
|
b.run(&vars);
|
||||||
};
|
};
|
||||||
|
|
||||||
match c.data {
|
match c.data {
|
||||||
VDataEnum::Int(v) => {
|
VDataEnum::Int(v) => {
|
||||||
for i in 0..v {
|
for i in 0..v {
|
||||||
@ -666,10 +673,28 @@ impl RStatementEnum {
|
|||||||
pub fn out(&self) -> VType {
|
pub fn out(&self) -> VType {
|
||||||
match self {
|
match self {
|
||||||
Self::Value(v) => v.out(),
|
Self::Value(v) => v.out(),
|
||||||
Self::Tuple(v) | Self::List(v) => {
|
Self::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out()).collect()).into(),
|
||||||
VSingleType::Tuple(v.iter().map(|v| v.out()).collect()).into()
|
Self::List(v) => VSingleType::List({
|
||||||
|
let mut types = VType { types: vec![] };
|
||||||
|
for t in v {
|
||||||
|
types = types | t.out();
|
||||||
|
}
|
||||||
|
types
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
Self::Variable(_, t, is_ref) => {
|
||||||
|
if *is_ref {
|
||||||
|
VType {
|
||||||
|
types: t
|
||||||
|
.types
|
||||||
|
.iter()
|
||||||
|
.map(|t| VSingleType::Reference(Box::new(t.clone())))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Self::Variable(_, t) => t.clone(),
|
|
||||||
Self::FunctionCall(f, _) => {
|
Self::FunctionCall(f, _) => {
|
||||||
eprintln!("Warn: generalizing a functions return type regardless of the inputs. Type-checker might assume this value can have more types than it really can.");
|
eprintln!("Warn: generalizing a functions return type regardless of the inputs. Type-checker might assume this value can have more types than it really can.");
|
||||||
f.out_all()
|
f.out_all()
|
||||||
@ -793,6 +818,7 @@ impl Display for VSingleType {
|
|||||||
Self::List(t) => write!(f, "[{t}]"),
|
Self::List(t) => write!(f, "[{t}]"),
|
||||||
Self::Function(args, out) => write!(f, "({args:?}) -> {out}"),
|
Self::Function(args, out) => write!(f, "({args:?}) -> {out}"),
|
||||||
Self::Thread(_) => write!(f, "THREAD"),
|
Self::Thread(_) => write!(f, "THREAD"),
|
||||||
|
Self::Reference(r) => write!(f, "&{r}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -822,7 +848,9 @@ impl Display for SStatementEnum {
|
|||||||
v.iter().map(|v| format!("{} ", v)).collect::<String>()
|
v.iter().map(|v| format!("{} ", v)).collect::<String>()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
SStatementEnum::Variable(v) => write!(f, "{v}"),
|
SStatementEnum::Variable(v, is_ref) => {
|
||||||
|
write!(f, "{}{v}", if *is_ref { "&" } else { "" })
|
||||||
|
}
|
||||||
SStatementEnum::FunctionCall(func, args) => {
|
SStatementEnum::FunctionCall(func, args) => {
|
||||||
write!(f, "{func}(")?;
|
write!(f, "{func}(")?;
|
||||||
for (i, arg) in args.iter().enumerate() {
|
for (i, arg) in args.iter().enumerate() {
|
||||||
@ -902,6 +930,7 @@ impl Display for VDataEnum {
|
|||||||
}
|
}
|
||||||
Self::Function(v) => write!(f, "{v}"),
|
Self::Function(v) => write!(f, "{v}"),
|
||||||
Self::Thread(..) => write!(f, "THREAD"),
|
Self::Thread(..) => write!(f, "THREAD"),
|
||||||
|
Self::Reference(r) => write!(f, "{}", r.lock().unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,20 @@ pub enum BuiltinFunction {
|
|||||||
// OS
|
// OS
|
||||||
RunCommand,
|
RunCommand,
|
||||||
RunCommandGetBytes,
|
RunCommandGetBytes,
|
||||||
|
// Math
|
||||||
|
Add,
|
||||||
|
Sub,
|
||||||
|
Mul,
|
||||||
|
Div,
|
||||||
|
Mod,
|
||||||
|
Pow,
|
||||||
|
// List
|
||||||
|
Push,
|
||||||
|
Insert,
|
||||||
|
Pop,
|
||||||
|
Remove,
|
||||||
|
Get,
|
||||||
|
Len,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuiltinFunction {
|
impl BuiltinFunction {
|
||||||
@ -62,6 +76,18 @@ impl BuiltinFunction {
|
|||||||
"string_to_bytes" => Self::StringToBytes,
|
"string_to_bytes" => Self::StringToBytes,
|
||||||
"run_command" => Self::RunCommand,
|
"run_command" => Self::RunCommand,
|
||||||
"run_command_get_bytes" => Self::RunCommandGetBytes,
|
"run_command_get_bytes" => Self::RunCommandGetBytes,
|
||||||
|
"add" => Self::Add,
|
||||||
|
"sub" => Self::Sub,
|
||||||
|
"mul" => Self::Mul,
|
||||||
|
"div" => Self::Div,
|
||||||
|
"mod" => Self::Mod,
|
||||||
|
"pow" => Self::Pow,
|
||||||
|
"push" => Self::Push,
|
||||||
|
"insert" => Self::Insert,
|
||||||
|
"pop" => Self::Pop,
|
||||||
|
"remove" => Self::Remove,
|
||||||
|
"get" => Self::Get,
|
||||||
|
"len" => Self::Len,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -74,7 +100,7 @@ impl BuiltinFunction {
|
|||||||
// String
|
// String
|
||||||
Self::ToString | Self::Format => VSingleType::String.into(),
|
Self::ToString | Self::Format => VSingleType::String.into(),
|
||||||
// !
|
// !
|
||||||
Self::Run | Self::Thread | Self::Await => {
|
Self::Run | Self::Thread | Self::Await | Self::Pop | Self::Remove | Self::Get => {
|
||||||
VType { types: vec![] } // TODO!
|
VType { types: vec![] } // TODO!
|
||||||
// unreachable!("this has to be implemented somewhere else!")
|
// unreachable!("this has to be implemented somewhere else!")
|
||||||
}
|
}
|
||||||
@ -136,6 +162,11 @@ impl BuiltinFunction {
|
|||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
Self::Add | Self::Sub | Self::Mul | Self::Div | Self::Mod | Self::Pow => VType {
|
||||||
|
types: vec![VSingleType::Int, VSingleType::Float],
|
||||||
|
},
|
||||||
|
Self::Push | Self::Insert => VSingleType::Tuple(vec![]).into(),
|
||||||
|
Self::Len => VSingleType::Int.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn run(&self, args: &Vec<RStatement>, vars: &Vec<Arc<Mutex<VData>>>) -> VData {
|
pub fn run(&self, args: &Vec<RStatement>, vars: &Vec<Arc<Mutex<VData>>>) -> VData {
|
||||||
@ -443,6 +474,220 @@ impl BuiltinFunction {
|
|||||||
unreachable!("run_command not 1 arg")
|
unreachable!("run_command not 1 arg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Self::Add => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
match (args[0].run(vars).data, args[1].run(vars).data) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a + b).to(),
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Float(a as f64 + b).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
|
VDataEnum::Float(a + b as f64).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a + b).to(),
|
||||||
|
_ => unreachable!("add: not a number"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("add: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Sub => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
match (args[0].run(vars).data, args[1].run(vars).data) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a - b).to(),
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Float(a as f64 - b).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
|
VDataEnum::Float(a - b as f64).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a - b).to(),
|
||||||
|
_ => unreachable!("sub: not a number"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("sub: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Mul => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
match (args[0].run(vars).data, args[1].run(vars).data) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a * b).to(),
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Float(a as f64 * b).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
|
VDataEnum::Float(a * b as f64).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a * b).to(),
|
||||||
|
_ => unreachable!("mul: not a number"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("mul: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Div => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
match (args[0].run(vars).data, args[1].run(vars).data) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a / b).to(),
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Float(a as f64 / b).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
|
VDataEnum::Float(a / b as f64).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a / b).to(),
|
||||||
|
_ => unreachable!("div: not a number"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("div: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Mod => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
match (args[0].run(vars).data, args[1].run(vars).data) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(a % b).to(),
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Float(a as f64 % b).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
|
VDataEnum::Float(a % b as f64).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => VDataEnum::Float(a % b).to(),
|
||||||
|
_ => unreachable!("mod: not a number"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("mod: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Pow => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
match (args[0].run(vars).data, args[1].run(vars).data) {
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Int(b)) => VDataEnum::Int(if b == 0 {
|
||||||
|
1
|
||||||
|
} else if b > 0 {
|
||||||
|
a.pow(b as _)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
})
|
||||||
|
.to(),
|
||||||
|
(VDataEnum::Int(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Float((a as f64).powf(b)).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Int(b)) => {
|
||||||
|
VDataEnum::Float(a.powi(b as _)).to()
|
||||||
|
}
|
||||||
|
(VDataEnum::Float(a), VDataEnum::Float(b)) => {
|
||||||
|
VDataEnum::Float(a.powf(b)).to()
|
||||||
|
}
|
||||||
|
_ => unreachable!("pow: not a number"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("pow: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Push => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
if let VDataEnum::Reference(v) = args[0].run(vars).data {
|
||||||
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
|
v.push(args[1].run(vars));
|
||||||
|
}
|
||||||
|
VDataEnum::Tuple(vec![]).to()
|
||||||
|
} else {
|
||||||
|
unreachable!("push: not a reference")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("push: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Insert => {
|
||||||
|
if args.len() == 3 {
|
||||||
|
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
||||||
|
(args[0].run(vars).data, args[1].run(vars).data)
|
||||||
|
{
|
||||||
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
|
v.insert(i as _, args[2].run(vars));
|
||||||
|
}
|
||||||
|
VDataEnum::Tuple(vec![]).to()
|
||||||
|
} else {
|
||||||
|
unreachable!("insert: not a reference and index")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("insert: not 3 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Pop => {
|
||||||
|
if args.len() == 1 {
|
||||||
|
if let VDataEnum::Reference(v) = args[0].run(vars).data {
|
||||||
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
|
v.pop().unwrap_or_else(|| VDataEnum::Tuple(vec![]).to())
|
||||||
|
} else {
|
||||||
|
unreachable!("pop: not a list")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("pop: not a reference")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("pop: not 1 arg")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Remove => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
||||||
|
(args[0].run(vars).data, args[1].run(vars).data)
|
||||||
|
{
|
||||||
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
|
if v.len() > i as _ && i >= 0 {
|
||||||
|
v.remove(i as _)
|
||||||
|
} else {
|
||||||
|
VDataEnum::Tuple(vec![]).to()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("remove: not a list")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("remove: not a reference and index")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("remove: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Get => {
|
||||||
|
if args.len() == 2 {
|
||||||
|
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) =
|
||||||
|
(args[0].run(vars).data, args[1].run(vars).data)
|
||||||
|
{
|
||||||
|
if let VDataEnum::List(_, v) = &mut v.lock().unwrap().data {
|
||||||
|
if i >= 0 {
|
||||||
|
match v.get(i as usize) {
|
||||||
|
Some(v) => v.clone(),
|
||||||
|
None => VDataEnum::Tuple(vec![]).to(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
VDataEnum::Tuple(vec![]).to()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("get: not a list")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("get: not a reference and index")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("get: not 2 args")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Len => {
|
||||||
|
if args.len() == 1 {
|
||||||
|
VDataEnum::Int(match args[0].run(vars).data {
|
||||||
|
VDataEnum::String(v) => v.len(),
|
||||||
|
VDataEnum::Tuple(v) => v.len(),
|
||||||
|
VDataEnum::List(_, v) => v.len(),
|
||||||
|
_ => unreachable!("len: invalid type"),
|
||||||
|
} as _)
|
||||||
|
.to()
|
||||||
|
} else {
|
||||||
|
unreachable!("len: not 1 arg")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ impl VData {
|
|||||||
f.out_all()
|
f.out_all()
|
||||||
}),
|
}),
|
||||||
VDataEnum::Thread(_, o) => VSingleType::Thread(o.clone()),
|
VDataEnum::Thread(_, o) => VSingleType::Thread(o.clone()),
|
||||||
|
VDataEnum::Reference(r) => r.lock().unwrap().out_single(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get(&self, i: usize) -> Option<Self> {
|
pub fn get(&self, i: usize) -> Option<Self> {
|
||||||
@ -49,6 +50,7 @@ pub enum VDataEnum {
|
|||||||
List(VType, Vec<VData>),
|
List(VType, Vec<VData>),
|
||||||
Function(RFunction),
|
Function(RFunction),
|
||||||
Thread(VDataThread, VType),
|
Thread(VDataThread, VType),
|
||||||
|
Reference(Arc<Mutex<VData>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -136,6 +138,7 @@ impl VDataEnum {
|
|||||||
None => None,
|
None => None,
|
||||||
},
|
},
|
||||||
Self::Tuple(v) | Self::List(_, v) => v.get(i).cloned(),
|
Self::Tuple(v) | Self::List(_, v) => v.get(i).cloned(),
|
||||||
|
Self::Reference(r) => r.lock().unwrap().get(i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,6 +150,7 @@ impl VSingleType {
|
|||||||
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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,6 +213,7 @@ pub enum VSingleType {
|
|||||||
List(VType),
|
List(VType),
|
||||||
Function(Vec<VType>, VType),
|
Function(Vec<VType>, VType),
|
||||||
Thread(VType),
|
Thread(VType),
|
||||||
|
Reference(Box<Self>),
|
||||||
}
|
}
|
||||||
impl VSingleType {
|
impl VSingleType {
|
||||||
pub fn inner_types(&self) -> Vec<VSingleType> {
|
pub fn inner_types(&self) -> Vec<VSingleType> {
|
||||||
@ -256,6 +261,8 @@ impl VSingleType {
|
|||||||
(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).is_empty(),
|
||||||
(Self::Thread(..), _) => false,
|
(Self::Thread(..), _) => false,
|
||||||
|
(Self::Reference(r), Self::Reference(b)) => r.fits_in(b),
|
||||||
|
(Self::Reference(_), _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user