mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
changed VData system again, renamed src/script to src/lang and added src/c.mers, which is an example something that currently does not work properly due to the VData implementation (and serves as a reminder to fix the issue)
This commit is contained in:
parent
f8102c8fe6
commit
aff55fdc9e
@ -25,4 +25,3 @@ for word text.regex("\\S+").assume_no_enum()
|
|||||||
words = rnd()
|
words = rnd()
|
||||||
sleep(0.75)
|
sleep(0.75)
|
||||||
}
|
}
|
||||||
println(" ~ ~ ~ ~ ~ ~ ~ ~ ~ ~")
|
|
||||||
|
@ -6,5 +6,10 @@ list = [1 2 3 4 5 6 7 8 9 ...]
|
|||||||
// second.debug()
|
// second.debug()
|
||||||
|
|
||||||
&list.get_ref(2).assume1() = 24
|
&list.get_ref(2).assume1() = 24
|
||||||
|
should_not_be_changeable = &list.get(3).assume1()
|
||||||
|
should_not_be_changeable = 24
|
||||||
|
|
||||||
|
if list.get(2) != [24] println("[!!] list.get(2) != 24 (was {0})".format(list.get(2).to_string()))
|
||||||
|
if list.get(3) == [24] println("[!!] list.get(3) == 24")
|
||||||
|
|
||||||
list.debug()
|
list.debug()
|
||||||
|
@ -6,7 +6,7 @@ t = thread(() {
|
|||||||
println("got words from word list!")
|
println("got words from word list!")
|
||||||
})
|
})
|
||||||
|
|
||||||
sleep(0.5)
|
sleep(0.1)
|
||||||
|
|
||||||
// this will finish before the thread does.
|
// this will finish before the thread does.
|
||||||
http_get("https:\//github.com/").assume_no_enum()
|
http_get("https:\//github.com/").assume_no_enum()
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
a = 1
|
|
||||||
b = 2
|
|
||||||
a.debug()
|
|
||||||
b.debug()
|
|
4
mers/c.mers
Normal file
4
mers/c.mers
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
list = [1 ...]
|
||||||
|
b = list
|
||||||
|
&list.pop()
|
||||||
|
list
|
File diff suppressed because it is too large
Load Diff
@ -8,15 +8,34 @@ use super::{
|
|||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum RStatementEnum {
|
||||||
|
Value(VData),
|
||||||
|
Tuple(Vec<RStatement>),
|
||||||
|
List(Vec<RStatement>),
|
||||||
|
Variable(Arc<Mutex<VData>>, VType, bool),
|
||||||
|
FunctionCall(Arc<RFunction>, Vec<RStatement>),
|
||||||
|
BuiltinFunction(BuiltinFunction, Vec<RStatement>),
|
||||||
|
LibFunction(usize, usize, Vec<RStatement>, VType),
|
||||||
|
Block(RBlock),
|
||||||
|
If(RStatement, RStatement, Option<RStatement>),
|
||||||
|
Loop(RStatement),
|
||||||
|
For(Arc<Mutex<VData>>, RStatement, RStatement),
|
||||||
|
Switch(RStatement, Vec<(VType, RStatement)>),
|
||||||
|
Match(Arc<Mutex<VData>>, Vec<(RStatement, RStatement)>),
|
||||||
|
IndexFixed(RStatement, usize),
|
||||||
|
EnumVariant(usize, RStatement),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct RBlock {
|
pub struct RBlock {
|
||||||
pub statements: Vec<RStatement>,
|
pub statements: Vec<RStatement>,
|
||||||
}
|
}
|
||||||
impl RBlock {
|
impl RBlock {
|
||||||
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
pub fn run(&self, info: &GSInfo) -> VData {
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
for statement in &self.statements {
|
for statement in &self.statements {
|
||||||
last = Some(statement.run(vars, info));
|
last = Some(statement.run(info));
|
||||||
}
|
}
|
||||||
if let Some(v) = last {
|
if let Some(v) = last {
|
||||||
v
|
v
|
||||||
@ -37,14 +56,14 @@ impl RBlock {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct RFunction {
|
pub struct RFunction {
|
||||||
pub inputs: Vec<usize>,
|
pub inputs: Vec<Arc<Mutex<VData>>>,
|
||||||
pub input_types: Vec<VType>,
|
pub input_types: Vec<VType>,
|
||||||
pub input_output_map: Vec<(Vec<VSingleType>, VType)>,
|
pub input_output_map: Vec<(Vec<VSingleType>, VType)>,
|
||||||
pub block: RBlock,
|
pub block: RBlock,
|
||||||
}
|
}
|
||||||
impl RFunction {
|
impl RFunction {
|
||||||
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
pub fn run(&self, info: &GSInfo) -> VData {
|
||||||
self.block.run(vars, info)
|
self.block.run(info)
|
||||||
}
|
}
|
||||||
pub fn out(&self, input_types: &Vec<VSingleType>) -> VType {
|
pub fn out(&self, input_types: &Vec<VSingleType>) -> VType {
|
||||||
self.input_output_map
|
self.input_output_map
|
||||||
@ -87,18 +106,25 @@ pub struct RStatement {
|
|||||||
pub force_output_type: Option<VType>,
|
pub force_output_type: Option<VType>,
|
||||||
}
|
}
|
||||||
impl RStatement {
|
impl RStatement {
|
||||||
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
pub fn run(&self, info: &GSInfo) -> VData {
|
||||||
let out = self.statement.run(vars, info);
|
let out = self.statement.run(info);
|
||||||
if let Some((v, derefs, is_init)) = &self.output_to {
|
if let Some((v, derefs, is_init)) = &self.output_to {
|
||||||
let mut val = v.run(vars, info);
|
'init: {
|
||||||
// even if 0 derefs, deref once because it *has* to end on a reference (otherwise writing to it would be unacceptable as the value might not expect to be modified)
|
if *is_init && *derefs == 0 {
|
||||||
for _ in 0..(derefs + 1) {
|
if let RStatementEnum::Variable(var, _, _) = v.statement.as_ref() {
|
||||||
val = match val.inner().deref() {
|
*var.lock().unwrap() = out;
|
||||||
Some(v) => v,
|
break 'init;
|
||||||
None => unreachable!("can't dereference..."),
|
}
|
||||||
};
|
}
|
||||||
|
let mut val = v.run(info);
|
||||||
|
for _ in 0..(*derefs + 1) {
|
||||||
|
val = match val.deref() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => unreachable!("can't dereference..."),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
val.assign(out);
|
||||||
}
|
}
|
||||||
val.assign(out.inner());
|
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
} else {
|
} else {
|
||||||
out
|
out
|
||||||
@ -118,32 +144,14 @@ impl RStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum RStatementEnum {
|
|
||||||
Value(VData),
|
|
||||||
Tuple(Vec<RStatement>),
|
|
||||||
List(Vec<RStatement>),
|
|
||||||
Variable(usize, VType, bool),
|
|
||||||
FunctionCall(Arc<RFunction>, Vec<RStatement>),
|
|
||||||
BuiltinFunction(BuiltinFunction, Vec<RStatement>),
|
|
||||||
LibFunction(usize, usize, Vec<RStatement>, VType),
|
|
||||||
Block(RBlock),
|
|
||||||
If(RStatement, RStatement, Option<RStatement>),
|
|
||||||
Loop(RStatement),
|
|
||||||
For(usize, RStatement, RStatement),
|
|
||||||
Switch(RStatement, Vec<(VType, RStatement)>),
|
|
||||||
Match(usize, Vec<(RStatement, RStatement)>),
|
|
||||||
IndexFixed(RStatement, usize),
|
|
||||||
EnumVariant(usize, RStatement),
|
|
||||||
}
|
|
||||||
impl RStatementEnum {
|
impl RStatementEnum {
|
||||||
pub fn run(&self, vars: &mut Vec<VData>, info: &GSInfo) -> VData {
|
pub fn run(&self, info: &GSInfo) -> VData {
|
||||||
match self {
|
match self {
|
||||||
Self::Value(v) => v.clone(),
|
Self::Value(v) => v.clone(),
|
||||||
Self::Tuple(v) => {
|
Self::Tuple(v) => {
|
||||||
let mut w = vec![];
|
let mut w = vec![];
|
||||||
for v in v {
|
for v in v {
|
||||||
w.push(v.run(vars, info));
|
w.push(v.run(info));
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(w).to()
|
VDataEnum::Tuple(w).to()
|
||||||
}
|
}
|
||||||
@ -151,7 +159,7 @@ impl RStatementEnum {
|
|||||||
let mut w = vec![];
|
let mut w = vec![];
|
||||||
let mut out = VType { types: vec![] };
|
let mut out = VType { types: vec![] };
|
||||||
for v in v {
|
for v in v {
|
||||||
let val = v.run(vars, info);
|
let val = v.run(info);
|
||||||
out = out | val.out();
|
out = out | val.out();
|
||||||
w.push(val);
|
w.push(val);
|
||||||
}
|
}
|
||||||
@ -159,30 +167,29 @@ impl RStatementEnum {
|
|||||||
}
|
}
|
||||||
Self::Variable(v, _, is_ref) => {
|
Self::Variable(v, _, is_ref) => {
|
||||||
if *is_ref {
|
if *is_ref {
|
||||||
// shared mutability (clone_mut)
|
VDataEnum::Reference(v.lock().unwrap().clone_mut()).to()
|
||||||
VDataEnum::Reference(vars[*v].clone_mut()).to()
|
|
||||||
} else {
|
} else {
|
||||||
// Copy on Write (clone)
|
v.lock().unwrap().clone_data()
|
||||||
vars[*v].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] = args[i].run(vars, info);
|
input.lock().unwrap().assign(args[i].run(info));
|
||||||
}
|
}
|
||||||
func.run(vars, info)
|
func.run(info)
|
||||||
}
|
}
|
||||||
Self::BuiltinFunction(v, args) => v.run(args, vars, info),
|
Self::BuiltinFunction(v, args) => v.run(args, info),
|
||||||
Self::LibFunction(libid, fnid, args, _) => info.libs[*libid]
|
Self::LibFunction(libid, fnid, args, _) => {
|
||||||
.run_fn(*fnid, args.iter().map(|arg| arg.run(vars, info)).collect()),
|
info.libs[*libid].run_fn(*fnid, args.iter().map(|arg| arg.run(info)).collect())
|
||||||
Self::Block(b) => b.run(vars, info),
|
}
|
||||||
Self::If(c, t, e) => {
|
Self::Block(b) => b.run(info),
|
||||||
if let VDataEnum::Bool(v) = &c.run(vars, info).data().0 {
|
Self::If(c, t, e) => c.run(info).operate_on_data_immut(|v| {
|
||||||
|
if let VDataEnum::Bool(v) = v {
|
||||||
if *v {
|
if *v {
|
||||||
t.run(vars, info)
|
t.run(info)
|
||||||
} else {
|
} else {
|
||||||
if let Some(e) = e {
|
if let Some(e) = e {
|
||||||
e.run(vars, info)
|
e.run(info)
|
||||||
} else {
|
} else {
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
}
|
}
|
||||||
@ -190,75 +197,71 @@ impl RStatementEnum {
|
|||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
Self::Loop(c) => loop {
|
Self::Loop(c) => loop {
|
||||||
// loops will break if the value matches.
|
// loops will break if the value matches.
|
||||||
if let Some(break_val) = c.run(vars, info).inner().matches() {
|
if let Some(break_val) = c.run(info).matches() {
|
||||||
break break_val;
|
break break_val;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Self::For(v, c, b) => {
|
Self::For(v, c, b) => {
|
||||||
// matching values also break with value from a for loop.
|
// matching values also break with value from a for loop.
|
||||||
let c = c.run(vars, info);
|
c.run(info).operate_on_data_immut(|c: &VDataEnum| {
|
||||||
let mut vars = vars.clone();
|
let mut in_loop = |c: VData| {
|
||||||
let in_loop = |vars: &mut Vec<VData>, c| {
|
*v.lock().unwrap() = c;
|
||||||
vars[*v] = c;
|
b.run(info)
|
||||||
b.run(vars, info)
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let mut oval = VDataEnum::Tuple(vec![]).to();
|
let mut oval = VDataEnum::Tuple(vec![]).to();
|
||||||
match &c.data().0 {
|
match c {
|
||||||
VDataEnum::Int(v) => {
|
VDataEnum::Int(v) => {
|
||||||
for i in 0..*v {
|
for i in 0..*v {
|
||||||
if let Some(v) =
|
if let Some(v) = in_loop(VDataEnum::Int(i).to()).matches() {
|
||||||
in_loop(&mut vars, VDataEnum::Int(i).to()).inner().matches()
|
oval = v;
|
||||||
{
|
break;
|
||||||
oval = v;
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
VDataEnum::String(v) => {
|
||||||
|
for ch in v.chars() {
|
||||||
|
if let Some(v) =
|
||||||
|
in_loop(VDataEnum::String(ch.to_string()).to()).matches()
|
||||||
|
{
|
||||||
|
oval = v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VDataEnum::Tuple(v) | VDataEnum::List(_, v) => {
|
||||||
|
for v in v {
|
||||||
|
if let Some(v) = in_loop(v.clone()).matches() {
|
||||||
|
oval = v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VDataEnum::Function(f) => loop {
|
||||||
|
if let Some(v) = f.run(info).matches() {
|
||||||
|
if let Some(v) = in_loop(v).matches() {
|
||||||
|
oval = v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
VDataEnum::String(v) => {
|
oval
|
||||||
for ch in v.chars() {
|
})
|
||||||
if let Some(v) =
|
|
||||||
in_loop(&mut vars, VDataEnum::String(ch.to_string()).to())
|
|
||||||
.inner()
|
|
||||||
.matches()
|
|
||||||
{
|
|
||||||
oval = v;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VDataEnum::Tuple(v) | VDataEnum::List(_, v) => {
|
|
||||||
for v in v {
|
|
||||||
if let Some(v) = in_loop(&mut vars, v.clone()).inner().matches() {
|
|
||||||
oval = v;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VDataEnum::Function(f) => loop {
|
|
||||||
if let Some(v) = f.run(&mut vars, info).inner().matches() {
|
|
||||||
if let Some(v) = in_loop(&mut vars, v).inner().matches() {
|
|
||||||
oval = v;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
oval
|
|
||||||
}
|
}
|
||||||
Self::Switch(switch_on, cases) => {
|
Self::Switch(switch_on, cases) => {
|
||||||
let switch_on = switch_on.run(vars, info);
|
let switch_on = switch_on.run(info);
|
||||||
let switch_on_type = switch_on.out();
|
let switch_on_type = switch_on.out();
|
||||||
let mut out = VDataEnum::Tuple(vec![]).to();
|
let mut out = VDataEnum::Tuple(vec![]).to();
|
||||||
for (case_type, case_action) in cases.iter() {
|
for (case_type, case_action) in cases.iter() {
|
||||||
if switch_on_type.fits_in(case_type, info).is_empty() {
|
if switch_on_type.fits_in(case_type, info).is_empty() {
|
||||||
out = case_action.run(vars, info);
|
out = case_action.run(info);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,17 +270,17 @@ impl RStatementEnum {
|
|||||||
Self::Match(match_on, cases) => 'm: {
|
Self::Match(match_on, cases) => 'm: {
|
||||||
for (case_condition, case_action) in cases {
|
for (case_condition, case_action) in cases {
|
||||||
// [t] => Some(t), t => Some(t), [] | false => None
|
// [t] => Some(t), t => Some(t), [] | false => None
|
||||||
if let Some(v) = case_condition.run(vars, info).inner().matches() {
|
if let Some(v) = case_condition.run(info).matches() {
|
||||||
let og = { std::mem::replace(&mut vars[*match_on], v) };
|
let og = { std::mem::replace(&mut *match_on.lock().unwrap(), v) };
|
||||||
let res = case_action.run(vars, info);
|
let res = case_action.run(info);
|
||||||
vars[*match_on] = og;
|
*match_on.lock().unwrap() = og;
|
||||||
break 'm res;
|
break 'm res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VDataEnum::Tuple(vec![]).to()
|
VDataEnum::Tuple(vec![]).to()
|
||||||
}
|
}
|
||||||
Self::IndexFixed(st, i) => st.run(vars, info).get(*i, false).unwrap(),
|
Self::IndexFixed(st, i) => st.run(info).get(*i).unwrap(),
|
||||||
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(info))).to(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn out(&self, info: &GlobalScriptInfo) -> VType {
|
pub fn out(&self, info: &GlobalScriptInfo) -> VType {
|
||||||
@ -376,7 +379,7 @@ impl RScript {
|
|||||||
Ok(Self { main, info })
|
Ok(Self { main, info })
|
||||||
}
|
}
|
||||||
pub fn run(&self, args: Vec<String>) -> VData {
|
pub fn run(&self, args: Vec<String>) -> VData {
|
||||||
let mut vars = Vec::with_capacity(self.info.vars);
|
let mut vars = vec![];
|
||||||
vars.push(
|
vars.push(
|
||||||
VDataEnum::List(
|
VDataEnum::List(
|
||||||
VSingleType::String.into(),
|
VSingleType::String.into(),
|
||||||
@ -386,10 +389,7 @@ impl RScript {
|
|||||||
)
|
)
|
||||||
.to(),
|
.to(),
|
||||||
);
|
);
|
||||||
for _i in 1..self.info.vars {
|
self.main.run(&self.info)
|
||||||
vars.push(VDataEnum::Tuple(vec![]).to());
|
|
||||||
}
|
|
||||||
self.main.run(&mut vars, &self.info)
|
|
||||||
}
|
}
|
||||||
pub fn info(&self) -> &GSInfo {
|
pub fn info(&self) -> &GSInfo {
|
||||||
&self.info
|
&self.info
|
@ -8,8 +8,6 @@ pub type GSInfo = Arc<GlobalScriptInfo>;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GlobalScriptInfo {
|
pub struct GlobalScriptInfo {
|
||||||
pub vars: usize,
|
|
||||||
|
|
||||||
pub libs: Vec<libs::Lib>,
|
pub libs: Vec<libs::Lib>,
|
||||||
pub lib_fns: HashMap<String, (usize, usize)>,
|
pub lib_fns: HashMap<String, (usize, usize)>,
|
||||||
|
|
||||||
@ -28,7 +26,6 @@ impl GlobalScriptInfo {
|
|||||||
impl Default for GlobalScriptInfo {
|
impl Default for GlobalScriptInfo {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
vars: 0,
|
|
||||||
libs: vec![],
|
libs: vec![],
|
||||||
lib_fns: HashMap::new(),
|
lib_fns: HashMap::new(),
|
||||||
enum_variants: Self::default_enum_variants(),
|
enum_variants: Self::default_enum_variants(),
|
0
mers/src/script/mod.rs → mers/src/lang/mod.rs
Executable file → Normal file
0
mers/src/script/mod.rs → mers/src/lang/mod.rs
Executable file → Normal file
@ -1,17 +1,17 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
sync::Arc,
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
libs,
|
lang::{
|
||||||
script::{
|
|
||||||
builtins,
|
builtins,
|
||||||
global_info::GlobalScriptInfo,
|
global_info::GlobalScriptInfo,
|
||||||
val_data::VDataEnum,
|
val_data::{VData, VDataEnum},
|
||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
},
|
},
|
||||||
|
libs,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -158,7 +158,7 @@ impl ToRunnableError {
|
|||||||
// Local, used to keep local variables separated
|
// Local, used to keep local variables separated
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct LInfo {
|
struct LInfo {
|
||||||
vars: HashMap<String, (usize, VType)>,
|
vars: HashMap<String, (Arc<Mutex<VData>>, VType)>,
|
||||||
fns: HashMap<String, Arc<RFunction>>,
|
fns: HashMap<String, Arc<RFunction>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ fn get_all_functions(
|
|||||||
s: &SFunction,
|
s: &SFunction,
|
||||||
ginfo: &mut GlobalScriptInfo,
|
ginfo: &mut GlobalScriptInfo,
|
||||||
linfo: &mut LInfo,
|
linfo: &mut LInfo,
|
||||||
input_vars: &Vec<usize>,
|
input_vars: &Vec<Arc<Mutex<VData>>>,
|
||||||
inputs: &mut Vec<VSingleType>,
|
inputs: &mut Vec<VSingleType>,
|
||||||
out: &mut Vec<(Vec<VSingleType>, VType)>,
|
out: &mut Vec<(Vec<VSingleType>, VType)>,
|
||||||
) -> Result<(), ToRunnableError> {
|
) -> Result<(), ToRunnableError> {
|
||||||
@ -240,12 +240,12 @@ fn function(
|
|||||||
for (iname, itype) in &s.inputs {
|
for (iname, itype) in &s.inputs {
|
||||||
let mut itype = itype.to_owned();
|
let mut itype = itype.to_owned();
|
||||||
stypes(&mut itype, ginfo)?;
|
stypes(&mut itype, ginfo)?;
|
||||||
|
let var = Arc::new(Mutex::new(VData::new_placeholder()));
|
||||||
linfo
|
linfo
|
||||||
.vars
|
.vars
|
||||||
.insert(iname.clone(), (ginfo.vars, itype.clone()));
|
.insert(iname.clone(), (Arc::clone(&var), itype.clone()));
|
||||||
input_vars.push(ginfo.vars);
|
input_vars.push(var);
|
||||||
input_types.push(itype);
|
input_types.push(itype);
|
||||||
ginfo.vars += 1;
|
|
||||||
}
|
}
|
||||||
let mut all_outs = vec![];
|
let mut all_outs = vec![];
|
||||||
get_all_functions(
|
get_all_functions(
|
||||||
@ -367,13 +367,19 @@ fn statement_adv(
|
|||||||
if !linfo.vars.contains_key(v) {
|
if !linfo.vars.contains_key(v) {
|
||||||
if let Some((t, is_init)) = to_be_assigned_to {
|
if let Some((t, is_init)) = to_be_assigned_to {
|
||||||
*is_init = true;
|
*is_init = true;
|
||||||
linfo.vars.insert(v.to_owned(), (ginfo.vars, t));
|
linfo.vars.insert(v.to_owned(), (Arc::new(Mutex::new(VData::new_placeholder())), t));
|
||||||
ginfo.vars += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(var) = linfo.vars.get(v) {
|
if let Some(var) = linfo.vars.get(v) {
|
||||||
RStatementEnum::Variable(var.0, {
|
RStatementEnum::Variable(
|
||||||
let mut v = var.1.clone(); stypes(&mut v, ginfo)?; v }, *is_ref)
|
Arc::clone(&var.0),
|
||||||
|
{
|
||||||
|
let mut v = var.1.clone();
|
||||||
|
stypes(&mut v, ginfo)?;
|
||||||
|
v
|
||||||
|
},
|
||||||
|
*is_ref
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(ToRunnableError::UseOfUndefinedVariable(v.clone()));
|
return Err(ToRunnableError::UseOfUndefinedVariable(v.clone()));
|
||||||
}
|
}
|
||||||
@ -442,7 +448,7 @@ fn statement_adv(
|
|||||||
} else {
|
} else {
|
||||||
// anonymous function => return as value
|
// anonymous function => return as value
|
||||||
RStatementEnum::Value(
|
RStatementEnum::Value(
|
||||||
VDataEnum::Function(function(f, ginfo, linfo.clone())?).to(),
|
VDataEnum::Function(Arc::new(function(f, ginfo, linfo.clone())?)).to(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,11 +485,10 @@ fn statement_adv(
|
|||||||
if inner.types.is_empty() {
|
if inner.types.is_empty() {
|
||||||
return Err(ToRunnableError::ForLoopContainerHasNoInnerTypes);
|
return Err(ToRunnableError::ForLoopContainerHasNoInnerTypes);
|
||||||
}
|
}
|
||||||
|
let for_loop_var = Arc::new(Mutex::new(VData::new_placeholder()));
|
||||||
linfo
|
linfo
|
||||||
.vars
|
.vars
|
||||||
.insert(v.clone(), (ginfo.vars, inner));
|
.insert(v.clone(), (Arc::clone(&for_loop_var), inner));
|
||||||
let for_loop_var = ginfo.vars;
|
|
||||||
ginfo.vars += 1;
|
|
||||||
let block = statement(&b, ginfo, &mut linfo)?;
|
let block = statement(&b, ginfo, &mut linfo)?;
|
||||||
let o = RStatementEnum::For(for_loop_var, container, block);
|
let o = RStatementEnum::For(for_loop_var, container, block);
|
||||||
o
|
o
|
@ -1,6 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Debug, Display, Formatter},
|
fmt::{self, Debug, Display, Formatter},
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex, MutexGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -9,122 +9,6 @@ use super::{
|
|||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct VData {
|
|
||||||
/// (_, mutable) - if false, behave as CopyOnWrite.
|
|
||||||
pub data: Arc<Mutex<(VDataEnum, bool)>>,
|
|
||||||
}
|
|
||||||
impl VData {
|
|
||||||
/// if self is mutable, assigns the new value to the mutex.
|
|
||||||
/// if self is immutable, creates a new mutex and sets self to mutable.
|
|
||||||
pub fn assign(&mut self, new_val: VDataEnum) {
|
|
||||||
{
|
|
||||||
let mut d = self.data.lock().unwrap();
|
|
||||||
if d.1 {
|
|
||||||
d.0 = new_val;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #[cfg(debug_assertions)]
|
|
||||||
// eprintln!("VData: assign: overwriting my previous Arc because it was immutable.");
|
|
||||||
*self = new_val.to();
|
|
||||||
}
|
|
||||||
pub fn inner_replace(&mut self, new_val: VDataEnum) -> VDataEnum {
|
|
||||||
{
|
|
||||||
let mut d = self.data.lock().unwrap();
|
|
||||||
if d.1 {
|
|
||||||
return std::mem::replace(&mut d.0, new_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let o = self.data().0.clone();
|
|
||||||
*self = new_val.to();
|
|
||||||
o
|
|
||||||
}
|
|
||||||
/// returns the contained VDataEnum. May or may not clone.
|
|
||||||
pub fn inner(self) -> VDataEnum {
|
|
||||||
// Arc::unwrap_or_clone(self.data).lock().unwrap().0
|
|
||||||
let o = match Arc::try_unwrap(self.data) {
|
|
||||||
Ok(v) => std::mem::replace(&mut v.lock().unwrap().0, VDataEnum::Bool(false)),
|
|
||||||
Err(e) => e.lock().unwrap().0.clone(),
|
|
||||||
};
|
|
||||||
o
|
|
||||||
}
|
|
||||||
/// ensures self is mutable, then returns a new instance of VData that is also mutable and uses the same Arc<Mutex<_>>.
|
|
||||||
pub fn clone_mut(&mut self) -> Self {
|
|
||||||
// if not mutable, copy and set to mutable.
|
|
||||||
self.make_mut();
|
|
||||||
// now, both self and the returned value are set to mutable and share the same mutex.
|
|
||||||
let o = self.clone_mut_assume();
|
|
||||||
o
|
|
||||||
}
|
|
||||||
/// like clone_mut, but assumes self is already mutable, and therefor does not need to mutate self
|
|
||||||
/// as the Arc<Mutex<_>> will stay the same.
|
|
||||||
pub fn clone_mut_assume(&self) -> Self {
|
|
||||||
Self {
|
|
||||||
data: Arc::clone(&self.data),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn ptr_eq(&self, rhs: &Self) -> bool {
|
|
||||||
Arc::ptr_eq(&self.data, &rhs.data)
|
|
||||||
}
|
|
||||||
/// makes self mutable. might clone.
|
|
||||||
pub fn make_mut(&mut self) -> &mut Self {
|
|
||||||
{
|
|
||||||
let mut s = self.data();
|
|
||||||
if !s.1 {
|
|
||||||
if Arc::strong_count(&self.data) > 1 {
|
|
||||||
// not mutable yet - clone the value to avoid modifying an immutable one.
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!("VData: actually copying value due to mutation of an immutable shared value. (strong count: {})", Arc::strong_count(&self.data));
|
|
||||||
*s = (s.0.clone(), true);
|
|
||||||
} else {
|
|
||||||
// value was immutable, but not shared, so we can just make it mutable.
|
|
||||||
s.1 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn data(&self) -> std::sync::MutexGuard<(VDataEnum, bool)> {
|
|
||||||
self.data.lock().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Clone for VData {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
let mut d = self.data.lock().unwrap();
|
|
||||||
let o = if d.1 {
|
|
||||||
// mutable, copy the value to avoid accidentally modifying it.
|
|
||||||
// DON'T just set it to immutable even if we are the only reference (inner mutability!)
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!(
|
|
||||||
"VData: Clone: copying value due to clone of a mutable value. (strong count: {})",
|
|
||||||
Arc::strong_count(&self.data)
|
|
||||||
);
|
|
||||||
d.0.clone().to()
|
|
||||||
} else {
|
|
||||||
// immutable, return the same arc (-> avoid cloning)
|
|
||||||
Self {
|
|
||||||
data: Arc::clone(&self.data),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
o
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Debug for VData {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
let d = self.data.lock().unwrap();
|
|
||||||
if d.1 {
|
|
||||||
write!(f, "(!mutable!):{:?}", d.0)
|
|
||||||
} else {
|
|
||||||
write!(f, "(immutable):{:?}", d.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl PartialEq for VData {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.data().0 == other.data().0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum VDataEnum {
|
pub enum VDataEnum {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
@ -133,17 +17,214 @@ pub enum VDataEnum {
|
|||||||
String(String),
|
String(String),
|
||||||
Tuple(Vec<VData>),
|
Tuple(Vec<VData>),
|
||||||
List(VType, Vec<VData>),
|
List(VType, Vec<VData>),
|
||||||
Function(RFunction),
|
Function(Arc<RFunction>),
|
||||||
Thread(thread::VDataThread, VType),
|
Thread(thread::VDataThread, VType),
|
||||||
Reference(VData),
|
Reference(VData),
|
||||||
EnumVariant(usize, Box<VData>),
|
EnumVariant(usize, Box<VData>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct VData(Arc<Mutex<VDataInner>>);
|
||||||
|
enum VDataInner {
|
||||||
|
Data(usize, Box<VDataEnum>),
|
||||||
|
Mut(Arc<Mutex<VData>>),
|
||||||
|
ClonedFrom(VData),
|
||||||
|
}
|
||||||
|
/// can be either Data, Mut or ClonedFrom.
|
||||||
|
/// - any ClonedFrom will point to a Data variant. It can never point to anything else.
|
||||||
|
/// it will increase the Data's clone count by one on creation and decrease it again on Drop::drop().
|
||||||
|
/// - any Mut will eventually point to a ClonedFrom or a Data variant. It can also point to another Mut.
|
||||||
|
impl VDataInner {
|
||||||
|
fn to(self) -> VData {
|
||||||
|
VData(Arc::new(Mutex::new(self)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl VDataEnum {
|
||||||
|
pub fn to(self) -> VData {
|
||||||
|
VDataInner::Data(0, Box::new(self)).to()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VData {
|
||||||
|
pub fn new_placeholder() -> Self {
|
||||||
|
VDataEnum::Bool(false).to()
|
||||||
|
}
|
||||||
|
/// clones self, retrurning a new instance of self that will always yield the value self had when this function was called.
|
||||||
|
/// note to dev: since the actual data is stored in VDataEnum, which either clones data or calls clone() (= clone_data()) on further VData, this automatically borrows all child data as immutable too. rust's Drop::drop() implementation (probably) handles everything for us too, so this can be implemented without thinking about recursion.
|
||||||
|
pub fn clone_data(&self) -> Self {
|
||||||
|
match &mut *self.0.lock().unwrap() {
|
||||||
|
VDataInner::Data(cloned, _data) => {
|
||||||
|
*cloned += 1;
|
||||||
|
VDataInner::ClonedFrom(self.clone_arc()).to()
|
||||||
|
}
|
||||||
|
VDataInner::Mut(inner) => inner.lock().unwrap().clone_data(),
|
||||||
|
VDataInner::ClonedFrom(inner) => inner.clone_data(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// clones self, returning a new instance of self that will always yield the same data as self, so that changes done to either are shared between both.
|
||||||
|
pub fn clone_mut(&self) -> Self {
|
||||||
|
VDataInner::Mut(Arc::new(Mutex::new(self.clone_arc()))).to()
|
||||||
|
}
|
||||||
|
fn clone_arc(&self) -> Self {
|
||||||
|
Self(Arc::clone(&self.0))
|
||||||
|
}
|
||||||
|
pub fn operate_on_data_immut<F, O>(&self, mut func: F) -> O
|
||||||
|
where
|
||||||
|
F: FnOnce(&VDataEnum) -> O,
|
||||||
|
{
|
||||||
|
match &*self.0.lock().unwrap() {
|
||||||
|
VDataInner::Data(_, data) => func(data.as_ref()),
|
||||||
|
VDataInner::Mut(inner) => inner.lock().unwrap().operate_on_data_immut(func),
|
||||||
|
VDataInner::ClonedFrom(inner) => inner.operate_on_data_immut(func),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// runs func on the underlying data.
|
||||||
|
/// attempts to get a mutable reference to the data. if this fails, it will (partially) clone the data, then point the VData to the new data,
|
||||||
|
/// so that other VDatas pointing to the same original data aren't changed.
|
||||||
|
pub fn operate_on_data_mut<F, O>(&mut self, mut func: F) -> O
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut VDataEnum) -> O,
|
||||||
|
{
|
||||||
|
let (new_val, o) = {
|
||||||
|
match &mut *self.0.lock().unwrap() {
|
||||||
|
VDataInner::Data(count, data) => {
|
||||||
|
if *count == 0 {
|
||||||
|
(None, func(data.as_mut()))
|
||||||
|
} else {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("Cloning: data should be modified, but was borrowed immutably.");
|
||||||
|
let mut new_data = data.clone();
|
||||||
|
let o = func(new_data.as_mut());
|
||||||
|
// *self doesn't modify the ::Data, it instead points the value that wraps it to a new ::Data, leaving the old one as it was.
|
||||||
|
// for proof: data is untouched, only the new_data is ever modified.
|
||||||
|
(Some(VDataInner::Data(0, new_data).to()), o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VDataInner::Mut(inner) => (None, inner.lock().unwrap().operate_on_data_mut(func)),
|
||||||
|
VDataInner::ClonedFrom(inner) => (None, inner.operate_on_data_mut(func)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(nv) = new_val {
|
||||||
|
*self = nv;
|
||||||
|
}
|
||||||
|
o
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Since operate_on_data_mut can clone, it may be inefficient for just assigning (where we don't care about the previous value, so it doesn't need to be cloned).
|
||||||
|
/// This is what this function is for. (TODO: actually make it more efficient instead of using operate_on_data_mut)
|
||||||
|
pub fn assign_data(&mut self, new_data: VDataEnum) {
|
||||||
|
self.operate_on_data_mut(|d| *d = new_data)
|
||||||
|
}
|
||||||
|
/// Assigns the new_data to self. Affects all muts pointing to the same data, but no ClonedFroms.
|
||||||
|
pub fn assign(&mut self, new: VData) {
|
||||||
|
self.assign_data(new.inner_cloned())
|
||||||
|
// !PROBLEM! If ClonedFrom always has to point to a Data, this may break things!
|
||||||
|
// match &mut *self.0.lock().unwrap() {
|
||||||
|
// VDataInner::Data(count, data) => {
|
||||||
|
// // *self doesn't modify the ::Data, it instead points the value that wraps it to a new ::Data, leaving the old one as it was.
|
||||||
|
// // for proof: data is untouched.
|
||||||
|
// *self = new_data;
|
||||||
|
// }
|
||||||
|
// VDataInner::Mut(inner) => inner.lock().unwrap().assign(new_data),
|
||||||
|
// VDataInner::ClonedFrom(inner) => inner.assign(new_data),
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Drop for VDataInner {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Self::ClonedFrom(origin) = self {
|
||||||
|
if let Self::Data(ref_count, _data) = &mut *origin.0.lock().unwrap() {
|
||||||
|
eprint!("rc: {}", *ref_count);
|
||||||
|
*ref_count = ref_count.saturating_sub(1);
|
||||||
|
eprintln!(" -> {}", *ref_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VData {
|
||||||
|
/// this will always clone! if a reference or mutable reference is enough, use operate_on_data_* instead!
|
||||||
|
pub fn inner_cloned(&self) -> VDataEnum {
|
||||||
|
self.operate_on_data_immut(|v| v.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - make VData act like VDataEnum (as if it were real data) - -
|
||||||
|
|
||||||
|
impl Clone for VData {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
self.clone_data()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl VData {
|
||||||
|
pub fn fmtgs(&self, f: &mut Formatter<'_>, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
||||||
|
self.operate_on_data_immut(|v| v.fmtgs(f, info))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Debug for VData {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
self.operate_on_data_immut(|v| Debug::fmt(v, f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Display for VData {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
self.operate_on_data_immut(|v| Display::fmt(v, f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialEq for VData {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.operate_on_data_immut(|a| other.operate_on_data_immut(|b| a == b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialEq<VDataEnum> for VData {
|
||||||
|
fn eq(&self, other: &VDataEnum) -> bool {
|
||||||
|
self.operate_on_data_immut(|a| a == other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialEq<VData> for VDataEnum {
|
||||||
|
fn eq(&self, other: &VData) -> bool {
|
||||||
|
other.operate_on_data_immut(|b| self == b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl VData {
|
||||||
|
pub fn out_single(&self) -> VSingleType {
|
||||||
|
self.operate_on_data_immut(|v| v.out_single())
|
||||||
|
}
|
||||||
|
pub fn out(&self) -> VType {
|
||||||
|
self.out_single().to()
|
||||||
|
}
|
||||||
|
pub fn noenum(&self) -> Self {
|
||||||
|
if let Some(v) = self.operate_on_data_immut(|v| v.noenum()) {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
self.clone_data()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn safe_to_share(&self) -> bool {
|
||||||
|
self.operate_on_data_immut(|v| v.safe_to_share())
|
||||||
|
}
|
||||||
|
pub fn get(&self, i: usize) -> Option<VData> {
|
||||||
|
self.operate_on_data_immut(|v| v.get(i))
|
||||||
|
}
|
||||||
|
pub fn matches(&self) -> Option<Self> {
|
||||||
|
match self.operate_on_data_immut(|v| v.matches()) {
|
||||||
|
Some(Some(v)) => Some(v),
|
||||||
|
Some(None) => Some(self.clone_data()),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn deref(&self) -> Option<Self> {
|
||||||
|
self.operate_on_data_immut(|v| v.deref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - VDataEnum - -
|
||||||
|
|
||||||
impl Clone for VDataEnum {
|
impl Clone for VDataEnum {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
// exception: don't clone the value AND don't use CoW,
|
// exception: don't clone the value AND don't use CoW,
|
||||||
// because we want to share the same Arc<Mutex<_>>.
|
// because we want to share the same Arc<Mutex<_>>.
|
||||||
Self::Reference(r) => Self::Reference(r.clone_mut_assume()),
|
Self::Reference(r) => Self::Reference(r.clone_mut()),
|
||||||
// default impls
|
// default impls
|
||||||
Self::Bool(b) => Self::Bool(*b),
|
Self::Bool(b) => Self::Bool(*b),
|
||||||
Self::Int(i) => Self::Int(*i),
|
Self::Int(i) => Self::Int(*i),
|
||||||
@ -161,8 +242,8 @@ impl PartialEq for VDataEnum {
|
|||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Self::Reference(a), Self::Reference(b)) => a == b,
|
(Self::Reference(a), Self::Reference(b)) => a == b,
|
||||||
(Self::Reference(a), b) => &a.data().0 == b,
|
(Self::Reference(a), b) => a == b,
|
||||||
(a, Self::Reference(b)) => a == &b.data().0,
|
(a, Self::Reference(b)) => a == b,
|
||||||
(Self::Bool(a), Self::Bool(b)) => *a == *b,
|
(Self::Bool(a), Self::Bool(b)) => *a == *b,
|
||||||
(Self::Int(a), Self::Int(b)) => *a == *b,
|
(Self::Int(a), Self::Int(b)) => *a == *b,
|
||||||
(Self::Float(a), Self::Float(b)) => *a == *b,
|
(Self::Float(a), Self::Float(b)) => *a == *b,
|
||||||
@ -176,55 +257,26 @@ impl PartialEq for VDataEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VData {
|
impl VDataEnum {
|
||||||
pub fn safe_to_share(&self) -> bool {
|
pub fn deref(&self) -> Option<VData> {
|
||||||
self.data().0.safe_to_share()
|
if let Self::Reference(r) = self {
|
||||||
}
|
Some(r.clone_mut())
|
||||||
pub fn out(&self) -> VType {
|
} else {
|
||||||
VType {
|
None
|
||||||
types: vec![self.out_single()],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn out_single(&self) -> VSingleType {
|
pub fn out_single(&self) -> VSingleType {
|
||||||
match &self.data().0 {
|
match self {
|
||||||
VDataEnum::Bool(..) => VSingleType::Bool,
|
Self::Bool(..) => VSingleType::Bool,
|
||||||
VDataEnum::Int(..) => VSingleType::Int,
|
Self::Int(..) => VSingleType::Int,
|
||||||
VDataEnum::Float(..) => VSingleType::Float,
|
Self::Float(..) => VSingleType::Float,
|
||||||
VDataEnum::String(..) => VSingleType::String,
|
Self::String(..) => VSingleType::String,
|
||||||
VDataEnum::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out()).collect()),
|
Self::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out_single().to()).collect()),
|
||||||
VDataEnum::List(t, _) => VSingleType::List(t.clone()),
|
Self::List(t, _) => VSingleType::List(t.clone()),
|
||||||
VDataEnum::Function(f) => VSingleType::Function(f.input_output_map.clone()),
|
Self::Function(f) => VSingleType::Function(f.input_output_map.clone()),
|
||||||
VDataEnum::Thread(_, o) => VSingleType::Thread(o.clone()),
|
Self::Thread(_, o) => VSingleType::Thread(o.clone()),
|
||||||
VDataEnum::Reference(r) => VSingleType::Reference(Box::new(r.out_single())),
|
Self::Reference(r) => VSingleType::Reference(Box::new(r.out_single())),
|
||||||
VDataEnum::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out()),
|
Self::EnumVariant(e, v) => VSingleType::EnumVariant(*e, v.out_single().to()),
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn get(&self, i: usize, as_mut: bool) -> Option<Self> {
|
|
||||||
if let Some(mut d) = self.data().0.get(i) {
|
|
||||||
if as_mut {
|
|
||||||
d.make_mut();
|
|
||||||
}
|
|
||||||
Some(d)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn noenum(self) -> Self {
|
|
||||||
self.inner().noenum()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VDataEnum {
|
|
||||||
pub fn to(self) -> VData {
|
|
||||||
VData {
|
|
||||||
data: Arc::new(Mutex::new((self, false))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn deref(self) -> Option<VData> {
|
|
||||||
if let Self::Reference(r) = self {
|
|
||||||
Some(r)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,10 +292,10 @@ impl VDataEnum {
|
|||||||
Self::Thread(..) | Self::Reference(..) | Self::EnumVariant(..) => false,
|
Self::Thread(..) | Self::Reference(..) | Self::EnumVariant(..) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn noenum(self) -> VData {
|
pub fn noenum(&self) -> Option<VData> {
|
||||||
match self {
|
match self {
|
||||||
Self::EnumVariant(_, v) => *v,
|
Self::EnumVariant(_, v) => Some(v.clone_data()),
|
||||||
v => v.to(),
|
v => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get(&self, i: usize) -> Option<VData> {
|
pub fn get(&self, i: usize) -> Option<VData> {
|
||||||
@ -259,8 +311,8 @@ 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.get(i, false),
|
Self::Reference(r) => r.get(i),
|
||||||
Self::EnumVariant(_, v) => v.get(i, false),
|
Self::EnumVariant(_, v) => v.get(i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn matches_ref_bool(&self) -> bool {
|
pub fn matches_ref_bool(&self) -> bool {
|
||||||
@ -270,18 +322,19 @@ impl VDataEnum {
|
|||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn matches(self) -> Option<VData> {
|
/// Some(None) => matches with self
|
||||||
|
pub fn matches(&self) -> Option<Option<VData>> {
|
||||||
match self {
|
match self {
|
||||||
VDataEnum::Tuple(mut tuple) => tuple.pop(),
|
VDataEnum::Tuple(tuple) => tuple.get(0).cloned().map(|v| Some(v)),
|
||||||
VDataEnum::Bool(v) => {
|
VDataEnum::Bool(v) => {
|
||||||
if v {
|
if *v {
|
||||||
Some(VDataEnum::Bool(v).to())
|
Some(Some(VDataEnum::Bool(true).to()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VDataEnum::EnumVariant(..) => None,
|
VDataEnum::EnumVariant(..) => None,
|
||||||
other => Some(other.to()),
|
other => Some(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -460,14 +513,3 @@ impl Display for VDataEnum {
|
|||||||
self.fmtgs(f, None)
|
self.fmtgs(f, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VData {
|
|
||||||
pub fn fmtgs(&self, f: &mut Formatter, info: Option<&GlobalScriptInfo>) -> fmt::Result {
|
|
||||||
self.data().0.fmtgs(f, info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Display for VData {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
||||||
self.fmtgs(f, None)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,20 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod lang;
|
||||||
mod libs;
|
mod libs;
|
||||||
mod parsing;
|
mod parsing;
|
||||||
mod script;
|
|
||||||
|
|
||||||
|
pub use lang::{val_data::*, val_type::*};
|
||||||
pub use libs::{
|
pub use libs::{
|
||||||
comms::{ByteData, ByteDataA, Message, RespondableMessage},
|
comms::{ByteData, ByteDataA, Message, RespondableMessage},
|
||||||
inlib::MyLib,
|
inlib::MyLib,
|
||||||
};
|
};
|
||||||
pub use parsing::*;
|
pub use parsing::*;
|
||||||
pub use script::{val_data::*, val_type::*};
|
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use super::{
|
pub use super::{
|
||||||
script::{val_data::*, val_type::*},
|
lang::{val_data::*, val_type::*},
|
||||||
MyLib, RespondableMessage,
|
MyLib, RespondableMessage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::{
|
use crate::lang::{
|
||||||
val_data::{VData, VDataEnum},
|
val_data::{VData, VDataEnum},
|
||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
};
|
};
|
||||||
@ -58,7 +58,7 @@ impl From<run_function::Message> for Message {
|
|||||||
// implementations for the message/response pairs
|
// implementations for the message/response pairs
|
||||||
|
|
||||||
pub mod run_function {
|
pub mod run_function {
|
||||||
use crate::script::val_data::VData;
|
use crate::lang::val_data::VData;
|
||||||
|
|
||||||
use super::{ByteData, ByteDataA, MessageResponse, RespondableMessage};
|
use super::{ByteData, ByteDataA, MessageResponse, RespondableMessage};
|
||||||
|
|
||||||
@ -461,7 +461,7 @@ impl ByteData for VSingleType {
|
|||||||
}
|
}
|
||||||
impl ByteDataA for VData {
|
impl ByteDataA for VData {
|
||||||
fn as_byte_data(&self, vec: &mut Vec<u8>) {
|
fn as_byte_data(&self, vec: &mut Vec<u8>) {
|
||||||
self.data().0.as_byte_data(vec)
|
self.operate_on_data_immut(|v| v.as_byte_data(vec))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ByteData for VData {
|
impl ByteData for VData {
|
||||||
|
@ -3,7 +3,7 @@ use std::{
|
|||||||
io::{BufRead, Stdin, StdinLock, Stdout, StdoutLock, Write},
|
io::{BufRead, Stdin, StdinLock, Stdout, StdoutLock, Write},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::script::{val_data::VData, val_type::VType};
|
use crate::lang::{val_data::VData, val_type::VType};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
comms::{self, ByteData, ByteDataA, Message, MessageResponse, RespondableMessage},
|
comms::{self, ByteData, ByteDataA, Message, MessageResponse, RespondableMessage},
|
||||||
|
@ -11,13 +11,13 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
libs::comms::{ByteData, ByteDataA},
|
lang::{
|
||||||
parsing::{file::File, parse},
|
|
||||||
script::{
|
|
||||||
global_info::GlobalScriptInfo,
|
global_info::GlobalScriptInfo,
|
||||||
val_data::{VData, VDataEnum},
|
val_data::{VData, VDataEnum},
|
||||||
val_type::VType,
|
val_type::VType,
|
||||||
},
|
},
|
||||||
|
libs::comms::{ByteData, ByteDataA},
|
||||||
|
parsing::{file::File, parse},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::comms::{MessageResponse, RespondableMessage};
|
use self::comms::{MessageResponse, RespondableMessage};
|
||||||
@ -93,9 +93,9 @@ impl Lib {
|
|||||||
for (_name, func) in registered_fns.iter_mut() {
|
for (_name, func) in registered_fns.iter_mut() {
|
||||||
for (args, out) in func.iter_mut() {
|
for (args, out) in func.iter_mut() {
|
||||||
for t in args.iter_mut() {
|
for t in args.iter_mut() {
|
||||||
crate::script::to_runnable::stypes(t, &mut ginfo);
|
crate::lang::to_runnable::stypes(t, &mut ginfo);
|
||||||
}
|
}
|
||||||
crate::script::to_runnable::stypes(out, &mut ginfo);
|
crate::lang::to_runnable::stypes(out, &mut ginfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (name, id) in ginfo.enum_variants {
|
for (name, id) in ginfo.enum_variants {
|
||||||
|
@ -6,11 +6,11 @@ use std::{fs, time::Instant};
|
|||||||
use notify::Watcher as FsWatcher;
|
use notify::Watcher as FsWatcher;
|
||||||
|
|
||||||
mod interactive_mode;
|
mod interactive_mode;
|
||||||
|
mod lang;
|
||||||
mod libs;
|
mod libs;
|
||||||
#[cfg(feature = "nushell_plugin")]
|
#[cfg(feature = "nushell_plugin")]
|
||||||
mod nushell_plugin;
|
mod nushell_plugin;
|
||||||
mod parsing;
|
mod parsing;
|
||||||
mod script;
|
|
||||||
mod tutor;
|
mod tutor;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -4,11 +4,11 @@ use nu_plugin::{serve_plugin, MsgPackSerializer, Plugin};
|
|||||||
use nu_protocol::{PluginExample, PluginSignature, ShellError, Span, Spanned, SyntaxShape, Value};
|
use nu_protocol::{PluginExample, PluginSignature, ShellError, Span, Spanned, SyntaxShape, Value};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parsing,
|
lang::{
|
||||||
script::{
|
|
||||||
global_info::GlobalScriptInfo,
|
global_info::GlobalScriptInfo,
|
||||||
val_data::{VData, VDataEnum},
|
val_data::{VData, VDataEnum},
|
||||||
},
|
},
|
||||||
|
parsing,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use std::{fmt::Debug, process::Command, sync::Arc};
|
use std::{fmt::Debug, process::Command, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
libs,
|
lang::{
|
||||||
script::{
|
|
||||||
code_macro::MacroError,
|
code_macro::MacroError,
|
||||||
code_parsed::*,
|
code_parsed::*,
|
||||||
code_runnable::RScript,
|
code_runnable::RScript,
|
||||||
@ -11,6 +10,7 @@ use crate::{
|
|||||||
val_data::VDataEnum,
|
val_data::VDataEnum,
|
||||||
val_type::{VSingleType, VType},
|
val_type::{VSingleType, VType},
|
||||||
},
|
},
|
||||||
|
libs,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::file::File;
|
use super::file::File;
|
||||||
@ -785,7 +785,7 @@ pub mod implementation {
|
|||||||
}
|
}
|
||||||
"!" => {
|
"!" => {
|
||||||
break SStatementEnum::Macro(
|
break SStatementEnum::Macro(
|
||||||
match crate::script::code_macro::parse_macro(file) {
|
match crate::lang::code_macro::parse_macro(file) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(ParseError {
|
return Err(ParseError {
|
||||||
@ -862,11 +862,17 @@ pub mod implementation {
|
|||||||
let args = [out].into_iter().chain(args.into_iter()).collect();
|
let args = [out].into_iter().chain(args.into_iter()).collect();
|
||||||
SStatementEnum::FunctionCall(func, args).to()
|
SStatementEnum::FunctionCall(func, args).to()
|
||||||
}
|
}
|
||||||
SStatementEnum::Value(vd) => match &vd.data().0 {
|
SStatementEnum::Value(vd) => {
|
||||||
VDataEnum::Int(i) => SStatementEnum::IndexFixed(out, *i as _).to(),
|
if let Some(i) = vd.operate_on_data_immut(|v| match v {
|
||||||
_ => {
|
VDataEnum::Int(i) => Some(*i as _),
|
||||||
|
_ => None,
|
||||||
|
}) {
|
||||||
|
SStatementEnum::IndexFixed(out, i).to()
|
||||||
|
} else {
|
||||||
return Err(ParseError {
|
return Err(ParseError {
|
||||||
err: ParseErrors::CannotUseFixedIndexingWithThisType(vd.out()),
|
err: ParseErrors::CannotUseFixedIndexingWithThisType(
|
||||||
|
vd.out_single().to(),
|
||||||
|
),
|
||||||
location: err_start_of_wrapper,
|
location: err_start_of_wrapper,
|
||||||
location_end: Some(err_end_of_wrapper),
|
location_end: Some(err_end_of_wrapper),
|
||||||
context: vec![(
|
context: vec![(
|
||||||
@ -876,7 +882,7 @@ pub mod implementation {
|
|||||||
info: None,
|
info: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
other => {
|
other => {
|
||||||
return Err(ParseError {
|
return Err(ParseError {
|
||||||
err: ParseErrors::CannotWrapWithThisStatement(other),
|
err: ParseErrors::CannotWrapWithThisStatement(other),
|
||||||
@ -974,6 +980,20 @@ pub mod implementation {
|
|||||||
)
|
)
|
||||||
.to()
|
.to()
|
||||||
}
|
}
|
||||||
|
(0..=50, Some('!'))
|
||||||
|
if matches!(
|
||||||
|
file.get_char(file.get_pos().current_char_index + 1),
|
||||||
|
Some('=')
|
||||||
|
) =>
|
||||||
|
{
|
||||||
|
file.next();
|
||||||
|
file.next();
|
||||||
|
SStatementEnum::FunctionCall(
|
||||||
|
"ne".to_owned(),
|
||||||
|
vec![out, parse_statement_adv(file, true, 50)?],
|
||||||
|
)
|
||||||
|
.to()
|
||||||
|
}
|
||||||
(0..=10, Some('=')) => {
|
(0..=10, Some('=')) => {
|
||||||
file.next();
|
file.next();
|
||||||
match out.statement.as_mut() {
|
match out.statement.as_mut() {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::val_data::VDataEnum;
|
use crate::lang::val_data::VDataEnum;
|
||||||
|
|
||||||
use super::Tutor;
|
use super::Tutor;
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ pub fn run(tutor: &mut Tutor) {
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
match tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
VDataEnum::Bool(true) => break,
|
VDataEnum::Bool(true) => break,
|
||||||
other => {
|
other => {
|
||||||
tutor.set_status(format!(" - Returned {} instead of true.", other));
|
tutor.set_status(format!(" - Returned {} instead of true.", other));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::val_data::VDataEnum;
|
use crate::lang::val_data::VDataEnum;
|
||||||
|
|
||||||
use super::Tutor;
|
use super::Tutor;
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ mul()
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
match tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
VDataEnum::Int(160) => break,
|
VDataEnum::Int(160) => break,
|
||||||
other => {
|
other => {
|
||||||
tutor.set_status(format!(" - Returned {other} instead of 160"));
|
tutor.set_status(format!(" - Returned {other} instead of 160"));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::val_data::VDataEnum;
|
use crate::lang::val_data::VDataEnum;
|
||||||
|
|
||||||
use super::Tutor;
|
use super::Tutor;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ fn compute_sum(a int b int) {
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
match tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
VDataEnum::Int(15) => break,
|
VDataEnum::Int(15) => break,
|
||||||
other => {
|
other => {
|
||||||
tutor.set_status(format!(" - Returned {} instead of 15.", other));
|
tutor.set_status(format!(" - Returned {} instead of 15.", other));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::val_data::VDataEnum;
|
use crate::lang::val_data::VDataEnum;
|
||||||
|
|
||||||
use super::Tutor;
|
use super::Tutor;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ switch! words_in_string {}
|
|||||||
true
|
true
|
||||||
"));
|
"));
|
||||||
loop {
|
loop {
|
||||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
match tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
VDataEnum::Tuple(v) if v.is_empty() => {
|
VDataEnum::Tuple(v) if v.is_empty() => {
|
||||||
tutor.set_status(format!(" - Returned an empty tuple."));
|
tutor.set_status(format!(" - Returned an empty tuple."));
|
||||||
tutor.update(None);
|
tutor.update(None);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::val_data::VDataEnum;
|
use crate::lang::val_data::VDataEnum;
|
||||||
|
|
||||||
use super::Tutor;
|
use super::Tutor;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ pub fn run(tutor: &mut Tutor) {
|
|||||||
// return any enum to return to the menu.
|
// return any enum to return to the menu.
|
||||||
"));
|
"));
|
||||||
loop {
|
loop {
|
||||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
match tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
VDataEnum::EnumVariant(..) => break,
|
VDataEnum::EnumVariant(..) => break,
|
||||||
other => {
|
other => {
|
||||||
tutor.set_status(format!(" - Returned {other} instead of an enum."));
|
tutor.set_status(format!(" - Returned {other} instead of an enum."));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::val_data::VDataEnum;
|
use crate::lang::val_data::VDataEnum;
|
||||||
|
|
||||||
use super::Tutor;
|
use super::Tutor;
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ five_less = sub(my_first_variable 5) // 10
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
match tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
VDataEnum::String(name) if !name.is_empty() => {
|
VDataEnum::String(name) if !name.is_empty() => {
|
||||||
tutor.i_name = Some(name.to_owned());
|
tutor.i_name = Some(name.to_owned());
|
||||||
break;
|
break;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::val_data::VDataEnum;
|
use crate::lang::val_data::VDataEnum;
|
||||||
|
|
||||||
use super::Tutor;
|
use super::Tutor;
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ switch! first {
|
|||||||
list.get(8)
|
list.get(8)
|
||||||
"));
|
"));
|
||||||
loop {
|
loop {
|
||||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
match tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
VDataEnum::Tuple(v) if !v.is_empty() => {
|
VDataEnum::Tuple(v) if !v.is_empty() => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::script::val_data::VDataEnum;
|
use crate::lang::val_data::VDataEnum;
|
||||||
|
|
||||||
use super::Tutor;
|
use super::Tutor;
|
||||||
|
|
||||||
@ -24,9 +24,9 @@ go_to()
|
|||||||
",
|
",
|
||||||
));
|
));
|
||||||
loop {
|
loop {
|
||||||
match &tutor.let_user_make_change().run(vec![]).data().0 {
|
match tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
VDataEnum::Int(pos) if *pos != 0 => {
|
VDataEnum::Int(pos) if pos != 0 => {
|
||||||
tutor.current_pos = ((*pos).max(0) as usize).min(MAX_POS);
|
tutor.current_pos = (pos.max(0) as usize).min(MAX_POS);
|
||||||
match tutor.current_pos {
|
match tutor.current_pos {
|
||||||
0 => continue,
|
0 => continue,
|
||||||
1 => super::base_comments::run(&mut tutor),
|
1 => super::base_comments::run(&mut tutor),
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::{path::PathBuf, thread::JoinHandle, time::Instant};
|
use std::{path::PathBuf, thread::JoinHandle, time::Instant};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
lang::{code_runnable::RScript, global_info::GSInfo, val_data::VDataEnum},
|
||||||
parsing::{self, file::File, parse::ScriptError},
|
parsing::{self, file::File, parse::ScriptError},
|
||||||
script::{code_runnable::RScript, global_info::GSInfo, val_data::VDataEnum},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod base_comments;
|
mod base_comments;
|
||||||
@ -45,7 +45,7 @@ false
|
|||||||
i_name: None,
|
i_name: None,
|
||||||
};
|
};
|
||||||
loop {
|
loop {
|
||||||
if let VDataEnum::Bool(true) = &tutor.let_user_make_change().run(vec![]).data().0 {
|
if let VDataEnum::Bool(true) = tutor.let_user_make_change().run(vec![]).inner_cloned() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ fn run_all() {
|
|||||||
let mut file = File::new(fs::read_to_string(file.path()).unwrap(), file.path());
|
let mut file = File::new(fs::read_to_string(file.path()).unwrap(), file.path());
|
||||||
// has to return true, otherwise the test will fail
|
// has to return true, otherwise the test will fail
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
parse::parse(&mut file).unwrap().run(vec![]).data().0,
|
parse::parse(&mut file).unwrap().run(vec![]).inner_cloned(),
|
||||||
VDataEnum::Bool(true)
|
VDataEnum::Bool(true)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,8 @@ fn main() {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.1;
|
.1;
|
||||||
my_lib.callbacks.run_function.consuming = Some(Box::new(move |msg| {
|
my_lib.callbacks.run_function.consuming = Some(Box::new(move |msg| {
|
||||||
let url = if let VDataEnum::String(url) = &msg.msg.args[0].data().0 {
|
let url = if let VDataEnum::String(url) = msg.msg.args[0].inner_cloned() {
|
||||||
url.clone()
|
url
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
&a = "value"
|
|
||||||
&list = ["a" "b" "c" ...]
|
|
||||||
&elem = &list.get_ref(1)
|
|
||||||
switch! elem {
|
|
||||||
[&string] elem.0 = "z"
|
|
||||||
[] {}
|
|
||||||
}
|
|
||||||
list.debug()
|
|
Loading…
Reference in New Issue
Block a user