Beginnings of a much simpler type system.

This commit is contained in:
James Harton 2019-02-22 22:08:48 +13:00
parent 115c1d51e9
commit e85fb16707
20 changed files with 465 additions and 734 deletions

View file

@ -6,3 +6,5 @@ edition = "2018"
[dependencies] [dependencies]
huia-parser = { path = "../huia-parser" } huia-parser = { path = "../huia-parser" }
wrc = "0.3.0"
string-interner = "0.7.0"

View file

@ -1,9 +0,0 @@
use crate::constant::Constant;
use crate::context::Context;
use std::rc::Rc;
pub fn bootstrap(context: &mut Context) {
let any_trait = Constant::new_trait("Any", Vec::new());
context.add_constant(Rc::new(any_trait));
}

View file

@ -1,15 +0,0 @@
use crate::constant::Constant;
use crate::context::Context;
use crate::method_table::{Method, MethodTable};
use std::rc::Rc;
pub fn bootstrap(context: &mut Context) {
let mut ary_type = Constant::native_array();
let method = Method::new("new", true);
ary_type.insert_method(method);
ary_type.implement(context.get_constant("Any").unwrap(), MethodTable::new());
context.add_constant(Rc::new(ary_type));
}

View file

@ -1,10 +0,0 @@
use crate::constant::Constant;
use crate::context::Context;
mod any;
mod array;
pub fn bootstrap(mut context: &mut Context) {
any::bootstrap(&mut context);
array::bootstrap(&mut context);
}

View file

