forked from M-Labs/nac3
nac3artiq: support more builtin errors
This commit is contained in:
parent
8fd868a673
commit
e126fef012
@ -10,6 +10,7 @@ use inkwell::{
|
||||
targets::*,
|
||||
OptimizationLevel,
|
||||
};
|
||||
use nac3core::toplevel::builtins::get_exn_constructor;
|
||||
use nac3core::typecheck::typedef::{TypeEnum, Unifier};
|
||||
use nac3parser::{
|
||||
ast::{self, ExprKind, Stmt, StmtKind, StrRef},
|
||||
@ -82,8 +83,6 @@ struct Nac3 {
|
||||
time_fns: &'static (dyn TimeFns + Sync),
|
||||
primitive: PrimitiveStore,
|
||||
builtins: Vec<(StrRef, FunSignature, Arc<GenCall>)>,
|
||||
builtins_ty: HashMap<StrRef, Type>,
|
||||
builtins_def: HashMap<StrRef, DefinitionId>,
|
||||
pyid_to_def: Arc<RwLock<HashMap<u64, DefinitionId>>>,
|
||||
primitive_ids: PrimitivePythonId,
|
||||
working_directory: TempDir,
|
||||
@ -260,6 +259,34 @@ impl Nac3 {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_exceptions(
|
||||
composer: &mut TopLevelComposer,
|
||||
builtin_def: &mut HashMap<StrRef, DefinitionId>,
|
||||
builtin_ty: &mut HashMap<StrRef, Type>,
|
||||
error_names: &[&str]
|
||||
) -> Vec<Type> {
|
||||
let mut types = Vec::new();
|
||||
// note: this is only for builtin exceptions, i.e. the exception name is "0:{exn}"
|
||||
for name in error_names {
|
||||
let def_id = composer.definition_ast_list.len();
|
||||
let (exception_fn, exception_class, exception_cons, exception_type) = get_exn_constructor(
|
||||
name,
|
||||
// class id
|
||||
def_id,
|
||||
// constructor id
|
||||
def_id + 1,
|
||||
&mut composer.unifier,
|
||||
&composer.primitives_ty
|
||||
);
|
||||
composer.definition_ast_list.push((Arc::new(RwLock::new(exception_class)), None));
|
||||
composer.definition_ast_list.push((Arc::new(RwLock::new(exception_fn)), None));
|
||||
builtin_ty.insert((*name).into(), exception_cons);
|
||||
builtin_def.insert((*name).into(), DefinitionId(def_id));
|
||||
types.push(exception_type);
|
||||
}
|
||||
types
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl Nac3 {
|
||||
#[new]
|
||||
@ -321,68 +348,42 @@ impl Nac3 {
|
||||
}))),
|
||||
),
|
||||
];
|
||||
let (_, builtins_def, builtins_ty) = TopLevelComposer::new(
|
||||
builtins.clone(),
|
||||
ComposerConfig { kernel_ann: Some("Kernel"), kernel_invariant_ann: "KernelInvariant" },
|
||||
);
|
||||
|
||||
let builtins_mod = PyModule::import(py, "builtins").unwrap();
|
||||
let id_fn = builtins_mod.getattr("id").unwrap();
|
||||
let numpy_mod = PyModule::import(py, "numpy").unwrap();
|
||||
let typing_mod = PyModule::import(py, "typing").unwrap();
|
||||
let types_mod = PyModule::import(py, "types").unwrap();
|
||||
|
||||
let get_id = |x| id_fn.call1((x,)).unwrap().extract().unwrap();
|
||||
let get_attr_id = |obj: &PyModule, attr| id_fn.call1((obj.getattr(attr).unwrap(),))
|
||||
.unwrap().extract().unwrap();
|
||||
let primitive_ids = PrimitivePythonId {
|
||||
virtual_id: id_fn
|
||||
.call1((builtins_mod
|
||||
.getattr("globals")
|
||||
.unwrap()
|
||||
.call0()
|
||||
.unwrap()
|
||||
.get_item("virtual")
|
||||
.unwrap(),))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap(),
|
||||
virtual_id: get_id(
|
||||
builtins_mod
|
||||
.getattr("globals")
|
||||
.unwrap()
|
||||
.call0()
|
||||
.unwrap()
|
||||
.get_item("virtual")
|
||||
.unwrap(
|
||||
)),
|
||||
generic_alias: (
|
||||
id_fn
|
||||
.call1((typing_mod.getattr("_GenericAlias").unwrap(),))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap(),
|
||||
id_fn
|
||||
.call1((types_mod.getattr("GenericAlias").unwrap(),))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap(),
|
||||
get_attr_id(typing_mod, "_GenericAlias"),
|
||||
get_attr_id(types_mod, "GenericAlias"),
|
||||
),
|
||||
none: id_fn.call1((builtins_mod.getattr("None").unwrap(),)).unwrap().extract().unwrap(),
|
||||
typevar: id_fn
|
||||
.call1((typing_mod.getattr("TypeVar").unwrap(),))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap(),
|
||||
int: id_fn.call1((builtins_mod.getattr("int").unwrap(),)).unwrap().extract().unwrap(),
|
||||
int32: id_fn.call1((numpy_mod.getattr("int32").unwrap(),)).unwrap().extract().unwrap(),
|
||||
int64: id_fn.call1((numpy_mod.getattr("int64").unwrap(),)).unwrap().extract().unwrap(),
|
||||
uint32: id_fn.call1((numpy_mod.getattr("uint32").unwrap(),)).unwrap().extract().unwrap(),
|
||||
uint64: id_fn.call1((numpy_mod.getattr("uint64").unwrap(),)).unwrap().extract().unwrap(),
|
||||
bool: id_fn.call1((builtins_mod.getattr("bool").unwrap(),)).unwrap().extract().unwrap(),
|
||||
float: id_fn
|
||||
.call1((builtins_mod.getattr("float").unwrap(),))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap(),
|
||||
list: id_fn.call1((builtins_mod.getattr("list").unwrap(),)).unwrap().extract().unwrap(),
|
||||
tuple: id_fn
|
||||
.call1((builtins_mod.getattr("tuple").unwrap(),))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap(),
|
||||
exception: id_fn
|
||||
.call1((builtins_mod.getattr("Exception").unwrap(),))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap(),
|
||||
none: get_attr_id(builtins_mod, "None"),
|
||||
typevar: get_attr_id(typing_mod, "TypeVar"),
|
||||
int: get_attr_id(builtins_mod, "int"),
|
||||
int32: get_attr_id(numpy_mod, "int32"),
|
||||
int64: get_attr_id(numpy_mod, "int64"),
|
||||
uint32: get_attr_id(numpy_mod, "uint32"),
|
||||
uint64: get_attr_id(numpy_mod, "uint64"),
|
||||
bool: get_attr_id(builtins_mod, "bool"),
|
||||
float: get_attr_id(builtins_mod, "float"),
|
||||
list: get_attr_id(builtins_mod, "list"),
|
||||
tuple: get_attr_id(builtins_mod, "tuple"),
|
||||
exception: get_attr_id(builtins_mod, "Exception"),
|
||||
};
|
||||
|
||||
let working_directory = tempfile::Builder::new().prefix("nac3-").tempdir().unwrap();
|
||||
@ -393,8 +394,6 @@ impl Nac3 {
|
||||
time_fns,
|
||||
primitive,
|
||||
builtins,
|
||||
builtins_ty,
|
||||
builtins_def,
|
||||
primitive_ids,
|
||||
top_levels: Default::default(),
|
||||
pyid_to_def: Default::default(),
|
||||
@ -440,7 +439,7 @@ impl Nac3 {
|
||||
embedding_map: &PyAny,
|
||||
py: Python,
|
||||
) -> PyResult<()> {
|
||||
let (mut composer, _, _) = TopLevelComposer::new(
|
||||
let (mut composer, mut builtins_def, mut builtins_ty) = TopLevelComposer::new(
|
||||
self.builtins.clone(),
|
||||
ComposerConfig { kernel_ann: Some("Kernel"), kernel_invariant_ann: "KernelInvariant" },
|
||||
);
|
||||
@ -462,9 +461,16 @@ impl Nac3 {
|
||||
store_obj: store_obj.clone(),
|
||||
store_str,
|
||||
};
|
||||
let mut module_to_resolver_cache: HashMap<u64, _> = HashMap::new();
|
||||
|
||||
let pyid_to_type = Arc::new(RwLock::new(HashMap::<u64, Type>::new()));
|
||||
let exception_names = [
|
||||
"ValueError",
|
||||
"RuntimeError"
|
||||
];
|
||||
add_exceptions(&mut composer, &mut builtins_def, &mut builtins_ty, &exception_names);
|
||||
|
||||
let mut module_to_resolver_cache: HashMap<u64, _> = HashMap::new();
|
||||
|
||||
let global_value_ids = Arc::new(RwLock::new(HashSet::<u64>::new()));
|
||||
let mut rpc_ids = vec![];
|
||||
for (stmt, path, module) in self.top_levels.iter() {
|
||||
@ -494,8 +500,8 @@ impl Nac3 {
|
||||
name_to_pyid.insert(key.into(), val);
|
||||
}
|
||||
let resolver = Arc::new(Resolver(Arc::new(InnerResolver {
|
||||
id_to_type: self.builtins_ty.clone().into(),
|
||||
id_to_def: self.builtins_def.clone().into(),
|
||||
id_to_type: builtins_ty.clone().into(),
|
||||
id_to_def: builtins_def.clone().into(),
|
||||
pyid_to_def: self.pyid_to_def.clone(),
|
||||
pyid_to_type: pyid_to_type.clone(),
|
||||
primitive_ids: self.primitive_ids.clone(),
|
||||
@ -579,8 +585,8 @@ impl Nac3 {
|
||||
let mut synthesized =
|
||||
parse_program(&synthesized, "__nac3_synthesized_modinit__".to_string().into()).unwrap();
|
||||
let resolver = Arc::new(Resolver(Arc::new(InnerResolver {
|
||||
id_to_type: self.builtins_ty.clone().into(),
|
||||
id_to_def: self.builtins_def.clone().into(),
|
||||
id_to_type: builtins_ty.clone().into(),
|
||||
id_to_def: builtins_def.clone().into(),
|
||||
pyid_to_def: self.pyid_to_def.clone(),
|
||||
pyid_to_type: pyid_to_type.clone(),
|
||||
primitive_ids: self.primitive_ids.clone(),
|
||||
|
@ -9,7 +9,92 @@ use inkwell::{types::BasicType, FloatPredicate, IntPredicate};
|
||||
|
||||
type BuiltinInfo = (Vec<(Arc<RwLock<TopLevelDef>>, Option<Stmt>)>, &'static [&'static str]);
|
||||
|
||||
pub fn get_exn_constructor(
|
||||
name: &str,
|
||||
class_id: usize,
|
||||
cons_id: usize,
|
||||
unifier: &mut Unifier,
|
||||
primitives: &PrimitiveStore
|
||||
)-> (TopLevelDef, TopLevelDef, Type, Type) {
|
||||
let int32 = primitives.int32;
|
||||
let int64 = primitives.int64;
|
||||
let string = primitives.str;
|
||||
let exception_fields = vec![
|
||||
("__name__".into(), int32, true),
|
||||
("__file__".into(), string, true),
|
||||
("__line__".into(), int32, true),
|
||||
("__col__".into(), int32, true),
|
||||
("__func__".into(), string, true),
|
||||
("__message__".into(), string, true),
|
||||
("__param0__".into(), int64, true),
|
||||
("__param1__".into(), int64, true),
|
||||
("__param2__".into(), int64, true),
|
||||
];
|
||||
let exn_cons_args = vec![
|
||||
FuncArg {
|
||||
name: "msg".into(),
|
||||
ty: string,
|
||||
default_value: Some(SymbolValue::Str("".into())),
|
||||
},
|
||||
FuncArg { name: "param0".into(), ty: int64, default_value: Some(SymbolValue::I64(0)) },
|
||||
FuncArg { name: "param1".into(), ty: int64, default_value: Some(SymbolValue::I64(0)) },
|
||||
FuncArg { name: "param2".into(), ty: int64, default_value: Some(SymbolValue::I64(0)) },
|
||||
];
|
||||
let exn_type = unifier.add_ty(TypeEnum::TObj {
|
||||
obj_id: DefinitionId(class_id),
|
||||
fields: exception_fields.iter().map(|(a, b, c)| (*a, (*b, *c))).collect(),
|
||||
params: Default::default(),
|
||||
});
|
||||
let signature = unifier.add_ty(TypeEnum::TFunc(FunSignature {
|
||||
args: exn_cons_args,
|
||||
ret: exn_type,
|
||||
vars: Default::default(),
|
||||
}));
|
||||
let fun_def = TopLevelDef::Function {
|
||||
name: format!("{}.__init__", name),
|
||||
simple_name: "__init__".into(),
|
||||
signature,
|
||||
var_id: Default::default(),
|
||||
instance_to_symbol: Default::default(),
|
||||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(exn_constructor)))),
|
||||
loc: None,
|
||||
};
|
||||
let class_def = TopLevelDef::Class {
|
||||
name: name.into(),
|
||||
object_id: DefinitionId(class_id),
|
||||
type_vars: Default::default(),
|
||||
fields: exception_fields,
|
||||
methods: vec![("__init__".into(), signature, DefinitionId(cons_id))],
|
||||
ancestors: vec![
|
||||
TypeAnnotation::CustomClass { id: DefinitionId(class_id), params: Default::default() },
|
||||
TypeAnnotation::CustomClass { id: DefinitionId(7), params: Default::default() },
|
||||
],
|
||||
constructor: Some(signature),
|
||||
resolver: None,
|
||||
loc: None,
|
||||
};
|
||||
(fun_def, class_def, signature, exn_type)
|
||||
}
|
||||
|
||||
pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||
// please refer to the top_level_def_list below for the definition IDs
|
||||
let (div_by_zero_fun, div_by_zero_class, _, _) = get_exn_constructor(
|
||||
"DivisionByZeroError",
|
||||
12,
|
||||
10,
|
||||
&mut primitives.1,
|
||||
&primitives.0,
|
||||
);
|
||||
let (index_err_fun, index_err_class, _, _) = get_exn_constructor(
|
||||
"IndexError",
|
||||
13,
|
||||
11,
|
||||
&mut primitives.1,
|
||||
&primitives.0,
|
||||
);
|
||||
|
||||
let int32 = primitives.0.int32;
|
||||
let int64 = primitives.0.int64;
|
||||
let uint32 = primitives.0.uint32;
|
||||
@ -24,7 +109,6 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||
None,
|
||||
);
|
||||
let var_map: HashMap<_, _> = vec![(num_ty.1, num_ty.0)].into_iter().collect();
|
||||
|
||||
let exception_fields = vec![
|
||||
("__name__".into(), int32, true),
|
||||
("__file__".into(), string, true),
|
||||
@ -36,36 +120,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||
("__param1__".into(), int64, true),
|
||||
("__param2__".into(), int64, true),
|
||||
];
|
||||
let div_by_zero = primitives.1.add_ty(TypeEnum::TObj {
|
||||
obj_id: DefinitionId(12),
|
||||
fields: exception_fields.iter().map(|(a, b, c)| (*a, (*b, *c))).collect(),
|
||||
params: Default::default(),
|
||||
});
|
||||
let index_error = primitives.1.add_ty(TypeEnum::TObj {
|
||||
obj_id: DefinitionId(13),
|
||||
fields: exception_fields.iter().map(|(a, b, c)| (*a, (*b, *c))).collect(),
|
||||
params: Default::default(),
|
||||
});
|
||||
let exn_cons_args = vec![
|
||||
FuncArg {
|
||||
name: "msg".into(),
|
||||
ty: string,
|
||||
default_value: Some(SymbolValue::Str("".into())),
|
||||
},
|
||||
FuncArg { name: "param0".into(), ty: int64, default_value: Some(SymbolValue::I64(0)) },
|
||||
FuncArg { name: "param1".into(), ty: int64, default_value: Some(SymbolValue::I64(0)) },
|
||||
FuncArg { name: "param2".into(), ty: int64, default_value: Some(SymbolValue::I64(0)) },
|
||||
];
|
||||
let div_by_zero_signature = primitives.1.add_ty(TypeEnum::TFunc(FunSignature {
|
||||
args: exn_cons_args.clone(),
|
||||
ret: div_by_zero,
|
||||
vars: Default::default(),
|
||||
}));
|
||||
let index_error_signature = primitives.1.add_ty(TypeEnum::TFunc(FunSignature {
|
||||
args: exn_cons_args,
|
||||
ret: index_error,
|
||||
vars: Default::default(),
|
||||
}));
|
||||
|
||||
let top_level_def_list = vec![
|
||||
Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def(
|
||||
0,
|
||||
@ -120,7 +175,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||
name: "Exception".into(),
|
||||
object_id: DefinitionId(7),
|
||||
type_vars: Default::default(),
|
||||
fields: exception_fields.clone(),
|
||||
fields: exception_fields,
|
||||
methods: Default::default(),
|
||||
ancestors: vec![],
|
||||
constructor: None,
|
||||
@ -141,56 +196,10 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||
None,
|
||||
None,
|
||||
))),
|
||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||
name: "ZeroDivisionError.__init__".into(),
|
||||
simple_name: "__init__".into(),
|
||||
signature: div_by_zero_signature,
|
||||
var_id: Default::default(),
|
||||
instance_to_symbol: Default::default(),
|
||||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(exn_constructor)))),
|
||||
loc: None,
|
||||
})),
|
||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||
name: "IndexError.__init__".into(),
|
||||
simple_name: "__init__".into(),
|
||||
signature: index_error_signature,
|
||||
var_id: Default::default(),
|
||||
instance_to_symbol: Default::default(),
|
||||
instance_to_stmt: Default::default(),
|
||||
resolver: None,
|
||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(exn_constructor)))),
|
||||
loc: None,
|
||||
})),
|
||||
Arc::new(RwLock::new(TopLevelDef::Class {
|
||||
name: "ZeroDivisionError".into(),
|
||||
object_id: DefinitionId(12),
|
||||
type_vars: Default::default(),
|
||||
fields: exception_fields.clone(),
|
||||
methods: vec![("__init__".into(), div_by_zero_signature, DefinitionId(8))],
|
||||
ancestors: vec![
|
||||
TypeAnnotation::CustomClass { id: DefinitionId(10), params: Default::default() },
|
||||
TypeAnnotation::CustomClass { id: DefinitionId(7), params: Default::default() },
|
||||
],
|
||||
constructor: Some(div_by_zero_signature),
|
||||
resolver: None,
|
||||
loc: None,
|
||||
})),
|
||||
Arc::new(RwLock::new(TopLevelDef::Class {
|
||||
name: "IndexError".into(),
|
||||
object_id: DefinitionId(13),
|
||||
type_vars: Default::default(),
|
||||
fields: exception_fields,
|
||||
methods: vec![("__init__".into(), index_error_signature, DefinitionId(9))],
|
||||
ancestors: vec![
|
||||
TypeAnnotation::CustomClass { id: DefinitionId(11), params: Default::default() },
|
||||
TypeAnnotation::CustomClass { id: DefinitionId(7), params: Default::default() },
|
||||
],
|
||||
constructor: Some(index_error_signature),
|
||||
resolver: None,
|
||||
loc: None,
|
||||
})),
|
||||
Arc::new(RwLock::new(div_by_zero_fun)),
|
||||
Arc::new(RwLock::new(index_err_fun)),
|
||||
Arc::new(RwLock::new(div_by_zero_class)),
|
||||
Arc::new(RwLock::new(index_err_class)),
|
||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||
name: "int32".into(),
|
||||
simple_name: "int32".into(),
|
||||
|
@ -461,6 +461,9 @@ impl TopLevelComposer {
|
||||
};
|
||||
let mut errors = HashSet::new();
|
||||
for (class_def, class_ast) in def_list.iter().skip(self.builtin_num) {
|
||||
if class_ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = analyze(class_def, class_ast) {
|
||||
errors.insert(e);
|
||||
}
|
||||
@ -557,6 +560,9 @@ impl TopLevelComposer {
|
||||
// first, only push direct parent into the list
|
||||
let mut errors = HashSet::new();
|
||||
for (class_def, class_ast) in self.definition_ast_list.iter_mut().skip(self.builtin_num) {
|
||||
if class_ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = get_direct_parents(class_def, class_ast) {
|
||||
errors.insert(e);
|
||||
}
|
||||
@ -587,7 +593,10 @@ impl TopLevelComposer {
|
||||
);
|
||||
Ok(())
|
||||
};
|
||||
for (class_def, _) in self.definition_ast_list.iter().skip(self.builtin_num) {
|
||||
for (class_def, ast) in self.definition_ast_list.iter().skip(self.builtin_num) {
|
||||
if ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = get_all_ancestors(class_def) {
|
||||
errors.insert(e);
|
||||
}
|
||||
@ -598,6 +607,9 @@ impl TopLevelComposer {
|
||||
|
||||
// insert the ancestors to the def list
|
||||
for (class_def, class_ast) in self.definition_ast_list.iter_mut().skip(self.builtin_num) {
|
||||
if class_ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
let mut class_def = class_def.write();
|
||||
let (class_ancestors, class_id, class_type_vars) = {
|
||||
if let TopLevelDef::Class { ancestors, object_id, type_vars, .. } =
|
||||
@ -661,6 +673,9 @@ impl TopLevelComposer {
|
||||
|
||||
let mut errors = HashSet::new();
|
||||
for (class_def, class_ast) in def_ast_list.iter().skip(self.builtin_num) {
|
||||
if class_ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
if matches!(&*class_def.read(), TopLevelDef::Class { .. }) {
|
||||
if let Err(e) = Self::analyze_single_class_methods_fields(
|
||||
class_def.clone(),
|
||||
@ -687,7 +702,10 @@ impl TopLevelComposer {
|
||||
loop {
|
||||
let mut finished = true;
|
||||
|
||||
for (class_def, _) in def_ast_list.iter().skip(self.builtin_num) {
|
||||
for (class_def, class_ast) in def_ast_list.iter().skip(self.builtin_num) {
|
||||
if class_ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
let mut class_def = class_def.write();
|
||||
if let TopLevelDef::Class { ancestors, .. } = class_def.deref() {
|
||||
// if the length of the ancestor is equal to the current depth
|
||||
@ -950,6 +968,9 @@ impl TopLevelComposer {
|
||||
Ok(())
|
||||
};
|
||||
for (function_def, function_ast) in def_list.iter().skip(self.builtin_num) {
|
||||
if function_ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = analyze(function_def, function_ast) {
|
||||
errors.insert(e);
|
||||
}
|
||||
@ -1553,6 +1574,9 @@ impl TopLevelComposer {
|
||||
Ok(())
|
||||
};
|
||||
for (i, (def, ast)) in definition_ast_list.iter().enumerate().skip(self.builtin_num) {
|
||||
if ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = analyze(i, def, ast) {
|
||||
errors.insert(e);
|
||||
}
|
||||
@ -1849,6 +1873,9 @@ impl TopLevelComposer {
|
||||
Ok(())
|
||||
};
|
||||
for (id, (def, ast)) in self.definition_ast_list.iter().enumerate().skip(self.builtin_num) {
|
||||
if ast.is_none() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = analyze_2(id, def, ast) {
|
||||
errors.insert(e);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user