fixed some bugs

This commit is contained in:
Dummi26
2023-03-10 13:44:18 +01:00
parent efff8c1d70
commit 6da8a77304
5 changed files with 108 additions and 35 deletions

View File

@@ -65,6 +65,12 @@ impl File {
None => None,
}
}
pub fn peek(&self) -> Option<char> {
match self.chars.get(self.pos.current_char_index) {
Some((_, c)) => Some(*c),
None => None,
}
}
}
impl Iterator for File {

View File

@@ -1,9 +1,9 @@
use crate::script::{
block::{
to_runnable, to_runnable::ToRunnableError, RFunction, RScript, SBlock, SFunction,
SStatement, SStatementEnum,
to_runnable, to_runnable::ToRunnableError, RScript, SBlock, SFunction, SStatement,
SStatementEnum,
},
value::{VData, VDataEnum, VSingleType, VType},
value::{VDataEnum, VSingleType, VType},
};
use super::file::File;
@@ -113,18 +113,30 @@ fn parse_statement_adv(
) -> Result<SStatement, ParseError> {
file.skip_whitespaces();
let mut start = String::new();
let out = match file.get_char(file.get_char_index()) {
let out = match file.peek() {
Some('{') => Some(SStatementEnum::Block(parse_block(file)?).into()),
Some('[') => {
file.next();
let mut v = vec![];
let mut list = false;
loop {
file.skip_whitespaces();
if let Some(']') = file.get_char(file.get_char_index()) {
if let Some(']') = file.peek() {
file.next();
if file[file.get_char_index()..].starts_with("[]") {
list = true;
file.next();
file.next();
}
break;
}
v.push(parse_statement(file)?);
}
Some(SStatementEnum::Tuple(v).into())
Some(if list {
SStatementEnum::List(v).into()
} else {
SStatementEnum::Tuple(v).into()
})
}
Some('$') => {
file.next();
@@ -163,12 +175,16 @@ fn parse_statement_adv(
out
} else {
loop {
match file.next() {
match match file.peek() {
Some(ch) if matches!(ch, '}' | ')' | '.') => Some(ch),
_ => file.next(),
} {
Some('=') => {
break parse_statement(file)?.output_to(start.trim().to_string());
}
Some(ch) if ch.is_whitespace() || matches!(ch, '}' | ')' | '.') => {
if let Some('=') = file.get_char(file.get_char_index()) {
Some(ch) if (ch.is_whitespace() || ch == '}' || ch == ')' || ch == '.') => {
file.skip_whitespaces();
if let Some('=') = file.peek() {
continue;
} else {
let start = start.trim();
@@ -230,7 +246,14 @@ fn parse_statement_adv(
}
"switch" | "switch!" => {
let force = start.ends_with("!");
let switch_on_what = parse_statement(file)?;
let mut switch_on_what = String::new();
loop {
match file.next() {
None => break,
Some(ch) if ch.is_whitespace() => break,
Some(ch) => switch_on_what.push(ch),
}
}
file.skip_whitespaces();
if let Some('{') = file.next() {
} else {
@@ -239,12 +262,17 @@ fn parse_statement_adv(
let mut cases = vec![];
loop {
file.skip_whitespaces();
if let Some('}') = file.get_char(file.get_char_index()) {
if let Some('}') = file.peek() {
break;
}
cases.push((parse_type(file)?, parse_statement(file)?));
}
break SStatementEnum::Switch(switch_on_what, cases, force).into();
break SStatementEnum::Switch(
SStatementEnum::Variable(switch_on_what).into(),
cases,
force,
)
.into();
}
"true" => {
break SStatementEnum::Value(VDataEnum::Bool(true).to()).into()
@@ -350,7 +378,7 @@ fn parse_type_adv(file: &mut File, in_fn_args: bool) -> Result<(VType, bool), Pa
break;
}
file.skip_whitespaces();
match file.get_char(file.get_char_index()) {
match file.peek() {
Some('/') => (),
_ => break,
}
@@ -375,12 +403,15 @@ fn parse_single_type_adv(
Some('[') => {
let mut types = vec![];
loop {
types.push(parse_single_type(file)?.into());
file.skip_whitespaces();
match file.get_char(file.get_char_index()) {
Some(']') => break,
match file.peek() {
Some(']') => {
file.next();
break;
}
_ => (),
}
types.push(parse_single_type(file)?.into());
}
if types.len() == 1 {
VSingleType::List(types.pop().unwrap())
@@ -391,6 +422,10 @@ fn parse_single_type_adv(
Some(ch) => {
let mut name = ch.to_string();
loop {
match file.peek() {
Some(']') => break,
_ => (),
}
match file.next() {
Some(ch) if ch.is_whitespace() => break,
Some(')') if in_fn_args => {

View File

@@ -2,17 +2,15 @@
// Types starting with S are directly parsed from Strings and unchecked. Types starting with T are type-checked templates for R-types. Types starting with R are runnable. S are converted to T after parsing is done, and T are converted to R whenever they need to run.
use std::{
collections::HashMap,
fmt::Display,
sync::{Arc, Mutex},
time::Duration,
};
use self::to_runnable::ToRunnableError;
use super::{
builtins::BuiltinFunction,
value::{VData, VDataEnum, VDataThreadEnum, VSingleType, VType},
value::{VData, VDataEnum, VSingleType, VType},
};
// Represents a block of code
@@ -60,6 +58,7 @@ impl SStatement {
pub enum SStatementEnum {
Value(VData),
Tuple(Vec<SStatement>),
List(Vec<SStatement>),
Variable(String),
FunctionCall(String, Vec<SStatement>),
FunctionDefinition(Option<String>, SFunction),
@@ -94,11 +93,11 @@ pub mod to_runnable {
sync::Arc,
};
use crate::script::value::{VData, VDataEnum, VSingleType, VType};
use crate::script::value::{VDataEnum, VSingleType, VType};
use super::{
Am, BuiltinFunction, RBlock, RFunction, RScript, RStatement, RStatementEnum, SBlock,
SFunction, SStatement, SStatementEnum,
BuiltinFunction, RBlock, RFunction, RScript, RStatement, RStatementEnum, SBlock, SFunction,
SStatement, SStatementEnum,
};
pub enum ToRunnableError {
@@ -253,12 +252,16 @@ pub mod to_runnable {
) -> Result<RStatement, ToRunnableError> {
let mut statement = match &*s.statement {
SStatementEnum::Value(v) => RStatementEnum::Value(v.clone()),
SStatementEnum::Tuple(v) => {
SStatementEnum::Tuple(v) | SStatementEnum::List(v) => {
let mut w = Vec::with_capacity(v.len());
for v in v {
w.push(statement(v, ginfo, linfo)?);
}
RStatementEnum::Tuple(w)
if let SStatementEnum::List(_) = &*s.statement {
RStatementEnum::List(w)
} else {
RStatementEnum::Tuple(w)
}
}
SStatementEnum::Variable(v) => {
if let Some(var) = linfo.vars.get(v) {
@@ -376,7 +379,6 @@ pub mod to_runnable {
let mut ncases = Vec::with_capacity(cases.len());
for case in cases {
ncases.push((case.0.clone(), statement(&case.1, ginfo, linfo)?));
eprintln!("NCASE: {:#?}", ncases.last().unwrap().0);
}
let switch_on = statement(switch_on, ginfo, linfo)?;
let switch_on_out = switch_on.out();
@@ -386,7 +388,6 @@ pub mod to_runnable {
'force: {
for (case_type, _) in ncases.iter() {
if val_type.fits_in(&case_type).is_empty() {
eprintln!("Breaking.");
break 'force;
}
}
@@ -503,6 +504,7 @@ impl RStatement {
pub enum RStatementEnum {
Value(VData),
Tuple(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
FunctionCall(Arc<RFunction>, Vec<RStatement>),
BuiltinFunction(BuiltinFunction, Vec<RStatement>),
@@ -523,6 +525,16 @@ impl RStatementEnum {
}
VDataEnum::Tuple(w).to()
}
Self::List(v) => {
let mut w = vec![];
let mut out = VType { types: vec![] };
for v in v {
let val = v.run(vars);
out = out | val.out();
w.push(val);
}
VDataEnum::List(out, w).to()
}
Self::Variable(v, _) => vars[*v].lock().unwrap().clone(),
Self::FunctionCall(func, args) => {
for (i, input) in func.inputs.iter().enumerate() {
@@ -576,7 +588,7 @@ impl RStatementEnum {
in_loop(VDataEnum::String(ch.to_string()).to())
}
}
VDataEnum::Tuple(v) | VDataEnum::List(v) => {
VDataEnum::Tuple(v) | VDataEnum::List(_, v) => {
for v in v {
in_loop(v)
}
@@ -603,7 +615,9 @@ impl RStatementEnum {
pub fn out(&self) -> VType {
match self {
Self::Value(v) => v.out(),
Self::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out()).collect()).into(),
Self::Tuple(v) | Self::List(v) => {
VSingleType::Tuple(v.iter().map(|v| v.out()).collect()).into()
}
Self::Variable(_, t) => t.clone(),
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.");
@@ -658,6 +672,7 @@ impl RScript {
pub fn run(&self, args: Vec<String>) -> VData {
let mut vars = Vec::with_capacity(self.vars);
vars.push(am(VDataEnum::List(
VSingleType::String.into(),
args.into_iter()
.map(|v| VDataEnum::String(v).to())
.collect(),
@@ -744,6 +759,13 @@ impl Display for SStatementEnum {
v.iter().map(|v| format!("{} ", v)).collect::<String>()
)
}
SStatementEnum::List(v) => {
write!(
f,
"[{} ...]",
v.iter().map(|v| format!("{} ", v)).collect::<String>()
)
}
SStatementEnum::Variable(v) => write!(f, "{v}"),
SStatementEnum::FunctionCall(func, args) => {
write!(f, "{func}(")?;
@@ -805,7 +827,7 @@ impl Display for VDataEnum {
Self::Int(v) => write!(f, "{v}"),
Self::Float(v) => write!(f, "{v}"),
Self::String(v) => write!(f, "{v}"),
Self::Tuple(v) | Self::List(v) => {
Self::Tuple(v) | Self::List(_, v) => {
write!(f, "[")?;
for v in v {
write!(f, "{v}")?;

View File

@@ -26,9 +26,7 @@ impl VData {
VDataEnum::Float(..) => VSingleType::Float,
VDataEnum::String(..) => VSingleType::String,
VDataEnum::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out()).collect()),
VDataEnum::List(v) => {
VSingleType::List(v.iter().fold(VType { types: vec![] }, |a, b| a | b.out()))
}
VDataEnum::List(t, _) => VSingleType::List(t.clone()),
VDataEnum::Function(f) => VSingleType::Function(f.in_types().clone(), {
eprintln!("Warn: generalizing function return type, disregarding input types. might make the type checker think it can return types it can only return with different arguments as the ones that were actually provided.");
f.out_all()
@@ -45,7 +43,7 @@ pub enum VDataEnum {
Float(f64),
String(String),
Tuple(Vec<VData>),
List(Vec<VData>),
List(VType, Vec<VData>),
Function(RFunction),
Thread(VDataThread, VType),
}