forked from M-Labs/nac3
core/codegen/expr: Implement vararg handling in gen_call
This commit is contained in:
parent
72295ccaa5
commit
f270019c24
|
@ -766,6 +766,9 @@ pub fn gen_call<'ctx, G: CodeGenerator>(
|
||||||
let param_vals;
|
let param_vals;
|
||||||
let is_extern;
|
let is_extern;
|
||||||
|
|
||||||
|
// Ensure that the function object only contains up to 1 vararg parameter
|
||||||
|
debug_assert!(fun.0.args.iter().filter(|arg| arg.is_vararg).count() <= 1);
|
||||||
|
|
||||||
let symbol = {
|
let symbol = {
|
||||||
// make sure this lock guard is dropped at the end of this scope...
|
// make sure this lock guard is dropped at the end of this scope...
|
||||||
let def = definition.read();
|
let def = definition.read();
|
||||||
|
@ -782,18 +785,46 @@ pub fn gen_call<'ctx, G: CodeGenerator>(
|
||||||
is_extern = instance_to_stmt.is_empty();
|
is_extern = instance_to_stmt.is_empty();
|
||||||
let old_key = ctx.get_subst_key(obj.as_ref().map(|a| a.0), fun.0, None);
|
let old_key = ctx.get_subst_key(obj.as_ref().map(|a| a.0), fun.0, None);
|
||||||
let mut keys = fun.0.args.clone();
|
let mut keys = fun.0.args.clone();
|
||||||
let mut mapping = HashMap::new();
|
let mut mapping = HashMap::<_, Vec<ValueEnum>>::new();
|
||||||
|
|
||||||
for (key, value) in params {
|
for (key, value) in params {
|
||||||
mapping.insert(key.unwrap_or_else(|| keys.remove(0).name), value);
|
// Find the matching argument
|
||||||
|
let matching_param = fun
|
||||||
|
.0
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.find_or_last(|p| key.is_some_and(|k| k == p.name))
|
||||||
|
.unwrap();
|
||||||
|
if matching_param.is_vararg {
|
||||||
|
if key.is_none() && !keys.is_empty() {
|
||||||
|
keys.remove(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(param) = mapping.get_mut(&matching_param.name) {
|
||||||
|
param.push(value);
|
||||||
|
} else {
|
||||||
|
mapping.insert(key.unwrap_or(matching_param.name), vec![value]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mapping.insert(key.unwrap_or_else(|| keys.remove(0).name), vec![value]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// default value handling
|
// default value handling
|
||||||
for k in keys {
|
for k in keys {
|
||||||
if mapping.contains_key(&k.name) {
|
if mapping.contains_key(&k.name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping.insert(
|
mapping.insert(
|
||||||
k.name,
|
k.name,
|
||||||
ctx.gen_symbol_val(generator, &k.default_value.unwrap(), k.ty).into(),
|
if k.is_vararg {
|
||||||
|
Vec::default()
|
||||||
|
} else {
|
||||||
|
vec![ctx
|
||||||
|
.gen_symbol_val(generator, &k.default_value.unwrap(), k.ty)
|
||||||
|
.into()]
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// reorder the parameters
|
// reorder the parameters
|
||||||
|
@ -804,13 +835,15 @@ pub fn gen_call<'ctx, G: CodeGenerator>(
|
||||||
.map(|arg| (mapping.remove(&arg.name).unwrap(), arg.ty))
|
.map(|arg| (mapping.remove(&arg.name).unwrap(), arg.ty))
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
if let Some(obj) = &obj {
|
if let Some(obj) = &obj {
|
||||||
real_params.insert(0, (obj.1.clone(), obj.0));
|
real_params.insert(0, (vec![obj.1.clone()], obj.0));
|
||||||
}
|
}
|
||||||
let static_params = real_params
|
let static_params = real_params
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, (v, _))| {
|
.filter_map(|(i, (v, _))| {
|
||||||
if let ValueEnum::Static(s) = v {
|
if v.len() != 1 {
|
||||||
|
None
|
||||||
|
} else if let ValueEnum::Static(s) = &v[0] {
|
||||||
Some((i, s.clone()))
|
Some((i, s.clone()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -840,8 +873,13 @@ pub fn gen_call<'ctx, G: CodeGenerator>(
|
||||||
};
|
};
|
||||||
param_vals = real_params
|
param_vals = real_params
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(p, t)| p.to_basic_value_enum(ctx, generator, t))
|
.map(|(ps, t)| {
|
||||||
.collect::<Result<Vec<_>, String>>()?;
|
ps.into_iter().map(|p| p.to_basic_value_enum(ctx, generator, t)).collect()
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<Vec<_>>, _>>()?
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
instance_to_symbol.get(&key).cloned().ok_or_else(String::new)
|
instance_to_symbol.get(&key).cloned().ok_or_else(String::new)
|
||||||
}
|
}
|
||||||
TopLevelDef::Class { .. } => {
|
TopLevelDef::Class { .. } => {
|
||||||
|
|
Loading…
Reference in New Issue