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 composer;
pub mod helper; pub mod helper;
mod type_annotation; pub mod type_annotation;
use composer::*; use composer::*;
use type_annotation::*; use type_annotation::*;
#[cfg(test)] #[cfg(test)]

View File

@ -3,8 +3,9 @@ use inkwell::{
targets::*, targets::*,
OptimizationLevel, OptimizationLevel,
}; };
use nac3core::typecheck::type_inferencer::PrimitiveStore; use nac3core::typecheck::{type_inferencer::PrimitiveStore, typedef::{Type, Unifier}};
use nac3parser::{ast::{Expr, ExprKind, StmtKind}, parser}; use nac3parser::{ast::{Expr, ExprKind, StmtKind}, parser};
use parking_lot::RwLock;
use std::{borrow::Borrow, 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 +16,11 @@ use nac3core::{
WorkerRegistry, WorkerRegistry,
}, },
symbol_resolver::SymbolResolver, 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, typecheck::typedef::FunSignature,
}; };
@ -68,25 +73,84 @@ fn main() {
for stmt in parser_result.into_iter() { for stmt in parser_result.into_iter() {
if let StmtKind::Assign { targets, value, .. } = &stmt.node { 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( fn handle_assignment_pattern(
targets: &[Expr], targets: &[Expr],
value: &Expr, value: &Expr,
resolver: &(dyn SymbolResolver + Send + Sync), resolver: &(dyn SymbolResolver + Send + Sync),
internal_resolver: &ResolverInternal, internal_resolver: &ResolverInternal,
def_list: &[Arc<RwLock<TopLevelDef>>],
unifier: &mut Unifier,
primitives: &PrimitiveStore,
) -> Result<(), String> { ) -> Result<(), String> {
if targets.len() == 1 { if targets.len() == 1 {
match &targets[0].node { match &targets[0].node {
ExprKind::Name { id, .. } => { ExprKind::Name { id, .. } => {
let val = parse_parameter_default_value(value.borrow(), resolver)?; if let Ok(var) = handle_typevar_definition(
internal_resolver.add_module_global(*id, val); value.borrow(),
Ok(()) 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::List { elts, .. }
| ExprKind::Tuple { 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(()) Ok(())
} }
_ => unreachable!("cannot be assigned") _ => Err(format!("assignment to {:?} is not supported at {}", targets[0], targets[0].location))
} }
} else { } else {
match &value.node { match &value.node {
@ -105,7 +169,10 @@ fn main() {
std::slice::from_ref(tar), std::slice::from_ref(tar),
val, val,
resolver, resolver,
internal_resolver internal_resolver,
def_list,
unifier,
primitives
)?; )?;
} }
Ok(()) 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); eprintln!("{}", err);
return; return;
} }