mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
.
This commit is contained in:
parent
f2d176e0dd
commit
efff8c1d70
@ -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)?;
|
||||||
|
@ -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}(")?;
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
pub mod block;
|
pub mod block;
|
||||||
|
pub mod builtins;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
Loading…
Reference in New Issue
Block a user