nac3core: default constant parameter support

This commit is contained in:
ychenfo 2021-11-11 22:43:09 +08:00
parent 439cef636f
commit c7b6b048fb
2 changed files with 95 additions and 7 deletions

View File

@ -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<ast::ArgData<()>>, Option<&ast::Expr>)> = args
.args
.iter()
.map(|x| -> Result<FuncArg, String> {
.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<FuncArg, String> {
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::<Result<Vec<_>, _>>()?
@ -1272,7 +1290,20 @@ impl TopLevelComposer {
}
let mut result = Vec::new();
for x in &args.args {
let mut arg_with_defualt: Vec<(&ast::Located<ast::ArgData<()>>, 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

View File

@ -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<SymbolValue, String> {
fn handle_constant(val: &Constant, loc: &Location) -> Result<SymbolValue, String> {
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::<Result<Vec<_>, _>>()?
)),
_ => 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::<Result<Vec<_>, _>>()?
)),
_ => unimplemented!("only constant default is supported now at {}", default.location),
}
}
}