- fixed a bug with t.fits_in(rhs) regarding inner types

- added //...\n and /*...*/ comment syntax
- added tuple.n indexing, where n is an int <= the tuples length (this is checked before the script runs)
This commit is contained in:
Dummi26 2023-03-12 15:42:19 +01:00
parent 15b78dc0b6
commit a4fbb8dd97
5 changed files with 186 additions and 25 deletions

View File

@ -6,8 +6,21 @@ pub(crate) mod parse;
pub(crate) mod script;
fn main() {
let str1: VType = VSingleType::String.into();
assert!(str1.fits_in(&VSingleType::String.into()).is_empty());
let val: VType = VSingleType::Tuple(vec![
VSingleType::Int.into(),
VSingleType::String.into(),
VSingleType::String.into(),
])
.into();
let case: VType = VSingleType::Tuple(vec![
VType {
types: vec![VSingleType::Tuple(vec![]).into(), VSingleType::Int.into()],
},
VSingleType::String.into(),
VSingleType::String.into(),
])
.into();
assert!(val.fits_in(&case).is_empty());
let script = parse::parse::parse(&mut parse::file::File::new(
std::fs::read_to_string("/tmp/script.txt").unwrap(),
))

View File

@ -25,6 +25,41 @@ impl Display for FilePosition {
impl File {
pub fn new(data: String) -> Self {
let mut chs = data.chars();
let mut data = String::with_capacity(data.len());
loop {
match chs.next() {
Some('/') => match chs.next() {
Some('/') => loop {
match chs.next() {
Some('\n') | None => break,
_ => (),
}
},
Some('*') => loop {
match chs.next() {
Some('*') => {
if let Some('/') = chs.next() {
break;
}
}
None => break,
_ => (),
}
},
Some(ch) => {
data.push('/');
data.push(ch);
}
None => {
data.push('/');
break;
}
},
Some(ch) => data.push(ch),
None => break,
}
}
let chars = data.char_indices().collect();
Self {
data,

View File

@ -271,12 +271,7 @@ fn parse_statement_adv(
}
cases.push((parse_type(file)?, parse_statement(file)?));
}
break SStatementEnum::Switch(
SStatementEnum::Variable(switch_on_what).into(),
cases,
force,
)
.into();
break SStatementEnum::Switch(switch_on_what, cases, force).into();
}
"true" => {
break SStatementEnum::Value(VDataEnum::Bool(true).to()).into()
@ -332,6 +327,10 @@ fn parse_statement_adv(
let args = [out].into_iter().chain(args.into_iter()).collect();
SStatementEnum::FunctionCall(func, args).into()
}
SStatementEnum::Value(vd) => match vd.data {
VDataEnum::Int(i) => SStatementEnum::IndexFixed(out, i as _).into(),
_ => todo!("fixed-indexing not available with this type."),
},
other => {
todo!("Wrapping in this type isn't implemented (yet?). Type: {other:?}")
}

View File

@ -66,8 +66,9 @@ pub enum SStatementEnum {
If(SStatement, SStatement, Option<SStatement>),
While(SStatement),
For(String, SStatement, SStatement),
Switch(SStatement, Vec<(VType, SStatement)>, bool),
Switch(String, Vec<(VType, SStatement)>, bool),
// Match(???),
IndexFixed(SStatement, usize),
}
impl Into<SStatement> for SStatementEnum {
fn into(self) -> SStatement {
@ -112,6 +113,7 @@ pub mod to_runnable {
},
InvalidTypeForWhileLoop(VType),
CaseForceButTypeNotCovered(VType),
NotIndexableFixed(VType, usize),
}
impl Debug for ToRunnableError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@ -137,6 +139,7 @@ pub mod to_runnable {
}
Self::InvalidTypeForWhileLoop(v) => write!(f, "Invalid type: Expected bool or Tuples of length 0 or 1 as return types for the while loop, but found {v:?} instead."),
Self::CaseForceButTypeNotCovered(v) => write!(f, "Switch! statement, but not all types covered. Types to cover: {v}"),
Self::NotIndexableFixed(t, i) => write!(f, "Cannot use fixed-index {i} on type {t}."),
}
}
}
@ -376,17 +379,23 @@ pub mod to_runnable {
o
}
SStatementEnum::Switch(switch_on, cases, force) => {
if let Some(switch_on_v) = linfo.vars.get(switch_on).cloned() {
let mut ncases = Vec::with_capacity(cases.len());
let og_type = linfo.vars.get(switch_on).unwrap().1.clone();
for case in cases {
linfo.vars.get_mut(switch_on).unwrap().1 = case.0.clone();
ncases.push((case.0.clone(), statement(&case.1, ginfo, linfo)?));
}
let switch_on = statement(switch_on, ginfo, linfo)?;
let switch_on_out = switch_on.out();
linfo.vars.get_mut(switch_on).unwrap().1 = og_type;
let switch_on_out = switch_on_v.1;
if *force {
for val_type in switch_on_out.types.iter() {
let val_type: VType = val_type.clone().into();
let mut linf2 = linfo.clone();
linf2.vars.get_mut(switch_on).unwrap().1 = val_type.clone();
'force: {
for (case_type, _) in ncases.iter() {
for (case_type, _) in cases {
if val_type.fits_in(&case_type).is_empty() {
break 'force;
}
@ -395,7 +404,37 @@ pub mod to_runnable {
}
}
}
RStatementEnum::Switch(switch_on, ncases)
RStatementEnum::Switch(
RStatementEnum::Variable(switch_on_v.0, switch_on_out).to(),
ncases,
)
} else {
return Err(ToRunnableError::UseOfUndefinedVariable(switch_on.clone()));
}
}
SStatementEnum::IndexFixed(st, i) => {
let st = statement(st, ginfo, linfo)?;
let ok = 'ok: {
let mut one = false;
for t in st.out().types {
one = true;
// only if all types are indexable by i
match t {
VSingleType::Tuple(v) => {
if v.len() <= *i {
break 'ok false;
}
}
_ => break 'ok false,
}
}
one
};
if ok {
RStatementEnum::IndexFixed(st, *i)
} else {
return Err(ToRunnableError::NotIndexableFixed(st.out(), *i));
}
}
}
.to();
@ -523,6 +562,7 @@ pub enum RStatementEnum {
While(RStatement),
For(usize, RStatement, RStatement),
Switch(RStatement, Vec<(VType, RStatement)>),
IndexFixed(RStatement, usize),
}
impl RStatementEnum {
pub fn run(&self, vars: &Vec<Am<VData>>) -> VData {
@ -620,6 +660,7 @@ impl RStatementEnum {
}
out
}
Self::IndexFixed(st, i) => st.run(vars).get(*i).unwrap(),
}
}
pub fn out(&self) -> VType {
@ -657,6 +698,7 @@ impl RStatementEnum {
}
out
}
Self::IndexFixed(st, i) => st.out().get(*i).unwrap(),
}
}
pub fn to(self) -> RStatement {
@ -820,6 +862,7 @@ impl Display for SStatementEnum {
}
write!(f, "}}")
}
SStatementEnum::IndexFixed(st, i) => write!(f, "{st}.{i}"),
}
}
}

