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, .. } => {
resolver.get_default_param_value(default).ok_or_else(
|| 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,
default.location
)

View File

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

View File

@ -4,8 +4,8 @@ use inkwell::{
OptimizationLevel,
};
use nac3core::typecheck::type_inferencer::PrimitiveStore;
use nac3parser::{ast::{ExprKind, StmtKind}, parser};
use std::env;
use nac3parser::{ast::{Expr, ExprKind, StmtKind}, parser};
use std::{borrow::Borrow, env};
use std::fs;
use std::{collections::HashMap, path::Path, sync::Arc, time::SystemTime};
@ -15,7 +15,7 @@ use nac3core::{
WorkerRegistry,
},
symbol_resolver::SymbolResolver,
toplevel::{composer::TopLevelComposer, TopLevelDef},
toplevel::{composer::TopLevelComposer, TopLevelDef, helper::parse_parameter_default_value},
typecheck::typedef::FunSignature,
};
@ -67,14 +67,57 @@ fn main() {
);
for stmt in parser_result.into_iter() {
// handle module globals
if let StmtKind::Assign { targets, value, .. } = &stmt.node {
if targets.len() == 1 {
if let ExprKind::Name { id, .. } = &targets[0].node {
internal_resolver.add_module_global(*id, value);
fn handle_assignment_pattern(
targets: &[Expr],
value: &Expr,
resolver: &(dyn SymbolResolver + Send + Sync),
internal_resolver: &ResolverInternal,
) -> Result<(), String> {
if targets.len() == 1 {
match &targets[0].node {
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 {
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))
}
}
} else {
unimplemented!("only single assign supported now")
}
if let Err(err) = handle_assignment_pattern(targets, value, resolver.as_ref(), internal_resolver.as_ref()) {
eprintln!("{}", err);
return;
}
continue;
}