mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
fixed [[2]].0.0 parsing 0.0 as a float, removed get_ref() and made get() return a reference to the inner value if called on a reference to a collection (&[int ...].get(0) returns []/[&int]).
This commit is contained in:
parent
56b457e1b3
commit
7af9902b6a
@ -78,7 +78,6 @@ pub enum BuiltinFunction {
|
||||
Pop,
|
||||
Remove,
|
||||
Get,
|
||||
GetRef,
|
||||
Len,
|
||||
// String
|
||||
Contains,
|
||||
@ -142,7 +141,6 @@ impl BuiltinFunction {
|
||||
"pop" => Self::Pop,
|
||||
"remove" => Self::Remove,
|
||||
"get" => Self::Get,
|
||||
"get_ref" => Self::GetRef,
|
||||
"len" => Self::Len,
|
||||
"contains" => Self::Contains,
|
||||
"starts_with" => Self::StartsWith,
|
||||
@ -448,7 +446,7 @@ impl BuiltinFunction {
|
||||
}
|
||||
}
|
||||
// TODO! finish this
|
||||
Self::Get | Self::GetRef | Self::Len => true,
|
||||
Self::Get | Self::Len => true,
|
||||
Self::Substring => {
|
||||
if input.len() >= 2 && input.len() <= 3 {
|
||||
let (s, start) = (&input[0], &input[1]);
|
||||
@ -603,26 +601,6 @@ impl BuiltinFunction {
|
||||
unreachable!("get, pop or remove called without args")
|
||||
}
|
||||
}
|
||||
Self::GetRef => {
|
||||
if let Some(v) = input.first() {
|
||||
VType {
|
||||
types: vec![
|
||||
VSingleType::Tuple(vec![]),
|
||||
VSingleType::Tuple(vec![{
|
||||
let mut v = v.get_any(info).expect("cannot use get on this type");
|
||||
v.types = v
|
||||
.types
|
||||
.into_iter()
|
||||
.map(|v| VSingleType::Reference(Box::new(v)))
|
||||
.collect();
|
||||
v
|
||||
}]),
|
||||
],
|
||||
}
|
||||
} else {
|
||||
unreachable!("get, pop or remove called without args")
|
||||
}
|
||||
}
|
||||
Self::Exit => VType { types: vec![] }, // doesn't return
|
||||
Self::FsList => VType {
|
||||
types: vec![
|
||||
@ -1395,9 +1373,9 @@ impl BuiltinFunction {
|
||||
_ => unreachable!("max: not a number"),
|
||||
})
|
||||
}),
|
||||
Self::Push => args[0].run(info).operate_on_data_mut(info, |list| {
|
||||
Self::Push => args[0].run(info).operate_on_data_mut(|list| {
|
||||
if let VDataEnum::Reference(v) = list {
|
||||
v.operate_on_data_mut(info, |list| {
|
||||
v.operate_on_data_mut(|list| {
|
||||
if let VDataEnum::List(_, v) = list {
|
||||
v.push(args[1].run(info));
|
||||
}
|
||||
@ -1407,11 +1385,11 @@ impl BuiltinFunction {
|
||||
unreachable!("push: not a reference")
|
||||
}
|
||||
}),
|
||||
Self::Insert => args[0].run(info).operate_on_data_mut(info, |v| {
|
||||
Self::Insert => args[0].run(info).operate_on_data_mut(|v| {
|
||||
args[1].run(info).operate_on_data_immut(|i| {
|
||||
// TODO: find out why the fuck this helps
|
||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) = (v, i) {
|
||||
v.operate_on_data_mut(info, |v| {
|
||||
v.operate_on_data_mut(|v| {
|
||||
if let VDataEnum::List(_, v) = v {
|
||||
v.insert(*i as _, args[2].run(info));
|
||||
}
|
||||
@ -1422,9 +1400,9 @@ impl BuiltinFunction {
|
||||
}
|
||||
})
|
||||
}),
|
||||
Self::Pop => args[0].run(info).operate_on_data_mut(info, |v| {
|
||||
Self::Pop => args[0].run(info).operate_on_data_mut(|v| {
|
||||
if let VDataEnum::Reference(v) = v {
|
||||
v.operate_on_data_mut(info, |v| {
|
||||
v.operate_on_data_mut(|v| {
|
||||
if let VDataEnum::List(_, v) = v {
|
||||
if let Some(v) = v.pop() {
|
||||
VDataEnum::Tuple(vec![v])
|
||||
@ -1440,12 +1418,12 @@ impl BuiltinFunction {
|
||||
unreachable!("pop: not a reference")
|
||||
}
|
||||
}),
|
||||
Self::Remove => args[0].run(info).operate_on_data_mut(info, |v| {
|
||||
Self::Remove => args[0].run(info).operate_on_data_mut(|v| {
|
||||
args[1].run(info).operate_on_data_immut(|i|
|
||||
// this being a reference means we wont need to call make_mut() later, so a .as_ref() borrow is enough.
|
||||
if let (VDataEnum::Reference(v), VDataEnum::Int(i)) = (v, i
|
||||
) {
|
||||
v.operate_on_data_mut(info, |v| {
|
||||
v.operate_on_data_mut(|v| {
|
||||
if let VDataEnum::List(_, v) = v {
|
||||
if *i >= 0 && v.len() > *i as _ {
|
||||
let v = v.remove(*i as _);
|
||||
@ -1464,23 +1442,10 @@ impl BuiltinFunction {
|
||||
args[1].run(info).operate_on_data_immut(|i| {
|
||||
if let VDataEnum::Int(i) = i {
|
||||
if *i >= 0 {
|
||||
match match container {
|
||||
VDataEnum::Reference(v) => v.operate_on_data_immut(|v| match v {
|
||||
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||
v.get(*i as usize).map(|v| v.clone())
|
||||
}
|
||||
_ => unreachable!(
|
||||
"get: reference to something other than list/tuple"
|
||||
),
|
||||
}),
|
||||
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||
v.get(*i as usize).map(|v| v.clone())
|
||||
}
|
||||
_ => unreachable!("get: not a reference/list/tuple"),
|
||||
} {
|
||||
Some(v) => VDataEnum::Tuple(vec![v]).to(),
|
||||
None => VDataEnum::Tuple(vec![]).to(),
|
||||
}
|
||||
container.get(*i as _).map_or_else(
|
||||
|| VDataEnum::Tuple(vec![]).to(),
|
||||
|v| VDataEnum::Tuple(vec![v]).to(),
|
||||
)
|
||||
} else {
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
}
|
||||
@ -1489,32 +1454,6 @@ impl BuiltinFunction {
|
||||
}
|
||||
})
|
||||
}),
|
||||
Self::GetRef => args[0].run(info).operate_on_data_mut(info, |container| {
|
||||
args[1].run(info).operate_on_data_immut(|i| {
|
||||
if let (VDataEnum::Reference(container), VDataEnum::Int(i)) = (container, i) {
|
||||
if *i >= 0 {
|
||||
// we can get mutably because this is the content of a reference
|
||||
match container.operate_on_data_mut(info, |container| match container {
|
||||
VDataEnum::List(_, v) | VDataEnum::Tuple(v) => {
|
||||
if let Some(v) = v.get_mut(*i as usize) {
|
||||
Some(VDataEnum::Reference(v.clone_mut()).to())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => unreachable!("get: not a reference/list/tuple"),
|
||||
}) {
|
||||
Some(v) => VDataEnum::Tuple(vec![v]).to(),
|
||||
None => VDataEnum::Tuple(vec![]).to(),
|
||||
}
|
||||
} else {
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
}
|
||||
} else {
|
||||
unreachable!("get_ref: not a reference and index")
|
||||
}
|
||||
})
|
||||
}),
|
||||
Self::Len => {
|
||||
if args.len() == 1 {
|
||||
VDataEnum::Int(args[0].run(info).operate_on_data_immut(|v| match v {
|
||||
|
@ -130,7 +130,7 @@ impl RStatement {
|
||||
None => unreachable!("can't dereference..."),
|
||||
};
|
||||
}
|
||||
val.assign(info, out);
|
||||
val.assign(out);
|
||||
}
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
} else {
|
||||
@ -181,7 +181,7 @@ impl RStatementEnum {
|
||||
}
|
||||
Self::FunctionCall(func, args) => {
|
||||
for (i, input) in func.inputs.iter().enumerate() {
|
||||
input.lock().unwrap().assign(info, args[i].run(info));
|
||||
input.lock().unwrap().assign(args[i].run(info));
|
||||
}
|
||||
func.run(info)
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ impl VData {
|
||||
/// 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, info: &GlobalScriptInfo, mut func: F) -> O
|
||||
pub fn operate_on_data_mut<F, O>(&mut self, mut func: F) -> O
|
||||
where
|
||||
F: FnOnce(&mut VDataEnum) -> O,
|
||||
{
|
||||
@ -116,25 +116,11 @@ impl VData {
|
||||
// *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.
|
||||
let new_vdata = VDataInner::Data(0, new_data).to();
|
||||
if info.log.vdata_clone.log() {
|
||||
drop(lock);
|
||||
info.log.log(LogMsg::VDataClone(
|
||||
#[cfg(debug_assertions)]
|
||||
self.1.clone(),
|
||||
#[cfg(not(debug_assertions))]
|
||||
None,
|
||||
self.inner_cloned(),
|
||||
Arc::as_ptr(&self.0) as usize,
|
||||
Arc::as_ptr(&new_vdata.0) as usize,
|
||||
));
|
||||
}
|
||||
(Some(new_vdata), o)
|
||||
}
|
||||
}
|
||||
VDataInner::Mut(inner) => {
|
||||
(None, inner.lock().unwrap().operate_on_data_mut(info, func))
|
||||
}
|
||||
VDataInner::ClonedFrom(inner) => (None, inner.operate_on_data_mut(info, func)),
|
||||
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 {
|
||||
@ -145,13 +131,13 @@ impl VData {
|
||||
|
||||
/// 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, info: &GlobalScriptInfo, new_data: VDataEnum) {
|
||||
let o = self.operate_on_data_mut(info, |d| *d = new_data);
|
||||
pub fn assign_data(&mut self, new_data: VDataEnum) {
|
||||
let o = self.operate_on_data_mut(|d| *d = new_data);
|
||||
o
|
||||
}
|
||||
/// Assigns the new_data to self. Affects all muts pointing to the same data, but no ClonedFroms.
|
||||
pub fn assign(&mut self, info: &GlobalScriptInfo, new: VData) {
|
||||
self.assign_data(info, new.inner_cloned())
|
||||
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) => {
|
||||
@ -244,6 +230,9 @@ impl VData {
|
||||
pub fn get(&self, i: usize) -> Option<VData> {
|
||||
self.operate_on_data_immut(|v| v.get(i))
|
||||
}
|
||||
pub fn get_ref(&mut self, i: usize) -> Option<VData> {
|
||||
self.operate_on_data_mut(|v| v.get_ref(i))
|
||||
}
|
||||
pub fn matches(&self) -> Option<Self> {
|
||||
match self.operate_on_data_immut(|v| v.matches()) {
|
||||
Some(Some(v)) => Some(v),
|
||||
@ -350,10 +339,28 @@ impl VDataEnum {
|
||||
None => None,
|
||||
},
|
||||
Self::Tuple(v) | Self::List(_, v) => v.get(i).cloned(),
|
||||
Self::Reference(r) => r.get(i),
|
||||
Self::Reference(r) => r.clone_mut().get_ref(i),
|
||||
Self::EnumVariant(_, v) => v.get(i),
|
||||
}
|
||||
}
|
||||
/// this is guaranteed to return Self::Reference(_), if it returns Some(_).
|
||||
pub fn get_ref(&mut self, i: usize) -> Option<VData> {
|
||||
Some(Self::Reference(self.get_ref_inner(i)?).to())
|
||||
}
|
||||
pub fn get_ref_inner(&mut self, i: usize) -> Option<VData> {
|
||||
match self {
|
||||
Self::Bool(..)
|
||||
| Self::Int(..)
|
||||
| Self::Float(..)
|
||||
| Self::Function(..)
|
||||
| Self::Thread(..) => None,
|
||||
// TODO: String
|
||||
Self::String(s) => None,
|
||||
Self::Tuple(v) | Self::List(_, v) => v.get(i).map(|v| v.clone_mut()),
|
||||
Self::Reference(r) => r.get_ref(i),
|
||||
Self::EnumVariant(_, v) => v.get_ref(i),
|
||||
}
|
||||
}
|
||||
pub fn matches_ref_bool(&self) -> bool {
|
||||
match self {
|
||||
VDataEnum::Tuple(v) => !v.is_empty(),
|
||||
|
@ -41,6 +41,20 @@ impl VSingleType {
|
||||
Self::String => Some(VSingleType::String.into()),
|
||||
Self::Tuple(t) => t.get(i).cloned(),
|
||||
Self::List(t) => Some(t.clone()),
|
||||
Self::Reference(r) => r.get_ref(i, gsinfo),
|
||||
Self::EnumVariant(_, t) | Self::EnumVariantS(_, t) => t.get(i, gsinfo),
|
||||
Self::CustomType(t) => gsinfo.custom_types[*t].get(i, gsinfo),
|
||||
&Self::CustomTypeS(_) => {
|
||||
unreachable!("CustomTypeS instead of CustomType, compiler bug? [get]")
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn get_ref(&self, i: usize, gsinfo: &GlobalScriptInfo) -> Option<VType> {
|
||||
match self {
|
||||
Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None,
|
||||
Self::String => Some(VSingleType::String.into()),
|
||||
Self::Tuple(t) => t.get(i).map(|v| v.reference()),
|
||||
Self::List(t) => Some(t.clone()),
|
||||
Self::Reference(r) => r.get(i, gsinfo),
|
||||
Self::EnumVariant(_, t) | Self::EnumVariantS(_, t) => t.get(i, gsinfo),
|
||||
Self::CustomType(t) => gsinfo.custom_types[*t].get(i, gsinfo),
|
||||
@ -113,6 +127,16 @@ impl VType {
|
||||
}
|
||||
Some(out)
|
||||
}
|
||||
pub fn reference(&self) -> Self {
|
||||
let mut out = Self::empty();
|
||||
Self {
|
||||
types: self
|
||||
.types
|
||||
.iter()
|
||||
.map(|v| VSingleType::Reference(Box::new(v.clone())))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VSingleType {
|
||||
@ -122,13 +146,30 @@ impl VSingleType {
|
||||
Self::String => Some(VSingleType::String.into()),
|
||||
Self::Tuple(t) => Some(t.iter().fold(VType { types: vec![] }, |a, b| a | b)),
|
||||
Self::List(t) => Some(t.clone()),
|
||||
Self::Reference(r) => r.get_any(info),
|
||||
Self::Reference(r) => r.get_any_ref(info),
|
||||
Self::EnumVariant(_, t) => t.get_any(info),
|
||||
Self::EnumVariantS(..) => unreachable!(),
|
||||
Self::CustomType(t) => info.custom_types[*t].get_any(info),
|
||||
Self::CustomTypeS(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn get_any_ref(&self, info: &GlobalScriptInfo) -> Option<VType> {
|
||||
match self {
|
||||
Self::Bool | Self::Int | Self::Float | Self::Function(..) | Self::Thread(..) => None,
|
||||
Self::String => Some(VSingleType::String.into()),
|
||||
Self::Tuple(t) => Some(
|
||||
t.iter()
|
||||
.fold(VType { types: vec![] }, |a, b| a | b.reference()),
|
||||
),
|
||||
Self::List(t) => Some(t.reference()),
|
||||
// TODO: idk if this is right...
|
||||
Self::Reference(r) => r.get_any_ref(info),
|
||||
Self::EnumVariant(_, t) => t.get_any_ref(info),
|
||||
Self::EnumVariantS(..) => unreachable!(),
|
||||
Self::CustomType(t) => info.custom_types[*t].get_any(info),
|
||||
Self::CustomTypeS(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
pub fn is_reference(&self) -> bool {
|
||||
match self {
|
||||
Self::Reference(_) => true,
|
||||
@ -151,6 +192,13 @@ impl VType {
|
||||
}
|
||||
Some(out)
|
||||
}
|
||||
pub fn get_any_ref(&self, info: &GlobalScriptInfo) -> Option<VType> {
|
||||
let mut out = VType { types: vec![] };
|
||||
for t in &self.types {
|
||||
out = out | t.get_any_ref(info)?; // if we can't use *get* on one type, we can't use it at all.
|
||||
}
|
||||
Some(out)
|
||||
}
|
||||
}
|
||||
|
||||
impl VType {
|
||||
|
@ -732,7 +732,7 @@ pub mod implementation {
|
||||
// int, float, var
|
||||
break {
|
||||
if let Ok(v) = start.parse() {
|
||||
if let Some('.') = nchar {
|
||||
if !is_part_of_chain_already && nchar == Some('.') {
|
||||
let pos = *file.get_pos();
|
||||
file.next();
|
||||
let mut pot_float = String::new();
|
||||
|
Loading…
Reference in New Issue
Block a user