View File

@ -34,6 +34,9 @@ impl VData {
VDataEnum::Thread(_, o) => VSingleType::Thread(o.clone()),
}
}
pub fn get(&self, i: usize) -> Option<Self> {
self.data.get(i)
}
}
#[derive(Clone, Debug)]
@ -118,6 +121,45 @@ impl VDataEnum {
}
}
// get()
impl VDataEnum {
pub fn get(&self, i: usize) -> Option<VData> {
match self {
Self::Bool(..)
| Self::Int(..)
| Self::Float(..)
| Self::Function(..)
| Self::Thread(..) => None,
Self::String(s) => match s.chars().nth(i) {
// Slow!
Some(ch) => Some(Self::String(format!("{ch}")).to()),
None => None,
},
Self::Tuple(v) | Self::List(_, v) => v.get(i).cloned(),
}
}
}
impl VSingleType {
// None => Cannot get, Some(t) => getting can return t or nothing
pub fn get(&self, i: usize) -> 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).cloned(),
Self::List(t) => Some(t.clone()),
}
}
}
impl VType {
pub fn get(&self, i: usize) -> Option<VType> {
let mut out = VType { types: vec![] };
for t in &self.types {
out = out | t.get(i)?; // if we can't use *get* on one type, we can't use it at all.
}
Some(out)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VType {
pub types: Vec<VSingleType>,
@ -127,7 +169,8 @@ impl VType {
pub fn fits_in(&self, rhs: &Self) -> Vec<VSingleType> {
let mut no = vec![];
for t in &self.types {
if !rhs.types.contains(t) {
// if t doesnt fit in any of rhs's types
if !rhs.types.iter().any(|r| t.fits_in(r)) {
no.push(t.clone())
}
}
@ -187,6 +230,34 @@ impl VSingleType {
_ => vec![],
}
}
pub fn fits_in(&self, rhs: &Self) -> bool {
match (self, rhs) {
(Self::Bool, Self::Bool)
| (Self::Int, Self::Int)
| (Self::Float, Self::Float)
| (Self::String, Self::String) => true,
(Self::Bool | Self::Int | Self::Float | Self::String, _) => false,
(Self::Tuple(a), Self::Tuple(b)) => {
if a.len() == b.len() {
a.iter().zip(b.iter()).all(|(a, b)| a.fits_in(b).is_empty())
} else {
false
}
}
(Self::Tuple(_), _) => false,
(Self::List(a), Self::List(b)) => a.fits_in(b).is_empty(),
(Self::List(_), _) => false,
(Self::Function(ai, ao), Self::Function(bi, bo)) => {
ai.iter()
.zip(bi.iter())
.all(|(a, b)| a.fits_in(b).is_empty())
&& ao.fits_in(bo).is_empty()
}
(Self::Function(..), _) => false,
(Self::Thread(a), Self::Thread(b)) => a.fits_in(b).is_empty(),
(Self::Thread(..), _) => false,
}
}
}
impl Into<VType> for VSingleType {