mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-14 19:26:17 +01:00
fixed some bugs
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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}")?;
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user