1
0
forked from M-Labs/nac3

[standalone] Add support for registering globals without type decl

This commit is contained in:
David Mak 2024-10-07 17:00:20 +08:00
parent 65a12d9ab3
commit 56c845aac4
2 changed files with 42 additions and 33 deletions
nac3core/src/toplevel
nac3standalone/src

View File

@ -382,6 +382,19 @@ impl TopLevelComposer {
)) ))
} }
ast::StmtKind::Assign { .. } => {
// Assignment statements can assign to (and therefore create) more than one
// variable, but this function only allows returning one set of symbol information.
// We want to avoid changing this to return a `Vec` of symbol info, as this would
// require `iter().next().unwrap()` on every variable created from a non-Assign
// statement.
//
// Make callers use `register_top_level_var` instead, as it provides more
// fine-grained control over which symbols to register, while also simplifying the
// usage of this function.
panic!("Registration of top-level Assign statements must use TopLevelComposer::register_top_level_var (at {})", ast.location);
}
ast::StmtKind::AnnAssign { target, annotation, .. } => { ast::StmtKind::AnnAssign { target, annotation, .. } => {
let ExprKind::Name { id: name, .. } = target.node else { let ExprKind::Name { id: name, .. } = target.node else {
return Err(format!( return Err(format!(

View File

@ -174,46 +174,49 @@ fn handle_typevar_definition(
fn handle_assignment_pattern( fn handle_assignment_pattern(
targets: &[Expr], targets: &[Expr],
value: &Expr, value: &Expr,
resolver: &(dyn SymbolResolver + Send + Sync), resolver: Arc<dyn SymbolResolver + Send + Sync>,
internal_resolver: &ResolverInternal, internal_resolver: &ResolverInternal,
def_list: &[Arc<RwLock<TopLevelDef>>], composer: &mut TopLevelComposer,
unifier: &mut Unifier,
primitives: &PrimitiveStore,
) -> Result<(), String> { ) -> Result<(), String> {
if targets.len() == 1 { if targets.len() == 1 {
match &targets[0].node { let target = &targets[0];
match &target.node {
ExprKind::Name { id, .. } => { ExprKind::Name { id, .. } => {
let def_list = composer.extract_def_list();
let unifier = &mut composer.unifier;
let primitives = &composer.primitives_ty;
if let Ok(var) = if let Ok(var) =
handle_typevar_definition(value, resolver, def_list, unifier, primitives) handle_typevar_definition(value, &*resolver, &def_list, unifier, primitives)
{ {
internal_resolver.add_id_type(*id, var); internal_resolver.add_id_type(*id, var);
Ok(()) Ok(())
} else if let Ok(val) = parse_parameter_default_value(value, resolver) { } else if let Ok(val) = parse_parameter_default_value(value, &*resolver) {
internal_resolver.add_module_global(*id, val); internal_resolver.add_module_global(*id, val);
let (name, def_id, _) = composer
.register_top_level_var(
*id,
None,
Some(resolver.clone()),
"__main__",
target.location,
)
.unwrap();
internal_resolver.add_id_def(name, def_id);
Ok(()) Ok(())
} else { } else {
Err(format!("fails to evaluate this expression `{:?}` as a constant or generic parameter at {}", Err(format!("fails to evaluate this expression `{:?}` as a constant or generic parameter at {}",
targets[0].node, target.node,
targets[0].location, target.location,
)) ))
} }
} }
ExprKind::List { elts, .. } | ExprKind::Tuple { elts, .. } => { ExprKind::List { elts, .. } | ExprKind::Tuple { elts, .. } => {
handle_assignment_pattern( handle_assignment_pattern(elts, value, resolver, internal_resolver, composer)?;
elts,
value,
resolver,
internal_resolver,
def_list,
unifier,
primitives,
)?;
Ok(()) Ok(())
} }
_ => Err(format!( _ => Err(format!("assignment to {target:?} is not supported at {}", target.location)),
"assignment to {:?} is not supported at {}",
targets[0], targets[0].location
)),
} }
} else { } else {
match &value.node { match &value.node {
@ -223,11 +226,9 @@ fn handle_assignment_pattern(
handle_assignment_pattern( handle_assignment_pattern(
std::slice::from_ref(tar), std::slice::from_ref(tar),
val, val,
resolver, resolver.clone(),
internal_resolver, internal_resolver,
def_list, composer,
unifier,
primitives,
)?; )?;
} }
Ok(()) Ok(())
@ -360,17 +361,12 @@ fn main() {
for stmt in parser_result { for stmt in parser_result {
match &stmt.node { match &stmt.node {
StmtKind::Assign { targets, value, .. } => { StmtKind::Assign { targets, value, .. } => {
let def_list = composer.extract_def_list();
let unifier = &mut composer.unifier;
let primitives = &composer.primitives_ty;
if let Err(err) = handle_assignment_pattern( if let Err(err) = handle_assignment_pattern(
targets, targets,
value, value,
resolver.as_ref(), resolver.clone(),
internal_resolver.as_ref(), internal_resolver.as_ref(),
&def_list, &mut composer,
unifier,
primitives,
) { ) {
panic!("{err}"); panic!("{err}");
} }