start adding primitives

This commit is contained in:
pca006132 2020-12-28 12:45:35 +08:00 committed by pca006132
parent fd3e1d4923
commit 81f4be60c7
4 changed files with 148 additions and 17 deletions

View File

@ -1,3 +1,4 @@
use super::primitives::*;
use super::types::{Type::*, *}; use super::types::{Type::*, *};
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
@ -147,14 +148,14 @@ pub fn resolve_call(
} else { } else {
return Err("divergent type after substitution".to_string()); return Err("divergent type after substitution".to_string());
} }
}, }
PrimitiveType(id) => &ctx.get_primitive(*id), PrimitiveType(id) => &ctx.get_primitive(*id),
ClassType(id) | VirtualClassType(id) => &ctx.get_class(*id).base, ClassType(id) | VirtualClassType(id) => &ctx.get_class(*id).base,
ParametricType(id, _) => &ctx.get_parametric(*id).base, ParametricType(id, _) => &ctx.get_parametric(*id).base,
_ => return Err("not supported".to_string()), _ => return Err("not supported".to_string()),
}; };
base.methods.get(func) base.methods.get(func)
}, }
None => ctx.get_fn(func), None => ctx.get_fn(func),
} }
.ok_or("no such function".to_string())?; .ok_or("no such function".to_string())?;

View File

@ -2,4 +2,5 @@ extern crate rustpython_parser;
mod types; mod types;
mod inference; mod inference;
mod primitives;

127
nac3type/src/primitives.rs Normal file
View File

@ -0,0 +1,127 @@
use super::types::{Type::*, *};
use std::collections::HashMap;
use std::rc::Rc;
pub const TUPLE_TYPE: ParamId = ParamId(0);
pub const LIST_TYPE: ParamId = ParamId(1);
pub const BOOL_TYPE: PrimitiveId = PrimitiveId(0);
pub const INT32_TYPE: PrimitiveId = PrimitiveId(1);
pub const FLOAT_TYPE: PrimitiveId = PrimitiveId(2);
fn impl_math(def: &mut TypeDef, ty: &Rc<Type>) {
let bin = Rc::new(ParametricType(
TUPLE_TYPE,
vec![SelfType.into(), ty.clone()],
));
let result = Some(ty.clone());
let fun = FnDef {
args: bin.clone(),
result,
};
def.methods.insert("__add__", fun.clone());
def.methods.insert("__sub__", fun.clone());
def.methods.insert("__mul__", fun.clone());
def.methods.insert("__neg__", fun.clone());
def.methods.insert(
"__truediv__",
FnDef {
args: bin.clone(),
result: Some(PrimitiveType(FLOAT_TYPE).into()),
},
);
def.methods.insert("__floordiv__", fun.clone());
def.methods.insert("__mod__", fun.clone());
def.methods.insert("__pow__", fun.clone());
}
fn impl_bits(def: &mut TypeDef, ty: &Rc<Type>) {
let bin = Rc::new(ParametricType(
TUPLE_TYPE,
vec![SelfType.into(), PrimitiveType(INT32_TYPE).into()],
));
let result = Some(ty.clone());
let fun = FnDef {
args: bin.clone(),
result,
};
def.methods.insert("__lshift__", fun.clone());
def.methods.insert("__rshift__", fun.clone());
def.methods.insert(
"__xor__",
FnDef {
args: ParametricType(TUPLE_TYPE, vec![SelfType.into(), ty.clone()]).into(),
result: Some(ty.clone()),
},
);
}
fn impl_eq(def: &mut TypeDef, ty: &Rc<Type>) {
let bin = Rc::new(ParametricType(
TUPLE_TYPE,
vec![SelfType.into(), ty.clone()],
));
let fun = FnDef {
args: bin.clone(),
result: Some(PrimitiveType(BOOL_TYPE).into()),
};
def.methods.insert("__eq__", fun.clone());
def.methods.insert("__ne__", fun.clone());
}
fn impl_order(def: &mut TypeDef, ty: &Rc<Type>) {
let bin = Rc::new(ParametricType(
TUPLE_TYPE,
vec![SelfType.into(), ty.clone()],
));
let fun = FnDef {
args: bin.clone(),
result: Some(PrimitiveType(BOOL_TYPE).into()),
};
def.methods.insert("__lt__", fun.clone());
def.methods.insert("__gt__", fun.clone());
def.methods.insert("__le__", fun.clone());
def.methods.insert("__ge__", fun.clone());
}
pub fn basic_ctx() -> GlobalContext<'static> {
let primitives = [
TypeDef {
name: "bool",
fields: HashMap::new(),
methods: HashMap::new(),
},
TypeDef {
name: "int32",
fields: HashMap::new(),
methods: HashMap::new(),
},
TypeDef {
name: "float",
fields: HashMap::new(),
methods: HashMap::new(),
},
]
.to_vec();
let mut ctx = GlobalContext::new(primitives);
let b_def = ctx.get_primitive_mut(BOOL_TYPE);
let b = PrimitiveType(BOOL_TYPE).into();
impl_eq(b_def, &b);
let int32_def = ctx.get_primitive_mut(INT32_TYPE);
let int32 = PrimitiveType(INT32_TYPE).into();
impl_math(int32_def, &int32);
impl_bits(int32_def, &int32);
impl_order(int32_def, &int32);
impl_eq(int32_def, &int32);
let float_def = ctx.get_primitive_mut(FLOAT_TYPE);
let float = PrimitiveType(FLOAT_TYPE).into();
impl_math(float_def, &float);
impl_order(float_def, &float);
impl_eq(float_def, &float);
ctx
}

