mirror of
https://github.com/Dummi26/mers.git
synced 2025-12-15 03:36:16 +01:00
there can now be multiple functions with the same name. The most recently declared one will be preferred if multiple would be valid.
This commit is contained in:
@@ -19,8 +19,8 @@ pub enum RStatementEnum {
|
||||
List(Vec<RStatement>),
|
||||
Variable(Arc<Mutex<VData>>, VType, bool),
|
||||
FunctionCall(Arc<RFunction>, Vec<RStatement>),
|
||||
BuiltinFunction(BuiltinFunction, Vec<RStatement>),
|
||||
LibFunction(usize, usize, Vec<RStatement>, VType),
|
||||
BuiltinFunctionCall(BuiltinFunction, Vec<RStatement>),
|
||||
LibFunctionCall(usize, usize, Vec<RStatement>, VType),
|
||||
Block(RBlock),
|
||||
If(RStatement, RStatement, Option<RStatement>),
|
||||
Loop(RStatement),
|
||||
@@ -186,8 +186,8 @@ impl RStatementEnum {
|
||||
}
|
||||
func.run(info)
|
||||
}
|
||||
Self::BuiltinFunction(v, args) => v.run(args, info),
|
||||
Self::LibFunction(libid, fnid, args, _) => {
|
||||
Self::BuiltinFunctionCall(v, args) => v.run(args, info),
|
||||
Self::LibFunctionCall(libid, fnid, args, _) => {
|
||||
info.libs[*libid].run_fn(*fnid, args.iter().map(|arg| arg.run(info)).collect())
|
||||
}
|
||||
Self::Block(b) => b.run(info),
|
||||
@@ -343,7 +343,7 @@ impl RStatementEnum {
|
||||
Self::FunctionCall(f, args) => {
|
||||
f.out_vt(&args.iter().map(|v| v.out(info)).collect(), info)
|
||||
}
|
||||
Self::LibFunction(.., out) => out.clone(),
|
||||
Self::LibFunctionCall(.., out) => out.clone(),
|
||||
Self::Block(b) => b.out(info),
|
||||
Self::If(_, a, b) => {
|
||||
if let Some(b) = b {
|
||||
@@ -354,7 +354,7 @@ impl RStatementEnum {
|
||||
}
|
||||
Self::Loop(c) => c.out(info).matches().1,
|
||||
Self::For(_, _, b) => VSingleType::Tuple(vec![]).to() | b.out(info).matches().1,
|
||||
Self::BuiltinFunction(f, args) => {
|
||||
Self::BuiltinFunctionCall(f, args) => {
|
||||
f.returns(args.iter().map(|rs| rs.out(info)).collect(), info)
|
||||
}
|
||||
Self::Switch(switch_on, cases, force) => {
|
||||
|
||||
@@ -33,7 +33,7 @@ pub enum ToRunnableError {
|
||||
CannotDeclareVariableWithDereference(String),
|
||||
CannotDereferenceTypeNTimes(VType, usize, VType),
|
||||
FunctionWrongArgCount(String, usize, usize),
|
||||
FunctionWrongArgs(Vec<VType>, String),
|
||||
FunctionWrongArgs(String, Vec<Arc<RFunction>>, Vec<VType>),
|
||||
InvalidType {
|
||||
expected: VType,
|
||||
found: VType,
|
||||
@@ -87,7 +87,7 @@ impl FormatGs for ToRunnableError {
|
||||
Ok(())
|
||||
},
|
||||
Self::FunctionWrongArgCount(v, a, b) => write!(f, "Tried to call function \"{v}\", which takes {a} arguments, with {b} arguments instead."),
|
||||
Self::FunctionWrongArgs(args, name) => write!(f, "Wrong args for function \"{name}\":{}", args.iter().map(|v| format!(" {v}")).collect::<String>()),
|
||||
Self::FunctionWrongArgs(fn_name, possible_fns, given_types) => write!(f, "Wrong args for function \"{fn_name}\": {} (possible fns: {})", given_types.iter().map(|v| format!(" {v}")).collect::<String>(), ""),
|
||||
Self::InvalidType {
|
||||
expected,
|
||||
found,
|
||||
@@ -164,7 +164,7 @@ impl FormatGs for ToRunnableError {
|
||||
#[derive(Clone)]
|
||||
struct LInfo {
|
||||
vars: HashMap<String, (Arc<Mutex<VData>>, VType)>,
|
||||
fns: HashMap<String, Arc<RFunction>>,
|
||||
fns: HashMap<String, Vec<Arc<RFunction>>>,
|
||||
}
|
||||
|
||||
pub fn to_runnable(
|
||||
@@ -461,25 +461,37 @@ fn statement_adv(
|
||||
}
|
||||
}
|
||||
let arg_types: Vec<_> = rargs.iter().map(|v| v.out(ginfo)).collect();
|
||||
if let Some(func) = linfo.fns.get(v) {
|
||||
if let Some(_out) = check_fn_args(
|
||||
&arg_types,
|
||||
&func
|
||||
.input_output_map
|
||||
.iter()
|
||||
.map(|v| (v.0.iter().map(|v| v.clone().to()).collect(), v.1.to_owned()))
|
||||
.collect(),
|
||||
ginfo,
|
||||
) {
|
||||
RStatementEnum::FunctionCall(func.clone(), rargs)
|
||||
} else {
|
||||
return Err(ToRunnableError::FunctionWrongArgs(arg_types, v.to_owned()));
|
||||
if let Some(funcs) = linfo.fns.get(v) {
|
||||
'find_func: {
|
||||
for func in funcs.iter().rev() {
|
||||
if let Some(_out) = check_fn_args(
|
||||
&arg_types,
|
||||
&func
|
||||
.input_output_map
|
||||
.iter()
|
||||
.map(|v| {
|
||||
(v.0.iter().map(|v| v.clone().to()).collect(), v.1.to_owned())
|
||||
})
|
||||
.collect(),
|
||||
ginfo,
|
||||
) {
|
||||
break 'find_func RStatementEnum::FunctionCall(
|
||||
Arc::clone(&func),
|
||||
rargs,
|
||||
);
|
||||
}
|
||||
}
|
||||
return Err(ToRunnableError::FunctionWrongArgs(
|
||||
v.to_owned(),
|
||||
funcs.iter().map(|v| Arc::clone(v)).collect(),
|
||||
arg_types,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
if let Some(builtin) = BuiltinFunction::get(v) {
|
||||
let arg_types = rargs.iter().map(|v| v.out(ginfo)).collect();
|
||||
if builtin.can_take(&arg_types, ginfo) {
|
||||
RStatementEnum::BuiltinFunction(builtin, rargs)
|
||||
RStatementEnum::BuiltinFunctionCall(builtin, rargs)
|
||||
} else {
|
||||
return Err(ToRunnableError::WrongInputsForBuiltinFunction(
|
||||
builtin,
|
||||
@@ -493,7 +505,7 @@ fn statement_adv(
|
||||
let lib = &ginfo.libs[*libid];
|
||||
let libfn = &lib.registered_fns[*fnid];
|
||||
if let Some(fn_out) = check_fn_args(&arg_types, &libfn.1, ginfo) {
|
||||
RStatementEnum::LibFunction(*libid, *fnid, rargs, fn_out.clone())
|
||||
RStatementEnum::LibFunctionCall(*libid, *fnid, rargs, fn_out.clone())
|
||||
} else {
|
||||
return Err(ToRunnableError::WrongArgsForLibFunction(
|
||||
v.to_owned(),
|
||||
@@ -507,18 +519,17 @@ fn statement_adv(
|
||||
}
|
||||
}
|
||||
SStatementEnum::FunctionDefinition(name, f) => {
|
||||
let f = Arc::new(function(f, ginfo, linfo.clone())?);
|
||||
if let Some(name) = name {
|
||||
// named function => add to global functions
|
||||
linfo
|
||||
.fns
|
||||
.insert(name.clone(), Arc::new(function(f, ginfo, linfo.clone())?));
|
||||
RStatementEnum::Value(VDataEnum::Tuple(vec![]).to())
|
||||
} else {
|
||||
// anonymous function => return as value
|
||||
RStatementEnum::Value(
|
||||
VDataEnum::Function(Arc::new(function(f, ginfo, linfo.clone())?)).to(),
|
||||
)
|
||||
let f = Arc::clone(&f);
|
||||
if let Some(vec) = linfo.fns.get_mut(name) {
|
||||
vec.push(f);
|
||||
} else {
|
||||
linfo.fns.insert(name.clone(), vec![f]);
|
||||
}
|
||||
}
|
||||
RStatementEnum::Value(VDataEnum::Function(f).to())
|
||||
}
|
||||
SStatementEnum::Block(b) => RStatementEnum::Block(block(&b, ginfo, linfo.clone())?),
|
||||
SStatementEnum::If(c, t, e) => RStatementEnum::If(
|
||||
|
||||
Reference in New Issue
Block a user