nac3standalone: iteration over multiple typevar assignment in the same line

This commit is contained in:
ychenfo 2021-11-24 18:24:16 +08:00
parent 34105b4f0e
commit 49240a80ad
2 changed files with 89 additions and 10 deletions

View File

@ -24,7 +24,7 @@ pub struct DefinitionId(pub usize);
pub mod composer;
pub mod helper;
mod type_annotation;
pub mod type_annotation;
use composer::*;
use type_annotation::*;
#[cfg(test)]

View File

@ -3,8 +3,9 @@ use inkwell::{
targets::*,
OptimizationLevel,
};
use nac3core::typecheck::type_inferencer::PrimitiveStore;
use nac3core::typecheck::{type_inferencer::PrimitiveStore, typedef::{Type, Unifier}};
use nac3parser::{ast::{Expr, ExprKind, StmtKind}, parser};
use parking_lot::RwLock;
use std::{borrow::Borrow, env};
use std::fs;
use std::{collections::HashMap, path::Path, sync::Arc, time::SystemTime};
@ -15,7 +16,11 @@ use nac3core::{
WorkerRegistry,
},
symbol_resolver::SymbolResolver,
toplevel::{composer::TopLevelComposer, TopLevelDef, helper::parse_parameter_default_value},
toplevel::{
composer::TopLevelComposer,
TopLevelDef, helper::parse_parameter_default_value,
type_annotation::*,
},
typecheck::typedef::FunSignature,
};
@ -68,25 +73,84 @@ fn main() {
for stmt in parser_result.into_iter() {
if let StmtKind::Assign { targets, value, .. } = &stmt.node {
fn handle_typevar_definition(
var: &Expr,
resolver: &(dyn SymbolResolver + Send + Sync),
def_list: &[Arc<RwLock<TopLevelDef>>],
unifier: &mut Unifier,
primitives: &PrimitiveStore,
) -> Result<Type, String> {
if let ExprKind::Call { func, args, .. } = &var.node {
if matches!(&func.node, ExprKind::Name { id, .. } if id == &"TypeVar".into()) {
let constraints = args
.iter()
.skip(1)
.map(|x| -> Result<Type, String> {
let ty = parse_ast_to_type_annotation_kinds(
resolver,
def_list,
unifier,
primitives,
x,
Default::default(),
)?;
get_type_from_type_annotation_kinds(def_list, unifier, primitives, &ty)
})
.collect::<Result<Vec<_>, _>>()?;
Ok(unifier.get_fresh_var_with_range(&constraints).0)
} else {
Err(format!("expression {:?} cannot be handled as a TypeVar in global scope", var))
}
} else {
Err(format!("expression {:?} cannot be handled as a TypeVar in global scope", var))
}
}
fn handle_assignment_pattern(
targets: &[Expr],
value: &Expr,
resolver: &(dyn SymbolResolver + Send + Sync),
internal_resolver: &ResolverInternal,
def_list: &[Arc<RwLock<TopLevelDef>>],
unifier: &mut Unifier,
primitives: &PrimitiveStore,
) -> 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(())
if let Ok(var) = handle_typevar_definition(
value.borrow(),
resolver,
def_list,
unifier,
primitives,
) {
internal_resolver.add_id_type(*id, var);
Ok(())
} else if let Ok(val) = parse_parameter_default_value(value.borrow(), resolver) {
internal_resolver.add_module_global(*id, val);
Ok(())
} else {
Err(format!("fails to evaluate this expression `{:?}` as a constant or TypeVar at {}",
targets[0].node,
targets[0].location,
))
}
}
ExprKind::List { elts, .. }
| ExprKind::Tuple { elts, .. } => {
handle_assignment_pattern(elts, value, resolver, internal_resolver)?;
handle_assignment_pattern(
elts,
value,
resolver,
internal_resolver,
def_list,
unifier,
primitives
)?;
Ok(())
}
_ => unreachable!("cannot be assigned")
_ => Err(format!("assignment to {:?} is not supported at {}", targets[0], targets[0].location))
}
} else {
match &value.node {
@ -105,7 +169,10 @@ fn main() {
std::slice::from_ref(tar),
val,
resolver,
internal_resolver
internal_resolver,
def_list,
unifier,
primitives
)?;
}
Ok(())
@ -115,7 +182,19 @@ fn main() {
}
}
}
if let Err(err) = handle_assignment_pattern(targets, value, resolver.as_ref(), internal_resolver.as_ref()) {
let def_list = composer.extract_def_list();
let unifier = &mut composer.unifier;
let primitives = &composer.primitives_ty;
if let Err(err) = handle_assignment_pattern(
targets,
value,
resolver.as_ref(),
internal_resolver.as_ref(),
&def_list,
unifier,
primitives,
) {
eprintln!("{}", err);
return;
}