nac3standalone: better support for global assignment
This commit is contained in:
parent
ee7c1eb11d
commit
99c103b35b
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
if targets.len() == 1 {
|
fn handle_assignment_pattern(
|
||||||
if let ExprKind::Name { id, .. } = &targets[0].node {
|
targets: &[Expr],
|
||||||
internal_resolver.add_module_global(*id, value);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue