default paramter support simple global modules
This commit is contained in:
parent
e75ec35687
commit
6397e42e74
|
@ -2,7 +2,7 @@ use inkwell::{types::BasicType, values::BasicValueEnum, AddressSpace};
|
||||||
use nac3core::{
|
use nac3core::{
|
||||||
codegen::CodeGenContext,
|
codegen::CodeGenContext,
|
||||||
location::Location,
|
location::Location,
|
||||||
symbol_resolver::SymbolResolver,
|
symbol_resolver::{SymbolResolver, SymbolValue},
|
||||||
toplevel::{DefinitionId, TopLevelDef},
|
toplevel::{DefinitionId, TopLevelDef},
|
||||||
typecheck::{
|
typecheck::{
|
||||||
type_inferencer::PrimitiveStore,
|
type_inferencer::PrimitiveStore,
|
||||||
|
@ -14,7 +14,7 @@ use pyo3::{
|
||||||
types::{PyList, PyModule, PyTuple},
|
types::{PyList, PyModule, PyTuple},
|
||||||
PyAny, PyObject, PyResult, Python,
|
PyAny, PyObject, PyResult, Python,
|
||||||
};
|
};
|
||||||
use nac3parser::ast::StrRef;
|
use nac3parser::ast::{self, StrRef};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
|
@ -399,9 +399,86 @@ impl Resolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_default_param_obj_value(&self, obj: &PyAny, helper: &PythonHelper) -> PyResult<Result<SymbolValue, String>> {
|
||||||
|
let ty_id: u64 = helper
|
||||||
|
.id_fn
|
||||||
|
.call1((helper.type_fn.call1((obj,))?,))?
|
||||||
|
.extract()?;
|
||||||
|
Ok(
|
||||||
|
if ty_id == self.primitive_ids.int || ty_id == self.primitive_ids.int32 {
|
||||||
|
let val: i32 = obj.extract()?;
|
||||||
|
Ok(SymbolValue::I32(val))
|
||||||
|
} else if ty_id == self.primitive_ids.int64 {
|
||||||
|
let val: i64 = obj.extract()?;
|
||||||
|
Ok(SymbolValue::I64(val))
|
||||||
|
} else if ty_id == self.primitive_ids.bool {
|
||||||
|
let val: bool = obj.extract()?;
|
||||||
|
Ok(SymbolValue::Bool(val))
|
||||||
|
} else if ty_id == self.primitive_ids.float {
|
||||||
|
let val: f64 = obj.extract()?;
|
||||||
|
Ok(SymbolValue::Double(val))
|
||||||
|
} else if ty_id == self.primitive_ids.tuple {
|
||||||
|
let elements: &PyTuple = obj.cast_as()?;
|
||||||
|
let elements: Result<Result<Vec<_>, String>, _> = elements
|
||||||
|
.iter()
|
||||||
|
.map(|elem| {
|
||||||
|
self.get_default_param_obj_value(
|
||||||
|
elem,
|
||||||
|
helper
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let elements = match elements? {
|
||||||
|
Ok(el) => el,
|
||||||
|
Err(err) => return Ok(Err(err))
|
||||||
|
};
|
||||||
|
Ok(SymbolValue::Tuple(elements))
|
||||||
|
} else {
|
||||||
|
Err("only primitives values and tuple can be default parameter value".into())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolResolver for Resolver {
|
impl SymbolResolver for Resolver {
|
||||||
|
fn get_default_param_value(
|
||||||
|
&self,
|
||||||
|
expr: &ast::Expr
|
||||||
|
) -> Option<SymbolValue> {
|
||||||
|
match &expr.node {
|
||||||
|
ast::ExprKind::Name { id, .. } => {
|
||||||
|
Python::with_gil(
|
||||||
|
|py| -> PyResult<Option<SymbolValue>> {
|
||||||
|
let obj: &PyAny = self.module.extract(py)?;
|
||||||
|
let members: &PyList = PyModule::import(py, "inspect")?
|
||||||
|
.getattr("getmembers")?
|
||||||
|
.call1((obj,))?
|
||||||
|
.cast_as()?;
|
||||||
|
let mut sym_value = None;
|
||||||
|
for member in members.iter() {
|
||||||
|
let key: &str = member.get_item(0)?.extract()?;
|
||||||
|
let val = member.get_item(1)?;
|
||||||
|
if key == id.to_string() {
|
||||||
|
let builtins = PyModule::import(py, "builtins")?;
|
||||||
|
let helper = PythonHelper {
|
||||||
|
id_fn: builtins.getattr("id").unwrap(),
|
||||||
|
len_fn: builtins.getattr("len").unwrap(),
|
||||||
|
type_fn: builtins.getattr("type").unwrap(),
|
||||||
|
};
|
||||||
|
sym_value = Some(self.get_default_param_obj_value(val, &helper).unwrap().unwrap());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(sym_value)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
_ => unimplemented!("other type of expr not supported at {}", expr.location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_symbol_type(
|
fn get_symbol_type(
|
||||||
&self,
|
&self,
|
||||||
unifier: &mut Unifier,
|
unifier: &mut Unifier,
|
||||||
|
|
|
@ -37,6 +37,10 @@ impl Resolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolResolver for Resolver {
|
impl SymbolResolver for Resolver {
|
||||||
|
fn get_default_param_value(&self, _: &nac3parser::ast::Expr) -> Option<crate::symbol_resolver::SymbolValue> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_symbol_type(
|
fn get_symbol_type(
|
||||||
&self,
|
&self,
|
||||||
_: &mut Unifier,
|
_: &mut Unifier,
|
||||||
|
|
|
@ -44,6 +44,7 @@ pub trait SymbolResolver {
|
||||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||||
) -> Option<BasicValueEnum<'ctx>>;
|
) -> Option<BasicValueEnum<'ctx>>;
|
||||||
fn get_symbol_location(&self, str: StrRef) -> Option<Location>;
|
fn get_symbol_location(&self, str: StrRef) -> Option<Location>;
|
||||||
|
fn get_default_param_value(&self, expr: &nac3parser::ast::Expr) -> Option<SymbolValue>;
|
||||||
// handle function call etc.
|
// handle function call etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1136,7 +1136,7 @@ impl TopLevelComposer {
|
||||||
default_value: match default {
|
default_value: match default {
|
||||||
None => None,
|
None => None,
|
||||||
Some(default) =>
|
Some(default) =>
|
||||||
Some(Self::parse_parameter_default_value(default)?)
|
Some(Self::parse_parameter_default_value(default, resolver)?)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1353,7 +1353,7 @@ impl TopLevelComposer {
|
||||||
if name == "self".into() {
|
if name == "self".into() {
|
||||||
return Err(format!("`self` parameter cannot take default value at {}", x.location));
|
return Err(format!("`self` parameter cannot take default value at {}", x.location));
|
||||||
}
|
}
|
||||||
Some(Self::parse_parameter_default_value(default)?)
|
Some(Self::parse_parameter_default_value(default, class_resolver)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -347,51 +347,64 @@ impl TopLevelComposer {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_parameter_default_value(default: &ast::Expr) -> Result<SymbolValue, String> {
|
pub fn parse_parameter_default_value(default: &ast::Expr, resolver: &(dyn SymbolResolver + Send + Sync)) -> Result<SymbolValue, String> {
|
||||||
fn handle_constant(val: &Constant, loc: &Location) -> Result<SymbolValue, String> {
|
parse_parameter_default_value(default, resolver)
|
||||||
match val {
|
}
|
||||||
Constant::Int(v) => {
|
}
|
||||||
if let Ok(v) = v.try_into() {
|
|
||||||
Ok(SymbolValue::I32(v))
|
pub fn parse_parameter_default_value(default: &ast::Expr, resolver: &(dyn SymbolResolver + Send + Sync)) -> Result<SymbolValue, String> {
|
||||||
} else {
|
fn handle_constant(val: &Constant, loc: &Location) -> Result<SymbolValue, String> {
|
||||||
Err(format!(
|
match val {
|
||||||
"int64 default parameter should be specified explicitly by `int64()` at {}",
|
Constant::Int(v) => {
|
||||||
loc
|
if let Ok(v) = v.try_into() {
|
||||||
))
|
Ok(SymbolValue::I32(v))
|
||||||
}
|
} else {
|
||||||
}
|
Err(format!(
|
||||||
Constant::Float(v) => Ok(SymbolValue::Double(*v)),
|
"int64 default parameter should be specified explicitly by `int64()` at {}",
|
||||||
Constant::Bool(v) => Ok(SymbolValue::Bool(*v)),
|
loc
|
||||||
Constant::Tuple(tuple) => Ok(SymbolValue::Tuple(
|
))
|
||||||
tuple.iter().map(|x| handle_constant(x, loc)).collect::<Result<Vec<_>, _>>()?
|
}
|
||||||
)),
|
}
|
||||||
_ => unimplemented!("this constant is not supported at {}", loc),
|
Constant::Float(v) => Ok(SymbolValue::Double(*v)),
|
||||||
}
|
Constant::Bool(v) => Ok(SymbolValue::Bool(*v)),
|
||||||
}
|
Constant::Tuple(tuple) => Ok(SymbolValue::Tuple(
|
||||||
match &default.node {
|
tuple.iter().map(|x| handle_constant(x, loc)).collect::<Result<Vec<_>, _>>()?
|
||||||
ast::ExprKind::Constant { value, .. } => handle_constant(value, &default.location),
|
)),
|
||||||
ast::ExprKind::Call { func, args, .. } if {
|
_ => unimplemented!("this constant is not supported at {}", loc),
|
||||||
match &func.node {
|
}
|
||||||
ast::ExprKind::Name { id, .. } => *id == "int64".into(),
|
}
|
||||||
_ => false,
|
match &default.node {
|
||||||
}
|
ast::ExprKind::Constant { value, .. } => handle_constant(value, &default.location),
|
||||||
} => {
|
ast::ExprKind::Call { func, args, .. } if {
|
||||||
if args.len() == 1 {
|
match &func.node {
|
||||||
match &args[0].node {
|
ast::ExprKind::Name { id, .. } => *id == "int64".into(),
|
||||||
ast::ExprKind::Constant { value: Constant::Int(v), .. } =>
|
_ => false,
|
||||||
Ok(SymbolValue::I64(v.try_into().unwrap())),
|
}
|
||||||
_ => Err(format!("only allow constant integer here at {}", default.location))
|
} => {
|
||||||
}
|
if args.len() == 1 {
|
||||||
} else {
|
match &args[0].node {
|
||||||
Err(format!("only allow constant integer here at {}", default.location))
|
ast::ExprKind::Constant { value: Constant::Int(v), .. } =>
|
||||||
}
|
Ok(SymbolValue::I64(v.try_into().unwrap())),
|
||||||
}
|
_ => Err(format!("only allow constant integer here at {}", default.location))
|
||||||
ast::ExprKind::Tuple { elts, .. } => Ok(SymbolValue::Tuple(elts
|
}
|
||||||
.iter()
|
} else {
|
||||||
.map(|x| Self::parse_parameter_default_value(x))
|
Err(format!("only allow constant integer here at {}", default.location))
|
||||||
.collect::<Result<Vec<_>, _>>()?
|
}
|
||||||
)),
|
}
|
||||||
_ => unimplemented!("only constant default is supported now at {}", default.location),
|
ast::ExprKind::Tuple { elts, .. } => Ok(SymbolValue::Tuple(elts
|
||||||
}
|
.iter()
|
||||||
|
.map(|x| parse_parameter_default_value(x, resolver))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?
|
||||||
|
)),
|
||||||
|
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)",
|
||||||
|
id,
|
||||||
|
default.location
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unimplemented!("only constant default is supported now at {}", default.location),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ use inkwell::values::BasicValueEnum;
|
||||||
pub struct DefinitionId(pub usize);
|
pub struct DefinitionId(pub usize);
|
||||||
|
|
||||||
pub mod composer;
|
pub mod composer;
|
||||||
mod helper;
|
pub mod helper;
|
||||||
mod type_annotation;
|
mod type_annotation;
|
||||||
use composer::*;
|
use composer::*;
|
||||||
use type_annotation::*;
|
use type_annotation::*;
|
||||||
|
|
|
@ -35,6 +35,10 @@ impl ResolverInternal {
|
||||||
struct Resolver(Arc<ResolverInternal>);
|
struct Resolver(Arc<ResolverInternal>);
|
||||||
|
|
||||||
impl SymbolResolver for Resolver {
|
impl SymbolResolver for Resolver {
|
||||||
|
fn get_default_param_value(&self, _: &nac3parser::ast::Expr) -> Option<crate::symbol_resolver::SymbolValue> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_symbol_type(
|
fn get_symbol_type(
|
||||||
&self,
|
&self,
|
||||||
_: &mut Unifier,
|
_: &mut Unifier,
|
||||||
|
|
|
@ -19,6 +19,10 @@ struct Resolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolResolver for Resolver {
|
impl SymbolResolver for Resolver {
|
||||||
|
fn get_default_param_value(&self, _: &nac3parser::ast::Expr) -> Option<crate::symbol_resolver::SymbolValue> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
fn get_symbol_type(
|
fn get_symbol_type(
|
||||||
&self,
|
&self,
|
||||||
_: &mut Unifier,
|
_: &mut Unifier,
|
||||||
|
|
|
@ -2,21 +2,22 @@ use inkwell::values::BasicValueEnum;
|
||||||
use nac3core::{
|
use nac3core::{
|
||||||
codegen::CodeGenContext,
|
codegen::CodeGenContext,
|
||||||
location::Location,
|
location::Location,
|
||||||
symbol_resolver::SymbolResolver,
|
symbol_resolver::{SymbolResolver, SymbolValue},
|
||||||
toplevel::{DefinitionId, TopLevelDef},
|
toplevel::{DefinitionId, TopLevelDef, helper::parse_parameter_default_value},
|
||||||
typecheck::{
|
typecheck::{
|
||||||
type_inferencer::PrimitiveStore,
|
type_inferencer::PrimitiveStore,
|
||||||
typedef::{Type, Unifier},
|
typedef::{Type, Unifier},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use nac3parser::ast::StrRef;
|
use nac3parser::ast::{self, StrRef};
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
pub struct ResolverInternal {
|
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>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResolverInternal {
|
impl ResolverInternal {
|
||||||
|
@ -27,11 +28,27 @@ impl ResolverInternal {
|
||||||
pub fn add_id_type(&self, id: StrRef, ty: Type) {
|
pub fn add_id_type(&self, id: StrRef, ty: Type) {
|
||||||
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) {
|
||||||
|
self.module_globals.lock().insert(id, expr.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Resolver(pub Arc<ResolverInternal>);
|
pub struct Resolver(pub Arc<ResolverInternal>);
|
||||||
|
|
||||||
impl SymbolResolver for Resolver {
|
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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => unimplemented!("other type of expr not supported at {}", expr.location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_symbol_type(
|
fn get_symbol_type(
|
||||||
&self,
|
&self,
|
||||||
_: &mut Unifier,
|
_: &mut Unifier,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use inkwell::{
|
||||||
OptimizationLevel,
|
OptimizationLevel,
|
||||||
};
|
};
|
||||||
use nac3core::typecheck::type_inferencer::PrimitiveStore;
|
use nac3core::typecheck::type_inferencer::PrimitiveStore;
|
||||||
use nac3parser::parser;
|
use nac3parser::{ast::{ExprKind, StmtKind}, parser};
|
||||||
use std::env;
|
use std::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};
|
||||||
|
@ -48,6 +48,7 @@ fn main() {
|
||||||
id_to_type: builtins_ty.into(),
|
id_to_type: builtins_ty.into(),
|
||||||
id_to_def: builtins_def.into(),
|
id_to_def: builtins_def.into(),
|
||||||
class_names: Default::default(),
|
class_names: Default::default(),
|
||||||
|
module_globals: Default::default(),
|
||||||
}
|
}
|
||||||
.into();
|
.into();
|
||||||
let resolver =
|
let resolver =
|
||||||
|
@ -66,6 +67,18 @@ 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 targets.len() == 1 {
|
||||||
|
if let ExprKind::Name { id, .. } = &targets[0].node {
|
||||||
|
internal_resolver.add_module_global(*id, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unimplemented!("only single assign supported now")
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let (name, def_id, ty) = composer
|
let (name, def_id, ty) = composer
|
||||||
.register_top_level(stmt, Some(resolver.clone()), "__main__".into())
|
.register_top_level(stmt, Some(resolver.clone()), "__main__".into())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
Loading…
Reference in New Issue