forked from M-Labs/nac3
start adding primitives
This commit is contained in:
parent
fd3e1d4923
commit
81f4be60c7
@ -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())?;
|
||||||
|
@ -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
127
nac3type/src/primitives.rs
Normal 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
|
||||||
|
}
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user