nac3standalone: better support for global assignment

This commit is contained in:
ychenfo 2021-11-23 00:25:37 +08:00
parent ee7c1eb11d
commit 99c103b35b
3 changed files with 58 additions and 18 deletions

View File

@ -399,7 +399,7 @@ pub fn parse_parameter_default_value(default: &ast::Expr, resolver: &(dyn Symbol
ast::ExprKind::Name { id, .. } => { ast::ExprKind::Name { id, .. } => {
resolver.get_default_param_value(default).ok_or_else( resolver.get_default_param_value(default).ok_or_else(
|| format!( || format!(
"this module global `{}` cannot be used as a default parameter at {} (should be primitive type or tuple)", "`{}` cannot be used as a default parameter at {} (not primitive type or tuple / not defined?)",
id, id,
default.location default.location
) )

View File

@ -3,7 +3,7 @@ use nac3core::{
codegen::CodeGenContext, codegen::CodeGenContext,
location::Location, location::Location,
symbol_resolver::{SymbolResolver, SymbolValue}, symbol_resolver::{SymbolResolver, SymbolValue},
toplevel::{DefinitionId, TopLevelDef, helper::parse_parameter_default_value}, toplevel::{DefinitionId, TopLevelDef},
typecheck::{ typecheck::{
type_inferencer::PrimitiveStore, type_inferencer::PrimitiveStore,
typedef::{Type, Unifier}, typedef::{Type, Unifier},
@ -17,7 +17,7 @@ pub struct ResolverInternal {
pub id_to_type: Mutex<HashMap<StrRef, Type>>, pub id_to_type: Mutex<HashMap<StrRef, Type>>,
pub id_to_def: Mutex<HashMap<StrRef, DefinitionId>>, pub id_to_def: Mutex<HashMap<StrRef, DefinitionId>>,
pub class_names: Mutex<HashMap<StrRef, Type>>, pub class_names: Mutex<HashMap<StrRef, Type>>,
pub module_globals: Mutex<HashMap<StrRef, ast::Expr>>, pub module_globals: Mutex<HashMap<StrRef, SymbolValue>>,
} }
impl ResolverInternal { impl ResolverInternal {
@ -29,8 +29,8 @@ impl ResolverInternal {
self.id_to_type.lock().insert(id, ty); self.id_to_type.lock().insert(id, ty);
} }
pub fn add_module_global(&self, id: StrRef, expr: &ast::Expr) { pub fn add_module_global(&self, id: StrRef, val: SymbolValue) {
self.module_globals.lock().insert(id, expr.clone()); self.module_globals.lock().insert(id, val);
} }
} }
@ -40,10 +40,7 @@ impl SymbolResolver for Resolver {
fn get_default_param_value(&self, expr: &ast::Expr) -> Option<SymbolValue> { fn get_default_param_value(&self, expr: &ast::Expr) -> Option<SymbolValue> {
match &expr.node { match &expr.node {
ast::ExprKind::Name { id, .. } => { ast::ExprKind::Name { id, .. } => {
let expr = self.0.module_globals.lock().get(id).cloned(); self.0.module_globals.lock().get(id).cloned()
expr.map(|x| {
parse_parameter_default_value(&x, self).unwrap()
})
} }
_ => unimplemented!("other type of expr not supported at {}", expr.location) _ => unimplemented!("other type of expr not supported at {}", expr.location)
} }

View File

@ -4,8 +4,8 @@ use inkwell::{
OptimizationLevel, OptimizationLevel,
}; };
use nac3core::typecheck::type_inferencer::PrimitiveStore; use nac3core::typecheck::type_inferencer::PrimitiveStore;
use nac3parser::{ast::{ExprKind, StmtKind}, parser}; use nac3parser::{ast::{Expr, ExprKind, StmtKind}, parser};
use std::env; use std::{borrow::Borrow, env};
use std::fs; use std::fs;
use std::{collections::HashMap, path::Path, sync::Arc, time::SystemTime}; use std::{collections::HashMap, path::Path, sync::Arc, time::SystemTime};
@ -15,7 +15,7 @@ use nac3core::{
WorkerRegistry, WorkerRegistry,
}, },
symbol_resolver::SymbolResolver, symbol_resolver::SymbolResolver,
toplevel::{composer::TopLevelComposer, TopLevelDef}, toplevel::{composer::TopLevelComposer, TopLevelDef, helper::parse_parameter_default_value},
typecheck::typedef::FunSignature, typecheck::typedef::FunSignature,
}; };
@ -67,14 +67,57 @@ fn main() {
); );
for stmt in parser_result.into_iter() { for stmt in parser_result.into_iter() {
// handle module globals
if let StmtKind::Assign { targets, value, .. } = &stmt.node { if let StmtKind::Assign { targets, value, .. } = &stmt.node {
fn handle_assignment_pattern(
targets: &[Expr],
value: &Expr,
resolver: &(dyn SymbolResolver + Send + Sync),
internal_resolver: &ResolverInternal,
) -> Result<(), String> {
if targets.len() == 1 { if targets.len() == 1 {
if let ExprKind::Name { id, .. } = &targets[0].node { match &targets[0].node {
internal_resolver.add_module_global(*id, value); ExprKind::Name { id, .. } => {
let val = parse_parameter_default_value(value.borrow(), resolver)?;
internal_resolver.add_module_global(*id, val);
Ok(())
}
ExprKind::List { elts, .. }
| ExprKind::Tuple { elts, .. } => {
handle_assignment_pattern(elts, value, resolver, internal_resolver)?;
Ok(())
}
_ => unreachable!("cannot be assigned")
} }
} else { } else {
unimplemented!("only single assign supported now") match &value.node {
ExprKind::List { elts, .. }
| ExprKind::Tuple { elts, .. } => {
if elts.len() != targets.len() {
Err(format!(
"number of elements to unpack does not match (expect {}, found {}) at {}",
targets.len(),
elts.len(),
value.location
))
} else {
for (tar, val) in targets.iter().zip(elts) {
handle_assignment_pattern(
std::slice::from_ref(tar),
val,
resolver,
internal_resolver
)?;
}
Ok(())
}
},
_ => Err(format!("unpack of this expression is not supported at {}", value.location))
}
}
}
if let Err(err) = handle_assignment_pattern(targets, value, resolver.as_ref(), internal_resolver.as_ref()) {
eprintln!("{}", err);
return;
} }
continue; continue;
} }