Simplify get_builtins to only return top-level built-in declarations #362

Merged
sb10q merged 1 commits from enhance/infer-builtins-list into master 2023-12-08 17:29:55 +08:00
5 changed files with 62 additions and 82 deletions

View File

@ -22,7 +22,7 @@ use inkwell::{
IntPredicate IntPredicate
}; };
type BuiltinInfo = (Vec<(Arc<RwLock<TopLevelDef>>, Option<Stmt>)>, &'static [&'static str]); type BuiltinInfo = Vec<(Arc<RwLock<TopLevelDef>>, Option<Stmt>)>;
pub fn get_exn_constructor( pub fn get_exn_constructor(
name: &str, name: &str,
@ -1906,68 +1906,6 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let ast_list: Vec<Option<ast::Stmt<()>>> = let ast_list: Vec<Option<ast::Stmt<()>>> =
(0..top_level_def_list.len()).map(|_| None).collect(); (0..top_level_def_list.len()).map(|_| None).collect();
(
izip!(top_level_def_list, ast_list).collect_vec(), izip!(top_level_def_list, ast_list).collect_vec()
&[
"int32",
"int64",
"uint32",
"uint64",
"float",
"round",
"round64",
"np_round",
"range",
"str",
"bool",
"floor",
"floor64",
"np_floor",
"ceil",
"ceil64",
"np_ceil",
"len",
"min",
"max",
"abs",
"np_isnan",
"np_isinf",
"np_sin",
"np_cos",
"np_exp",
"np_exp2",
"np_log",
"np_log10",
"np_log2",
"np_fabs",
"np_sqrt",
"np_rint",
"np_tan",
"np_arcsin",
"np_arccos",
"np_arctan",
"np_sinh",
"np_cosh",
"np_tanh",
"np_arcsinh",
"np_arccosh",
"np_arctanh",
"np_expm1",
"np_cbrt",
"sp_spec_erf",
"sp_spec_erfc",
"sp_spec_gamma",
"sp_spec_gammaln",
"sp_spec_j0",
"sp_spec_j1",
"np_arctan2",
"np_copysign",
"np_fmax",
"np_fmin",
"np_ldexp",
"np_hypot",
"np_nextafter",
"Some",
],
)
} }

View File

