diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index bf9f1561..152094d2 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -1065,10 +1065,23 @@ impl TopLevelComposer { and names thould not be the same as the keywords" .into()); } - - args.args + + let mut arg_with_defualt: Vec<(&ast::Located>, Option<&ast::Expr>)> = args + .args .iter() - .map(|x| -> Result { + .rev() + .zip(args + .defaults + .iter() + .rev() + .map(|x| -> Option<&ast::Expr> { Some(x) }) + .chain(std::iter::repeat(None)) + ).collect_vec(); + arg_with_defualt.reverse(); + + arg_with_defualt + .iter() + .map(|(x, default)| -> Result { let annotation = x .node .annotation @@ -1120,7 +1133,12 @@ impl TopLevelComposer { Ok(FuncArg { name: x.node.arg, ty, - default_value: Default::default(), + default_value: default.map(|default| { + match Self::parse_parameter_default_value(default) { + Ok(res) => res, + Err(err) => panic!("{}", err), + } + }), }) }) .collect::, _>>()? @@ -1272,7 +1290,20 @@ impl TopLevelComposer { } let mut result = Vec::new(); - for x in &args.args { + + let mut arg_with_defualt: Vec<(&ast::Located>, Option<&ast::Expr>)> = args + .args + .iter() + .rev() + .zip(args + .defaults + .iter() + .rev() + .map(|x| -> Option<&ast::Expr> { Some(x) }) + .chain(std::iter::repeat(None)) + ).collect_vec(); + arg_with_defualt.reverse(); + for (x, default) in arg_with_defualt { let name = x.node.arg; if name != zelf { let type_ann = { @@ -1317,8 +1348,15 @@ impl TopLevelComposer { let dummy_func_arg = FuncArg { name, ty: unifier.get_fresh_var().0, - // TODO: default value? - default_value: None, + default_value: default.map(|default| { + if name == "self".into() { + panic!("`self` parameter cannot take default value at {}", x.location) + } + match Self::parse_parameter_default_value(default) { + Ok(res) => res, + Err(err) => panic!("{}", err), + } + }) }; // push the dummy type and the type annotation // into the list for later unification diff --git a/nac3core/src/toplevel/helper.rs b/nac3core/src/toplevel/helper.rs index 35da97c9..836a739d 100644 --- a/nac3core/src/toplevel/helper.rs +++ b/nac3core/src/toplevel/helper.rs @@ -1,3 +1,8 @@ +use std::convert::TryInto; + +use nac3parser::ast::{Constant, Location}; +use crate::symbol_resolver::SymbolValue; + use super::*; impl TopLevelDef { @@ -341,4 +346,49 @@ impl TopLevelComposer { } Ok(result) } + + pub fn parse_parameter_default_value(default: &ast::Expr) -> Result { + fn handle_constant(val: &Constant, loc: &Location) -> Result { + match val { + Constant::Int(v) => { + if let Ok(v) = v.try_into() { + Ok(SymbolValue::I32(v)) + } else { + Ok(SymbolValue::I64(v.try_into().unwrap())) + } + } + Constant::Float(v) => Ok(SymbolValue::Double(*v)), + Constant::Bool(v) => Ok(SymbolValue::Bool(*v)), + Constant::Tuple(tuple) => Ok(SymbolValue::Tuple( + tuple.iter().map(|x| handle_constant(x, loc)).collect::, _>>()? + )), + _ => unimplemented!("this constant is not supported now at {}", loc), + } + } + match &default.node { + ast::ExprKind::Constant { value, .. } => handle_constant(value, &default.location), + ast::ExprKind::Call { func, args, .. } if { + match &func.node { + ast::ExprKind::Name { id, .. } => *id == "int64".into(), + _ => false, + } + } => { + if args.len() == 1 { + match &args[0].node { + ast::ExprKind::Constant { value: Constant::Int(v), .. } => + Ok(SymbolValue::I64(v.try_into().unwrap())), + _ => panic!("only allow constant integer here at {}", default.location) + } + } else { + panic!("only allow constant integer here at {}", default.location) + } + } + ast::ExprKind::Tuple { elts, .. } => Ok(SymbolValue::Tuple(elts + .iter() + .map(|x| Self::parse_parameter_default_value(x)) + .collect::, _>>()? + )), + _ => unimplemented!("only constant default is supported now at {}", default.location), + } + } }