@ -1,32 +1,134 @@
use crate::vtable::{Method, TraitData, VTable, VTableClassData, VTableImplData}; use crate::identifier::Identifier;
use std::sync::RwLock;
use wrc::WRC;
#[derive(Debug, Clone)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ClassData { pub struct ClassId(usize);
name: String,
vtable: VTableClassData, impl From<ClassId> for usize {
impls: Vec<(TraitData, VTableImplData)>, fn from(data: ClassId) -> usize {
data.0
}
} }
impl ClassData { impl From<usize> for ClassId {
pub fn new(name: &str) -> ClassData { fn from(data: usize) -> ClassId {
ClassData { ClassId(data)
name: name.to_string(), }
vtable: VTableClassData::new(), }
impls: Vec::new(),
pub struct Classes(RwLock<Vec<Class>>);
impl Classes {
pub fn new() -> Classes {
Classes(RwLock::new(Vec::new()))
}
pub fn push(&mut self, class: Class) -> ClassId {
let mut elements = self.0.write().unwrap();
let idx = elements.len();
elements.push(class);
ClassId::from(idx)
}
pub fn get(&self, idx: ClassId) -> Option<Class> {
let elements = self.0.read().unwrap();
match elements.get(idx.0) {
Some(class) => Some(class.clone()),
None => None,
}
}
pub fn next_id(&self) -> ClassId {
let elements = self.0.read().unwrap();
ClassId(elements.len())
}
pub fn is_empty(&self) -> bool {
let elements = self.0.read().unwrap();
elements.is_empty()
} }
} }
pub fn name(&self) -> &str { #[derive(Debug, Clone)]
&self.name pub struct Class(WRC<RwLock<ClassInner>>);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ClassInner {
id: ClassId,
name: Identifier,
}
impl ClassInner {
fn id(&self) -> ClassId {
self.id
}
fn name(&self) -> Identifier {
self.name
}
fn set_name(&mut self, name: Identifier) {
self.name = name
} }
} }
impl VTable for ClassData { impl Class {
fn insert_method(&mut self, method: Method) -> usize { pub fn new(id: ClassId, name: Identifier) -> Class {
self.vtable.insert_method(method) Class(WRC::new(RwLock::new(ClassInner { id, name })))
} }
fn get_method(&self, id: usize) -> Option<&Method> { pub fn id(&self) -> ClassId {
self.vtable.get_method(id) let class = self.0.read().unwrap();
class.id()
}
pub fn name(&self) -> Identifier {
let class = self.0.read().unwrap();
class.name()
}
pub fn set_name(&self, name: Identifier) {
let mut class = self.0.write().unwrap();
class.set_name(name);
}
}
impl PartialEq for Class {
fn eq(&self, other: &Class) -> bool {
self.id() == other.id()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::context::Context;
use crate::identifier::Identifiers;
#[test]
fn classes() {
let mut identifiers = Identifiers::new();
let mut classes = Classes::new();
let id = classes.next_id();
let name = identifiers.get("Marty McFly");
let class0 = Class::new(id, name);
let idx = classes.push(class0);
assert_eq!(idx.0, 0);
let class1 = classes.get(idx).unwrap();
assert_eq!(class1.id(), id);
assert_eq!(class1.name(), identifiers.get("Marty McFly"));
}
#[test]
fn set_name() {
let mut context = Context::new();
let class = context.new_class("Marty McFly");
assert_eq!(class.name(), context.get_identifier("Marty McFly"));
class.set_name(context.get_identifier("Doc Brown"));
assert_eq!(class.name(), context.get_identifier("Doc Brown"));
} }
} }

View file

@ -1,169 +0,0 @@
use crate::method_table::{Method, MethodTable};
use std::collections::BTreeMap;
use std::rc::Rc;
#[derive(Debug)]
pub struct Constant {
identifier: String,
inner: ConstantInner,
methods: MethodTable,
implements: Vec<(Rc<Constant>, MethodTable)>,
}
#[derive(Debug)]
pub enum ConstantInner {
NativeBoolean,
NativeFloat,
NativeInteger,
NativeArray,
NativeHashMap,
UserDefinedType {
property_types: BTreeMap<String, Rc<Constant>>,
},
Trait {
corequires: Vec<Rc<Constant>>,
},
}
pub struct Instance {
type_ref: Rc<Constant>,
inner: InstanceInner,
}
pub enum InstanceInner {
NativeBoolean(bool),
NativeFloat(f64),
NativeInteger(i64),
}
impl Constant {
pub fn native_array() -> Constant {
Constant {
identifier: "Huia.NativeArray".to_string(),
inner: ConstantInner::NativeArray,
methods: MethodTable::new(),
implements: Vec::new(),
}
}
pub fn native_boolean() -> Constant {
Constant {
identifier: "Huia.NativeBoolean".to_string(),
inner: ConstantInner::NativeBoolean,
methods: MethodTable::new(),
implements: Vec::new(),
}
}
pub fn native_float() -> Constant {
Constant {
identifier: "Huia.NativeFloat".to_string(),
inner: ConstantInner::NativeFloat,
methods: MethodTable::new(),
implements: Vec::new(),
}
}
pub fn native_hash_map() -> Constant {
Constant {
identifier: "Huia.NativeHashMap".to_string(),
inner: ConstantInner::NativeHashMap,
methods: MethodTable::new(),
implements: Vec::new(),
}
}
pub fn native_integer() -> Constant {
Constant {
identifier: "Huia.NativeInteger".to_string(),
inner: ConstantInner::NativeInteger,
methods: MethodTable::new(),
implements: Vec::new(),
}
}
pub fn new_trait(name: &str, corequires: Vec<Rc<Constant>>) -> Constant {
Constant {
identifier: name.to_string(),
inner: ConstantInner::Trait { corequires },
methods: MethodTable::new(),
implements: Vec::new(),
}
}
pub fn new_type(name: &str, property_types: BTreeMap<String, Rc<Constant>>) -> Constant {
Constant {
identifier: name.to_string(),
inner: ConstantInner::UserDefinedType { property_types },
methods: MethodTable::new(),
implements: Vec::new(),
}
}
pub fn identifier(&self) -> &str {
&self.identifier
}
pub fn is_native(&self) -> bool {
match self.inner {
ConstantInner::NativeArray => true,
ConstantInner::NativeBoolean => true,
ConstantInner::NativeFloat => true,
ConstantInner::NativeHashMap => true,
ConstantInner::NativeInteger => true,
_ => false,
}
}
pub fn insert_method(&mut self, method: Method) {
self.methods.insert(method);
}
pub fn get_method(&self, name: &str) -> Option<Rc<Method>> {
self.methods.get(name)
}
pub fn implement(&mut self, r#trait: Rc<Constant>, method_table: MethodTable) {
self.implements.push((r#trait, method_table));
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn native_array() {
let con = Constant::native_array();
assert_eq!(con.identifier(), "Huia.NativeArray");
assert!(con.is_native());
}
#[test]
fn native_boolean() {
let con = Constant::native_boolean();
assert_eq!(con.identifier(), "Huia.NativeBoolean");
assert!(con.is_native());
}
#[test]
fn native_float() {
let con = Constant::native_float();
assert_eq!(con.identifier(), "Huia.NativeFloat");
assert!(con.is_native());
}
#[test]
fn native_hash_map() {
let con = Constant::native_hash_map();
assert_eq!(con.identifier(), "Huia.NativeHashMap");
assert!(con.is_native());
}
#[test]
fn native_integer() {
let con = Constant::native_integer();
assert_eq!(con.identifier(), "Huia.NativeInteger");
assert!(con.is_native());
}
}

View file

@ -1,105 +1,58 @@
use crate::bootstrap::bootstrap; use crate::class::{Class, ClassId, Classes};
use crate::constant::Constant; use crate::identifier::{Identifier, Identifiers};
use crate::scope::Scope; use crate::r#trait::{Trait, TraitId, Traits};
use huia_parser::ast;
use huia_parser::ast::Value;
use std::collections::BTreeMap;
use std::rc::Rc;
pub struct Context { pub struct Context {
globals: Scope, classes: Classes,
traits: Traits,
identifiers: Identifiers,
} }
impl Context { impl Context {
pub fn new() -> Context { pub fn new() -> Context {
let globals = Scope::new(); Context {
let mut context = Context { globals }; classes: Classes::new(),
traits: Traits::new(),
bootstrap(&mut context); identifiers: Identifiers::new(),
context
}
pub fn consume(&mut self, terms: Vec<ast::Term>) {
for term in terms {
match term.node_type() {
ast::NodeType::Array => {}
ast::NodeType::Atom => {}
ast::NodeType::Binary => {}
ast::NodeType::Boolean => {}
ast::NodeType::Call => {}
ast::NodeType::Constant => {}
ast::NodeType::Constructor => {}
ast::NodeType::Declaration => {}
ast::NodeType::Definition => {
// let (deftype, defname, args, body) = term.definition().unwrap();
// match deftype.value_ref().as_ref() {
// "type" => self.define_type(defname, args, body),
// "def" => self.define_public_method(defname, args, body),
// "defp" => self.define_private_method(defname, args, body),
// "defs" => self.define_static_method(defname, args, body),
// _ => panic!("Unknown deftype {:?}", deftype),
// }
}
ast::NodeType::Float => {}
ast::NodeType::Integer => {}
ast::NodeType::Local => {}
ast::NodeType::Map => {}
ast::NodeType::MethodCall => {}
ast::NodeType::String => {}
ast::NodeType::Unary => {}
} }
} }
pub fn new_class(&mut self, name: &str) -> Class {
let name = self.identifiers.get(name);
let id = self.classes.next_id();
let class = Class::new(id, name);
self.classes.push(class);
self.classes.get(id).unwrap()
} }
fn define_type( pub fn get_class(&self, id: ClassId) -> Option<Class> {
&mut self, self.classes.get(id)
defname: &ast::Term,
args: &Vec<(ast::Identifier, ast::Term)>,
body: &Vec<(ast::Identifier, Vec<ast::Term>)>,
) {
// let name = defname.constant().unwrap().value_ref();
// let mut property_types = BTreeMap::new();
// for (ident, value) in args {
// property_types.insert(ident.value_ref().to_string(), value);
// }
// let t = Constant::new_type(name, property_types);
} }
fn define_public_method( pub fn new_trait(&mut self, name: &str) -> Trait {
&mut self, let name = self.identifiers.get(name);
defname: &ast::Term, let id = self.traits.next_id();
args: &Vec<(ast::Identifier, ast::Term)>, let tr = Trait::new(id, name);
body: &Vec<(ast::Identifier, Vec<ast::Term>)>, self.traits.push(tr);
) { self.traits.get(id).unwrap()
} }
fn define_private_method( pub fn get_trait(&self, id: TraitId) -> Option<Trait> {
&mut self, self.traits.get(id)
defname: &ast::Term,
args: &Vec<(ast::Identifier, ast::Term)>,
body: &Vec<(ast::Identifier, Vec<ast::Term>)>,
) {
} }
fn define_static_method( pub fn get_identifier(&mut self, value: &str) -> Identifier {
&mut self, self.identifiers.get(value)
defname: &ast::Term,
args: &Vec<(ast::Identifier, ast::Term)>,
body: &Vec<(ast::Identifier, Vec<ast::Term>)>,
) {
} }
pub fn add_constant(&mut self, constant: Rc<Constant>) { pub fn get_identifier_value(&self, identifier: Identifier) -> Option<&str> {
self.globals.insert(constant); self.identifiers.resolve(identifier)
} }
pub fn get_constant(&self, name: &str) -> Option<Rc<Constant>> { pub fn is_empty(&self) -> bool {
self.globals.get(name) // Traits and Classes must be empty if identifiers is empty because
// classes and traits must be initialised with identifier names.
self.identifiers.is_empty()
} }
} }
@ -109,6 +62,16 @@ mod test {
#[test] #[test]
fn new() { fn new() {
let context = Context::new(); let mut context = Context::new();
let class0 = context.new_class("Marty McFly");
let class1 = context.get_class(class0.id()).unwrap();
assert_eq!(class0, class1);
let tr0 = context.new_trait("Doc Brown");
let tr1 = context.get_trait(tr0.id()).unwrap();
assert_eq!(tr0, tr1);
let id = context.get_identifier("Einstein Brown");
assert_eq!(context.get_identifier_value(id).unwrap(), "Einstein Brown");
} }
} }

View file

@ -0,0 +1,42 @@
use string_interner::{StringInterner, Sym};
#[derive(Debug, Clone, Hash, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Identifier(Sym);
pub struct Identifiers(StringInterner<Sym>);
impl Identifiers {
pub fn new() -> Identifiers {
Identifiers(StringInterner::default())
}
pub fn get(&mut self, value: &str) -> Identifier {
let sym = self.0.get_or_intern(value);
Identifier(sym)
}
pub fn resolve(&self, identifier: Identifier) -> Option<&str> {
self.0.resolve(identifier.0)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
let mut identifiers = Identifiers::new();
assert!(identifiers.is_empty());
let sym0 = identifiers.get("Marty McFly");
let sym1 = identifiers.get("Marty McFly");
assert!(!identifiers.is_empty());
assert_eq!(sym0, sym1);
assert_eq!(identifiers.resolve(sym0).unwrap(), "Marty McFly");
}
}

View file

@ -1,10 +1,17 @@
extern crate huia_parser; extern crate huia_parser;
mod bootstrap; extern crate string_interner;
mod class; extern crate wrc;
mod constant;
mod context;
mod method_table;
mod scope;
mod vtable;
pub use class::ClassData; mod class;
mod context;
mod identifier;
mod r#trait;
mod r#type;
mod type_spec;
pub use class::{Class, ClassId};
pub use context::Context;
pub use identifier::Identifier;
pub use r#trait::{Trait, TraitId};
pub use r#type::Type;
pub use type_spec::TypeSpec;

View file

@ -1,67 +0,0 @@
use crate::constant::Constant;
use std::collections::BTreeMap;
use std::rc::Rc;
#[derive(Debug)]
pub struct MethodTable(BTreeMap<String, Rc<Method>>);
impl MethodTable {
pub fn new() -> MethodTable {
MethodTable(BTreeMap::new())
}
pub fn insert(&mut self, method: Method) {
let name = method.identifier();
self.0.insert(name.to_string(), Rc::new(method));
}
pub fn get(&self, name: &str) -> Option<Rc<Method>> {
match self.0.get(name) {
Some(m) => Some(m.clone()),
None => None,
}
}
}
#[derive(Debug)]
pub enum Visibility {
Public,
Private,
}
#[derive(Debug)]
pub struct Method {
identifier: String,
visibility: Visibility,
}
impl Method {
pub fn new(name: &str, public: bool) -> Method {
let visibility = match public {
true => Visibility::Public,
false => Visibility::Private,
};
Method {
identifier: name.to_string(),
visibility,
}
}
pub fn identifier(&self) -> &str {
&self.identifier
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn method_table() {
let mut mt = MethodTable::new();
let m = Method::new("marty", true);
mt.insert(m);
}
}

View file

@ -1,23 +0,0 @@
use crate::constant::Constant;
use std::collections::BTreeMap;
use std::rc::Rc;
#[derive(Debug)]
pub struct Scope(BTreeMap<String, Rc<Constant>>);
impl Scope {
pub fn new() -> Scope {
Scope(BTreeMap::new())
}
pub fn insert(&mut self, constant: Rc<Constant>) {
self.0.insert(constant.identifier().to_string(), constant);
}
pub fn get(&self, name: &str) -> Option<Rc<Constant>> {
match self.0.get(name) {
Some(c) => Some(c.clone()),
None => None,
}
}
}

134
huia-compiler/src/trait.rs Normal file
View file

@ -0,0 +1,134 @@
use crate::identifier::Identifier;
use std::sync::RwLock;
use wrc::WRC;
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct TraitId(usize);
impl From<TraitId> for usize {
fn from(data: TraitId) -> usize {
data.0
}
}
impl From<usize> for TraitId {
fn from(data: usize) -> TraitId {
TraitId(data)
}
}
pub struct Traits(RwLock<Vec<Trait>>);
impl Traits {
pub fn new() -> Traits {
Traits(RwLock::new(Vec::new()))
}
pub fn push(&mut self, r#trait: Trait) -> TraitId {
let mut elements = self.0.write().unwrap();
let idx = elements.len();
elements.push(r#trait);
TraitId::from(idx)
}
pub fn get(&self, idx: TraitId) -> Option<Trait> {
let elements = self.0.read().unwrap();
match elements.get(idx.0) {
Some(tr) => Some(tr.clone()),
None => None,
}
}
pub fn next_id(&self) -> TraitId {
let elements = self.0.read().unwrap();
TraitId(elements.len())
}
pub fn is_empty(&self) -> bool {
let elements = self.0.read().unwrap();
elements.is_empty()
}
}
#[derive(Debug, Clone)]
pub struct Trait(WRC<RwLock<TraitInner>>);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct TraitInner {
id: TraitId,
name: Identifier,
}
impl TraitInner {
fn id(&self) -> TraitId {
self.id
}
fn name(&self) -> Identifier {
self.name
}
fn set_name(&mut self, name: Identifier) {
self.name = name
}
}
impl Trait {
pub fn new(id: TraitId, name: Identifier) -> Trait {
Trait(WRC::new(RwLock::new(TraitInner { id, name })))
}
pub fn id(&self) -> TraitId {
let tr = self.0.read().unwrap();
tr.id()
}
pub fn name(&self) -> Identifier {
let tr = self.0.read().unwrap();
tr.name()
}
pub fn set_name(&self, name: Identifier) {
let mut tr = self.0.write().unwrap();
tr.set_name(name);
}
}
impl PartialEq for Trait {
fn eq(&self, other: &Trait) -> bool {
self.id() == other.id()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::context::Context;
use crate::identifier::Identifiers;
#[test]
fn traits() {
let mut identifiers = Identifiers::new();
let mut traits = Traits::new();
let id = traits.next_id();
let name = identifiers.get("Marty McFly");
let trait0 = Trait::new(id, name);
let idx = traits.push(trait0);
assert_eq!(idx.0, 0);
let trait1 = traits.get(idx).unwrap();
assert_eq!(trait1.id(), id);
assert_eq!(trait1.name(), identifiers.get("Marty McFly"));
}
#[test]
fn set_name() {
let mut context = Context::new();
let tr = context.new_trait("Marty McFly");
assert_eq!(tr.name(), context.get_identifier("Marty McFly"));
tr.set_name(context.get_identifier("Doc Brown"));
assert_eq!(tr.name(), context.get_identifier("Doc Brown"));
}
}

68
huia-compiler/src/type.rs Normal file
View file

@ -0,0 +1,68 @@
use crate::class::ClassId;
use crate::r#trait::TraitId;
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum Type {
Class(ClassId),
Trait(TraitId),
}
impl Type {
pub fn is_class(&self) -> bool {
match self {
Type::Class(_) => true,
_ => false,
}
}
pub fn is_trait(&self) -> bool {
match self {
Type::Trait(_) => true,
_ => false,
}
}
pub fn class_id(&self) -> Option<ClassId> {
match self {
Type::Class(id) => Some(id.clone()),
_ => None,
}
}
pub fn trait_id(&self) -> Option<TraitId> {
match self {
Type::Trait(id) => Some(id.clone()),
_ => None,
}
}
}
impl From<ClassId> for Type {
fn from(id: ClassId) -> Type {
Type::Class(id)
}
}
impl From<TraitId> for Type {
fn from(id: TraitId) -> Type {
Type::Trait(id)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
let ty0 = Type::from(ClassId::from(0));
let ty1 = Type::from(TraitId::from(0));
assert_ne!(ty0, ty1);
assert!(ty0.is_class());
assert!(ty1.is_trait());
assert_eq!(ty0.class_id().unwrap(), ClassId::from(0));
assert_eq!(ty1.trait_id().unwrap(), TraitId::from(0));
}
}

View file

@ -0,0 +1,36 @@
use crate::r#type::Type;
#[derive(Debug)]
pub struct TypeSpec(Vec<Type>);
impl TypeSpec {
pub fn new() -> TypeSpec {
TypeSpec(Vec::new())
}
pub fn push(&mut self, ty: Type) {
self.0.push(ty)
}
pub fn matches(&self, ty: Type) -> bool {
self.0.iter().any(|i| i == &ty)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::class::ClassId;
use crate::r#trait::TraitId;
#[test]
fn test() {
let mut type_spec = TypeSpec::new();
let ty0 = Type::from(ClassId::from(0));
let ty1 = Type::from(TraitId::from(0));
assert!(ty0.is_class());
assert!(ty1.is_trait());
type_spec.push(ty0);
type_spec.push(ty1);
}
}

View file

@ -1,67 +0,0 @@
use crate::vtable::{Instance, Requirement};
use std::fmt;
#[derive(Debug, Clone)]
pub struct Function {
return_requirements: Requirement,
heads: Vec<FunctionClause>,
}
impl Function {
pub fn new() -> Function {
Function {
return_requirements: Requirement::new(),
heads: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct FunctionClause {
argument_names: Vec<String>,
argument_requirements: Vec<Requirement>,
function_body: FunctionBody,
}
impl FunctionClause {
pub fn new() -> FunctionClause {
FunctionClause {
argument_names: Vec::new(),
argument_requirements: Vec::new(),
function_body: FunctionBody::Empty,
}
}
pub fn add_argument(&mut self, argument_name: &str, argument_type: Requirement) {
self.argument_names.push(argument_name.to_string());
self.argument_requirements.push(argument_type);
}
}
#[derive(Clone)]
pub enum FunctionBody {
Empty,
NativeFunction(fn(Instance, Vec<&str>, Vec<Instance>) -> Instance),
UserFunction(),
}
impl fmt::Debug for FunctionBody {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FunctionBody::Empty => write!(f, "Empty"),
FunctionBody::NativeFunction(_) => write!(f, "NativeFunction"),
FunctionBody::UserFunction() => write!(f, "UserFunction"),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
let mut f = Function::new();
let mut fhead = FunctionClause::new();
}
}

View file

@ -1,91 +0,0 @@
use crate::vtable::Function;
#[derive(Debug, Clone)]
pub struct Method {
name: String,
flag: MethodFlag,
fun: Function,
}
impl Method {
pub fn new(name: &str, flag: MethodFlag, fun: Function) -> Method {
let name = name.to_string();
Method { name, flag, fun }
}
pub fn is_public(&self) -> bool {
match self.flag {
MethodFlag::Public => true,
_ => false,
}
}
pub fn is_private(&self) -> bool {
match self.flag {
MethodFlag::Private => true,
_ => false,
}
}
pub fn is_static(&self) -> bool {
match self.flag {
MethodFlag::Static => true,
_ => false,
}
}
pub fn flag(&self) -> MethodFlag {
self.flag.clone()
}
pub fn set_flag(&mut self, flag: MethodFlag) {
self.flag = flag;
}
pub fn fun(&self) -> &Function {
&self.fun
}
pub fn set_fun(&mut self, fun: Function) {
self.fun = fun;
}
}
#[derive(Debug, Clone)]
pub enum MethodFlag {
Public,
Private,
Static,
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
let f = Function::new();
let m = Method::new("marty", MethodFlag::Public, f.clone());
assert!(m.is_public());
assert!(!m.is_private());
assert!(!m.is_static());
let m = Method::new("marty", MethodFlag::Private, f.clone());
assert!(!m.is_public());
assert!(m.is_private());
assert!(!m.is_static());
let m = Method::new("marty", MethodFlag::Static, f.clone());
assert!(!m.is_public());
assert!(!m.is_private());
assert!(m.is_static());
let mut m = Method::new("marty", MethodFlag::Static, f.clone());
m.set_flag(MethodFlag::Public);
assert!(m.is_public());
assert!(!m.is_private());
assert!(!m.is_static());
}
}

View file

@ -1,38 +0,0 @@
mod function;
mod method;
mod requirement;
mod tables;
mod r#trait;
pub use function::{Function, FunctionBody, FunctionClause};
pub use method::{Method, MethodFlag};
pub use r#trait::TraitData;
pub use requirement::Requirement;
use std::rc::Rc;
pub use tables::{VTableClassData, VTableDefaultImplData, VTableImplData, VTableTraitData};
use crate::ClassData;
#[derive(Debug, Clone)]
pub enum Type {
Class(ClassData),
Trait(TraitData),
}
#[derive(Debug, Clone)]
pub struct Instance {
class: Rc<ClassData>,
}
pub trait VTable {
fn insert_method(&mut self, method: Method) -> usize;
fn get_method(&self, id: usize) -> Option<&Method>;
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {}
}

View file

@ -1,23 +0,0 @@
use crate::vtable::Type;
use std::rc::Rc;
#[derive(Debug, Clone)]
pub struct Requirement(Vec<Rc<Type>>);
impl Requirement {
pub fn new() -> Requirement {
Requirement(Vec::new())
}
pub fn push(&mut self, r#type: Rc<Type>) {
self.0.push(r#type);
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
}

View file

@ -1,81 +0,0 @@
use crate::vtable::{Method, VTable};
#[derive(Debug, Clone)]
pub struct VTableImplData(Vec<Method>);
impl VTableImplData {
pub fn new() -> VTableImplData {
VTableImplData(Vec::new())
}
}
#[derive(Debug, Clone)]
pub struct VTableDefaultImplData(Vec<Method>);
impl VTableDefaultImplData {
pub fn new() -> VTableDefaultImplData {
VTableDefaultImplData(Vec::new())
}
}
#[derive(Debug, Clone)]
pub struct VTableClassData(Vec<Method>);
impl VTableClassData {
pub fn new() -> VTableClassData {
VTableClassData(Vec::new())
}
}
#[derive(Debug, Clone)]
pub struct VTableTraitData(Vec<Method>);
impl VTableTraitData {
pub fn new() -> VTableTraitData {
VTableTraitData(Vec::new())
}
}
impl VTable for VTableImplData {
fn insert_method(&mut self, method: Method) -> usize {
self.0.push(method);
self.0.len()
}
fn get_method(&self, id: usize) -> Option<&Method> {
self.0.get(id)
}
}
impl VTable for VTableDefaultImplData {
fn insert_method(&mut self, method: Method) -> usize {
self.0.push(method);
self.0.len()
}
fn get_method(&self, id: usize) -> Option<&Method> {
self.0.get(id)
}
}
impl VTable for VTableClassData {
fn insert_method(&mut self, method: Method) -> usize {
self.0.push(method);
self.0.len()
}
fn get_method(&self, id: usize) -> Option<&Method> {
self.0.get(id)
}
}
impl VTable for VTableTraitData {
fn insert_method(&mut self, method: Method) -> usize {
self.0.push(method);
self.0.len()
}
fn get_method(&self, id: usize) -> Option<&Method> {
self.0.get(id)
}
}

View file

@ -1,30 +0,0 @@
use crate::vtable::{Method, VTable, VTableTraitData};
#[derive(Debug, Clone)]
pub struct TraitData {
name: String,
vtable: VTableTraitData,
}
impl TraitData {
pub fn new(name: &str) -> TraitData {
TraitData {
name: name.to_string(),
vtable: VTableTraitData::new(),
}
}
pub fn name(&self) -> &str {
&self.name
}
}
impl VTable for TraitData {
fn insert_method(&mut self, method: Method) -> usize {
self.vtable.insert_method(method)
}
fn get_method(&self, id: usize) -> Option<&Method> {
self.vtable.get_method(id)
}
}