@ -53,7 +53,7 @@ impl TopLevelComposer {
core_config: ComposerConfig, core_config: ComposerConfig,
) -> (Self, HashMap<StrRef, DefinitionId>, HashMap<StrRef, Type>) { ) -> (Self, HashMap<StrRef, DefinitionId>, HashMap<StrRef, Type>) {
let mut primitives = Self::make_primitives(); let mut primitives = Self::make_primitives();
let (mut definition_ast_list, builtin_name_list) = builtins::get_builtins(&mut primitives); let mut definition_ast_list = builtins::get_builtins(&mut primitives);
let primitives_ty = primitives.0; let primitives_ty = primitives.0;
let mut unifier = primitives.1; let mut unifier = primitives.1;
let mut keyword_list: HashSet<StrRef> = HashSet::from_iter(vec![ let mut keyword_list: HashSet<StrRef> = HashSet::from_iter(vec![
@ -83,12 +83,26 @@ impl TopLevelComposer {
let mut builtin_id: HashMap<StrRef, DefinitionId> = Default::default(); let mut builtin_id: HashMap<StrRef, DefinitionId> = Default::default();
let mut builtin_ty: HashMap<StrRef, Type> = Default::default(); let mut builtin_ty: HashMap<StrRef, Type> = Default::default();
for (id, name) in builtin_name_list.iter().rev().enumerate() { let builtin_name_list = definition_ast_list.iter()
.map(|def_ast| match *def_ast.0.read() {
TopLevelDef::Class { name, .. } => name.to_string(),
TopLevelDef::Function { simple_name, .. } => simple_name.to_string(),
})
.collect_vec();
for (id, name) in builtin_name_list.iter().enumerate() {
let name = (**name).into(); let name = (**name).into();
let id = definition_ast_list.len() - id - 1;
let def = definition_ast_list[id].0.read(); let def = definition_ast_list[id].0.read();
if let TopLevelDef::Function { simple_name, signature, .. } = &*def { if let TopLevelDef::Function { name: func_name, simple_name, signature, .. } = &*def {
assert!(name == *simple_name); assert_eq!(name, *simple_name, "Simple name of builtin function should match builtin name list");
// Do not add member functions into the list of builtin IDs;
// Here we assume that all builtin top-level functions have the same name and simple
// name, and all member functions have something prefixed to its name
if *func_name != simple_name.to_string() {
continue
}
builtin_ty.insert(name, *signature); builtin_ty.insert(name, *signature);
builtin_id.insert(name, DefinitionId(id)); builtin_id.insert(name, DefinitionId(id));
} else if let TopLevelDef::Class { name, constructor, object_id, .. } = &*def } else if let TopLevelDef::Class { name, constructor, object_id, .. } = &*def

View File

@ -127,7 +127,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
slice: &ast::Expr<T>, slice: &ast::Expr<T>,
unifier: &mut Unifier, unifier: &mut Unifier,
mut locked: HashMap<DefinitionId, Vec<Type>>| { mut locked: HashMap<DefinitionId, Vec<Type>>| {
if vec!["virtual".into(), "Generic".into(), "list".into(), "tuple".into()].contains(id) if vec!["virtual".into(), "Generic".into(), "list".into(), "tuple".into(), "Option".into()].contains(id)
{ {
return Err(format!("keywords cannot be class name (at {})", expr.location)); return Err(format!("keywords cannot be class name (at {})", expr.location));
} }

View File

@ -0,0 +1,26 @@
def run() -> int32:
# Numeric Primitives
b: bool = False
i32: int32 = 0
i64: int64 = int64(0)
u32: uint32 = uint32(0)
u64: uint64 = uint64(0)
f64: float = 0.0
# String
s: str = ""
# List
l_i32: list[int32] = []
l_f64: list[float] = []
l_str: list[str] = []
# Option
o_some: Option[int32] = Some(0)
o_none: Option[int32] = none
# Tuple
t_i32_i32: tuple[int32, int32] = (0, 0)
t_i32_f64: tuple[int32, float] = (0, 0.0)
return 0

View File

@ -74,8 +74,15 @@ fn handle_typevar_definition(
unifier: &mut Unifier, unifier: &mut Unifier,
primitives: &PrimitiveStore, primitives: &PrimitiveStore,
) -> Result<Type, String> { ) -> Result<Type, String> {
if let ExprKind::Call { func, args, .. } = &var.node { let ExprKind::Call { func, args, .. } = &var.node else {
if matches!(&func.node, ExprKind::Name { id, .. } if id == &"TypeVar".into()) { return Err(format!(
"expression {:?} cannot be handled as a generic parameter in global scope",
var
))
};
match &func.node {
ExprKind::Name { id, .. } if id == &"TypeVar".into() => {
let constraints = args let constraints = args
.iter() .iter()
.skip(1) .skip(1)
@ -94,15 +101,10 @@ fn handle_typevar_definition(
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
Ok(unifier.get_fresh_var_with_range(&constraints, None, None).0) Ok(unifier.get_fresh_var_with_range(&constraints, None, None).0)
} else {
Err(format!(
"expression {:?} cannot be handled as a TypeVar in global scope",
var
))
} }
} else {
Err(format!( _ => Err(format!(
"expression {:?} cannot be handled as a TypeVar in global scope", "expression {:?} cannot be handled as a generic parameter in global scope",
var var
)) ))
} }
@ -135,7 +137,7 @@ fn handle_assignment_pattern(
internal_resolver.add_module_global(*id, val); internal_resolver.add_module_global(*id, val);
Ok(()) Ok(())
} else { } else {
Err(format!("fails to evaluate this expression `{:?}` as a constant or TypeVar at {}", Err(format!("fails to evaluate this expression `{:?}` as a constant or generic parameter at {}",
targets[0].node, targets[0].node,
targets[0].location, targets[0].location,
)) ))