View File

@ -2,16 +2,16 @@ use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub struct PrimitiveId(usize); pub struct PrimitiveId(pub(crate) usize);
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub struct ClassId(usize); pub struct ClassId(pub(crate) usize);
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub struct ParamId(usize); pub struct ParamId(pub(crate) usize);
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub struct VariableId(usize); pub struct VariableId(pub(crate) usize);
#[derive(PartialEq, Eq, Clone, Hash, Debug)] #[derive(PartialEq, Eq, Clone, Hash, Debug)]
pub enum Type { pub enum Type {
@ -24,38 +24,37 @@ pub enum Type {
TypeVariable(VariableId), TypeVariable(VariableId),
} }
#[derive(Clone)]
pub struct FnDef { pub struct FnDef {
pub args: Rc<Type>, pub args: Rc<Type>,
pub result: Option<Rc<Type>>, pub result: Option<Rc<Type>>,
} }
#[derive(Clone)]
pub struct TypeDef<'a> { pub struct TypeDef<'a> {
pub name: &'a str, pub name: &'a str,
pub fields: HashMap<&'a str, Type>, pub fields: HashMap<&'a str, Type>,
pub methods: HashMap<&'a str, FnDef>, pub methods: HashMap<&'a str, FnDef>,
} }
#[derive(Clone)]
pub struct ClassDef<'a> { pub struct ClassDef<'a> {
pub base: TypeDef<'a>, pub base: TypeDef<'a>,
pub parents: Vec<ClassId>, pub parents: Vec<ClassId>,
} }
#[derive(Clone)]
pub struct ParametricDef<'a> { pub struct ParametricDef<'a> {
pub base: TypeDef<'a>, pub base: TypeDef<'a>,
pub params: Vec<VariableId>, pub params: Vec<VariableId>,
} }
#[derive(Clone)]
pub struct VarDef<'a> { pub struct VarDef<'a> {
pub name: &'a str, pub name: &'a str,
pub bound: Vec<Rc<Type>>, pub bound: Vec<Rc<Type>>,
} }
pub const TUPLE_TYPE: ParamId = ParamId(0);
pub const LIST_TYPE: ParamId = ParamId(1);
pub const BOOL_TYPE: PrimitiveId = PrimitiveId(0);
pub const INT32_TYPE: PrimitiveId = PrimitiveId(1);
pub struct GlobalContext<'a> { pub struct GlobalContext<'a> {
primitive_defs: Vec<TypeDef<'a>>, primitive_defs: Vec<TypeDef<'a>>,
class_defs: Vec<ClassDef<'a>>, class_defs: Vec<ClassDef<'a>>,
@ -81,15 +80,16 @@ impl<'a> GlobalContext<'a> {
}; };
} }
pub fn add_class(&mut self, def: ClassDef<'a>) { pub fn add_class(&mut self, def: ClassDef<'a>) -> ClassId {
self.sym_table.insert( self.sym_table.insert(
def.base.name, def.base.name,
Type::ClassType(ClassId(self.class_defs.len())), Type::ClassType(ClassId(self.class_defs.len())),
); );
self.class_defs.push(def); self.class_defs.push(def);
ClassId(self.class_defs.len() - 1)
} }
pub fn add_parametric(&mut self, def: ParametricDef<'a>) { pub fn add_parametric(&mut self, def: ParametricDef<'a>) -> ParamId {
let params = def let params = def
.params .params
.iter() .iter()
@ -100,18 +100,20 @@ impl<'a> GlobalContext<'a> {
Type::ParametricType(ParamId(self.parametric_defs.len()), params), Type::ParametricType(ParamId(self.parametric_defs.len()), params),
); );
self.parametric_defs.push(def); self.parametric_defs.push(def);
ParamId(self.parametric_defs.len() - 1)
} }
pub fn add_variable(&mut self, def: VarDef<'a>) { pub fn add_variable(&mut self, def: VarDef<'a>) -> VariableId {
self.sym_table.insert( self.sym_table.insert(
def.name, def.name,
Type::TypeVariable(VariableId(self.var_defs.len())), Type::TypeVariable(VariableId(self.var_defs.len())),
); );
self.var_defs.push(def); self.add_variable_private(def)
} }
pub fn add_variable_private(&mut self, def: VarDef<'a>) { pub fn add_variable_private(&mut self, def: VarDef<'a>) -> VariableId {
self.var_defs.push(def); self.var_defs.push(def);
VariableId(self.var_defs.len() - 1)
} }
pub fn add_fn(&'a mut self, name: &'a str, def: FnDef) { pub fn add_fn(&'a mut self, name: &'a str, def: FnDef) {