This commit is contained in:
Dummi26 2023-03-09 18:51:58 +01:00
parent f2d176e0dd
commit efff8c1d70
3 changed files with 69 additions and 139 deletions

View File

@ -115,6 +115,17 @@ fn parse_statement_adv(
let mut start = String::new(); let mut start = String::new();
let out = match file.get_char(file.get_char_index()) { let out = match file.get_char(file.get_char_index()) {
Some('{') => Some(SStatementEnum::Block(parse_block(file)?).into()), Some('{') => Some(SStatementEnum::Block(parse_block(file)?).into()),
Some('[') => {
let mut v = vec![];
loop {
file.skip_whitespaces();
if let Some(']') = file.get_char(file.get_char_index()) {
break;
}
v.push(parse_statement(file)?);
}
Some(SStatementEnum::Tuple(v).into())
}
Some('$') => { Some('$') => {
file.next(); file.next();
file.skip_whitespaces(); file.skip_whitespaces();
@ -162,6 +173,23 @@ fn parse_statement_adv(
} else { } else {
let start = start.trim(); let start = start.trim();
match start { match start {
"fn" => {
file.skip_whitespaces();
let mut fn_name = String::new();
loop {
match file.next() {
Some('(') => break,
Some(ch) => fn_name.push(ch),
None => break,
}
}
let func = parse_function(file)?;
break SStatementEnum::FunctionDefinition(
Some(fn_name.trim().to_string()),
func,
)
.into();
}
"if" => { "if" => {
// TODO: Else // TODO: Else
let condition = parse_statement(file)?; let condition = parse_statement(file)?;

View File

@ -10,7 +10,10 @@ use std::{
use self::to_runnable::ToRunnableError; use self::to_runnable::ToRunnableError;
use super::value::{VData, VDataEnum, VDataThreadEnum, VSingleType, VType}; use super::{
builtins::BuiltinFunction,
value::{VData, VDataEnum, VDataThreadEnum, VSingleType, VType},
};
// Represents a block of code // Represents a block of code
#[derive(Debug)] #[derive(Debug)]
@ -56,6 +59,7 @@ impl SStatement {
#[derive(Debug)] #[derive(Debug)]
pub enum SStatementEnum { pub enum SStatementEnum {
Value(VData), Value(VData),
Tuple(Vec<SStatement>),
Variable(String), Variable(String),
FunctionCall(String, Vec<SStatement>), FunctionCall(String, Vec<SStatement>),
FunctionDefinition(Option<String>, SFunction), FunctionDefinition(Option<String>, SFunction),
@ -249,6 +253,13 @@ pub mod to_runnable {
) -> Result<RStatement, ToRunnableError> { ) -> Result<RStatement, ToRunnableError> {
let mut statement = match &*s.statement { let mut statement = match &*s.statement {
SStatementEnum::Value(v) => RStatementEnum::Value(v.clone()), SStatementEnum::Value(v) => RStatementEnum::Value(v.clone()),
SStatementEnum::Tuple(v) => {
let mut w = Vec::with_capacity(v.len());
for v in v {
w.push(statement(v, ginfo, linfo)?);
}
RStatementEnum::Tuple(w)
}
SStatementEnum::Variable(v) => { SStatementEnum::Variable(v) => {
if let Some(var) = linfo.vars.get(v) { if let Some(var) = linfo.vars.get(v) {
RStatementEnum::Variable(var.0, var.1.clone()) RStatementEnum::Variable(var.0, var.1.clone())
@ -282,21 +293,12 @@ pub mod to_runnable {
} }
RStatementEnum::FunctionCall(func.clone(), rargs) RStatementEnum::FunctionCall(func.clone(), rargs)
} else { } else {
RStatementEnum::BuiltinFunction(
// TODO: type-checking for builtins // TODO: type-checking for builtins
match v.as_str() { if let Some(builtin) = BuiltinFunction::get(v) {
"print" => BuiltinFunction::Print, RStatementEnum::BuiltinFunction(builtin, rargs)
"debug" => BuiltinFunction::Debug, } else {
"to_string" => BuiltinFunction::ToString, return Err(ToRunnableError::UseOfUndefinedFunction(v.clone()));
"format" => BuiltinFunction::Format, }
"run" => BuiltinFunction::Run,
"thread" => BuiltinFunction::Thread,
"await" => BuiltinFunction::Await,
"sleep" => BuiltinFunction::Sleep,
_ => return Err(ToRunnableError::UseOfUndefinedFunction(v.clone())),
},
rargs,
)
} }
} }
SStatementEnum::FunctionDefinition(name, f) => { SStatementEnum::FunctionDefinition(name, f) => {
@ -443,10 +445,10 @@ impl RBlock {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct RFunction { pub struct RFunction {
inputs: Vec<usize>, pub inputs: Vec<usize>,
input_types: Vec<VType>, pub input_types: Vec<VType>,
input_output_map: Vec<(Vec<VSingleType>, VType)>, pub input_output_map: Vec<(Vec<VSingleType>, VType)>,
block: RBlock, pub block: RBlock,
} }
impl RFunction { impl RFunction {
pub fn run(&self, vars: &Vec<Am<VData>>) -> VData { pub fn run(&self, vars: &Vec<Am<VData>>) -> VData {
@ -500,6 +502,7 @@ impl RStatement {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum RStatementEnum { pub enum RStatementEnum {
Value(VData), Value(VData),
Tuple(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 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>), FunctionCall(Arc<RFunction>, Vec<RStatement>),
BuiltinFunction(BuiltinFunction, Vec<RStatement>), BuiltinFunction(BuiltinFunction, Vec<RStatement>),
@ -509,30 +512,17 @@ pub enum RStatementEnum {
For(usize, RStatement, RStatement), For(usize, RStatement, RStatement),
Switch(RStatement, Vec<(VType, RStatement)>), Switch(RStatement, Vec<(VType, RStatement)>),
} }
#[derive(Clone, Debug)]
pub enum BuiltinFunction {
// print
Print,
Debug,
// format
ToString,
Format,
// math and basic operators (not possible, need to be different for each type)
// Add,
// Sub,
// Mul,
// Div,
// Mod,
// functions
Run,
Thread,
Await,
Sleep,
}
impl RStatementEnum { impl RStatementEnum {
pub fn run(&self, vars: &Vec<Am<VData>>) -> VData { pub fn run(&self, vars: &Vec<Am<VData>>) -> VData {
match self { match self {
Self::Value(v) => v.clone(), Self::Value(v) => v.clone(),
Self::Tuple(v) => {
let mut w = vec![];
for v in v {
w.push(v.run(vars));
}
VDataEnum::Tuple(w).to()
}
Self::Variable(v, _) => vars[*v].lock().unwrap().clone(), Self::Variable(v, _) => vars[*v].lock().unwrap().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() {
@ -595,95 +585,7 @@ impl RStatementEnum {
} }
VDataEnum::Tuple(vec![]).to() VDataEnum::Tuple(vec![]).to()
} }
Self::BuiltinFunction(v, args) => match v { Self::BuiltinFunction(v, args) => v.run(args, vars),
BuiltinFunction::Print => {
if let VDataEnum::String(arg) = args[0].run(vars).data {
println!("{}", arg);
VDataEnum::Tuple(vec![]).to()
} else {
unreachable!()
}
}
BuiltinFunction::Debug => {
println!("{:?}", args[0].run(vars).data);
VDataEnum::Tuple(vec![]).to()
}
BuiltinFunction::ToString => {
VDataEnum::String(format!("{}", args[0].run(vars).data)).to()
}
BuiltinFunction::Format => todo!("Format function (and validity check!)"),
BuiltinFunction::Run => {
if args.len() >= 1 {
if let VDataEnum::Function(f) = args[0].run(vars).data {
if f.inputs.len() != args.len() - 1 {
unreachable!()
}
for (i, var) in f.inputs.iter().enumerate() {
let val = args[i + 1].run(vars);
*vars[*var].lock().unwrap() = val;
}
f.run(vars)
} else {
unreachable!()
}
} else {
unreachable!()
}
}
BuiltinFunction::Thread => {
if args.len() >= 1 {
if let VDataEnum::Function(f) = args[0].run(vars).data {
if f.inputs.len() != args.len() - 1 {
unreachable!()
}
// to prevent weird stuff from happening, the function args will be stored in different Arc<Mutex<_>>s. This means that the args are different for each thread, while any variables that are captured from outside will be shared.
let mut thread_vars = vars.clone();
let mut run_input_types = vec![];
for (i, var) in f.inputs.iter().enumerate() {
let val = args[i + 1].run(vars);
run_input_types.push(val.out_single());
thread_vars[*var] = Arc::new(Mutex::new(val));
}
let out_type = f.out(&run_input_types);
VDataEnum::Thread(
VDataThreadEnum::Running(std::thread::spawn(move || {
f.run(&thread_vars)
}))
.to(),
out_type,
)
.to()
} else {
unreachable!()
}
} else {
unreachable!()
}
}
BuiltinFunction::Await => {
if args.len() == 1 {
if let VDataEnum::Thread(t, _) = args[0].run(vars).data {
t.get()
} else {
unreachable!()
}
} else {
unreachable!()
}
}
BuiltinFunction::Sleep => {
if args.len() == 1 {
match args[0].run(vars).data {
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(v as _)),
VDataEnum::Float(v) => std::thread::sleep(Duration::from_secs_f64(v)),
_ => unreachable!(),
}
VDataEnum::Tuple(vec![]).to()
} else {
unreachable!()
}
}
},
Self::Switch(switch_on, cases) => { Self::Switch(switch_on, cases) => {
let switch_on = switch_on.run(vars); let switch_on = switch_on.run(vars);
let switch_on_type = switch_on.out(); let switch_on_type = switch_on.out();
@ -701,6 +603,7 @@ impl RStatementEnum {
pub fn out(&self) -> VType { pub fn out(&self) -> VType {
match self { match self {
Self::Value(v) => v.out(), Self::Value(v) => v.out(),
Self::Tuple(v) => VSingleType::Tuple(v.iter().map(|v| v.out()).collect()).into(),
Self::Variable(_, t) => t.clone(), Self::Variable(_, t) => t.clone(),
Self::FunctionCall(f, _) => { 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."); 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.");
@ -722,16 +625,7 @@ impl RStatementEnum {
types: vec![VSingleType::Tuple(vec![])], types: vec![VSingleType::Tuple(vec![])],
} }
} }
Self::BuiltinFunction(f, _) => match f { Self::BuiltinFunction(f, _) => f.returns(),
BuiltinFunction::Print | BuiltinFunction::Debug | BuiltinFunction::Sleep => VType {
types: vec![VSingleType::Tuple(vec![])],
},
BuiltinFunction::ToString | BuiltinFunction::Format => VSingleType::String.into(),
BuiltinFunction::Run | BuiltinFunction::Thread | BuiltinFunction::Await => {
VType { types: vec![] } // TODO!
// unreachable!("this has to be implemented somewhere else!")
}
},
Self::Switch(_, cases) => { Self::Switch(_, cases) => {
let mut out = VSingleType::Tuple(vec![]).into(); // if nothing is executed let mut out = VSingleType::Tuple(vec![]).into(); // if nothing is executed
for (_, case) in cases.iter() { for (_, case) in cases.iter() {
@ -843,6 +737,13 @@ impl Display for SStatementEnum {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
SStatementEnum::Value(v) => write!(f, "{v}"), SStatementEnum::Value(v) => write!(f, "{v}"),
SStatementEnum::Tuple(v) => {
write!(
f,
"[{}]",
v.iter().map(|v| format!("{} ", v)).collect::<String>()
)
}
SStatementEnum::Variable(v) => write!(f, "{v}"), SStatementEnum::Variable(v) => write!(f, "{v}"),
SStatementEnum::FunctionCall(func, args) => { SStatementEnum::FunctionCall(func, args) => {
write!(f, "{func}(")?; write!(f, "{func}(")?;

View File

@ -1,2 +1,3 @@
pub mod block; pub mod block;
pub mod builtins;
pub mod value; pub mod value;