This commit is contained in:
James Harton 2019-02-25 13:36:51 +13:00
parent 2b2d40bb55
commit f2b84a6e54
44 changed files with 966 additions and 834 deletions

View file

@ -0,0 +1,11 @@
use crate::context::Context;
pub fn bootstrap(context: &mut Context) {
context.ensure_class(context.ident("Huia.Native.Array"));
context.ensure_class(context.ident("Huia.Native.Atom"));
context.ensure_class(context.ident("Huia.Native.Boolean"));
context.ensure_class(context.ident("Huia.Native.Float"));
context.ensure_class(context.ident("Huia.Native.Integer"));
context.ensure_class(context.ident("Huia.Native.Map"));
context.ensure_class(context.ident("Huia.Native.String"));
}

View file

@ -1,68 +0,0 @@
use crate::class::ClassId;
use crate::identifier::Identifier;
use std::sync::RwLock;
use wrc::WRC;
#[derive(Debug, Clone)]
pub struct Class(WRC<RwLock<ClassInner>>);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
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 Class {
pub fn new(id: ClassId, name: Identifier) -> Class {
Class(WRC::new(RwLock::new(ClassInner { id, name })))
}
pub fn id(&self) -> ClassId {
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 crate::context::Context;
#[test]
fn set_name() {
let mut context = Context::new();
let class = context.new_class("Marty McFly");
assert_eq!(class.name(), context.identifiers().get("Marty McFly"));
class.set_name(context.identifiers().get("Doc Brown"));
assert_eq!(class.name(), context.identifiers().get("Doc Brown"));
}
}

View file

@ -1,14 +0,0 @@
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ClassId(usize);
impl From<ClassId> for usize {
fn from(data: ClassId) -> usize {
data.0
}
}
impl From<usize> for ClassId {
fn from(data: usize) -> ClassId {
ClassId(data)
}
}

View file

@ -1,69 +0,0 @@
use crate::class::{Class, ClassId};
use crate::identifier::Identifier;
use std::sync::RwLock;
#[derive(Default, Debug)]
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(usize::from(idx)) {
Some(class) => Some(class.clone()),
None => None,
}
}
pub fn next_id(&self) -> ClassId {
let elements = self.0.read().unwrap();
ClassId::from(elements.len())
}
pub fn find(&self, name: Identifier) -> Option<ClassId> {
let elements = self.0.read().unwrap();
let class = elements.iter().find(|class| class.name() == name);
match class {
Some(class) => Some(class.id()),
None => None,
}
}
pub fn is_empty(&self) -> bool {
let elements = self.0.read().unwrap();
elements.is_empty()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::identifier::Identifiers;
#[test]
fn test() {
let 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!(usize::from(idx), 0);
let class1 = classes.get(idx).unwrap();
assert_eq!(class1.id(), id);
assert_eq!(class1.name(), identifiers.get("Marty McFly"));
}
}

View file

@ -1,6 +0,0 @@
mod actual;
mod class_id;
mod classes;
pub use actual::Class;
pub use class_id::ClassId;
pub use classes::Classes;

View file

@ -0,0 +1,137 @@
use crate::argument::Argument;
use crate::identifier::Identifier;
use crate::method::{Method, MethodId};
use crate::types::TypeId;
use crate::vtable::VTable;
use std::sync::RwLock;
use wrc::WRC;
#[derive(Debug, Clone)]
pub struct Class(WRC<RwLock<ClassInner>>);
#[derive(Debug)]
struct ClassInner {
id: TypeId,
name: Identifier,
properties: Vec<Argument>,
vtable: VTable,
impls: Vec<(TypeId, VTable)>,
}
impl ClassInner {
fn id(&self) -> TypeId {
self.id
}
fn name(&self) -> Identifier {
self.name
}
fn set_name(&mut self, name: Identifier) {
self.name = name
}
fn add_method(&mut self, method: Method) -> MethodId {
self.vtable.add_method(method)
}
fn next_id(&self) -> MethodId {
self.vtable.next_id()
}
fn add_property(&mut self, property: Argument) {
self.properties.push(property);
}
fn has_property(&self, name: Identifier) -> bool {
self.properties.iter().any(|p| p.name() == name)
}
fn implement(&mut self, tr: TypeId, vtable: VTable) {
self.impls.push((tr, vtable));
}
fn implements(&self, tr: TypeId) -> bool {
self.impls.iter().any(|(tr0, _)| tr0 == &tr)
}
}
impl Class {
pub fn new(id: TypeId, name: Identifier) -> Class {
let vtable = VTable::new();
let impls = Vec::new();
let properties = Vec::new();
Class(WRC::new(RwLock::new(ClassInner {
id,
name,
vtable,
properties,
impls,
})))
}
pub fn id(&self) -> TypeId {
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);
}
pub fn add_method(&self, method: Method) -> MethodId {
let mut class = self.0.write().unwrap();
class.add_method(method)
}
pub fn next_id(&self) -> MethodId {
let class = self.0.read().unwrap();
class.next_id()
}
pub fn add_property(&self, property: Argument) {
let mut class = self.0.write().unwrap();
class.add_property(property);
}
pub fn has_property(&self, name: Identifier) -> bool {
let class = self.0.read().unwrap();
class.has_property(name)
}
pub fn implement(&self, tr: TypeId, vtable: VTable) {
let mut class = self.0.write().unwrap();
class.implement(tr, vtable);
}
pub fn implements(&self, tr: TypeId) -> bool {
let class = self.0.read().unwrap();
class.implements(tr)
}
}
impl PartialEq for Class {
fn eq(&self, other: &Class) -> bool {
self.id() == other.id()
}
}
#[cfg(test)]
mod test {
use crate::context::Context;
#[test]
fn set_name() {
let mut context = Context::new();
let class = context.ensure_class(context.ident("Marty McFly"));
assert_eq!(class.name(), context.ident("Marty McFly"));
class.set_name(context.ident("Doc Brown"));
assert_eq!(class.name(), context.ident("Doc Brown"));
}
}

View file

@ -0,0 +1,2 @@
mod actual;
pub use actual::Class;

View file

@ -1,157 +0,0 @@
use crate::class::ClassId;
use string_interner::{StringInterner, Sym};
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ConstantId(usize);
impl From<ConstantId> for usize {
fn from(data: ConstantId) -> usize {
data.0
}
}
impl From<usize> for ConstantId {
fn from(data: usize) -> ConstantId {
ConstantId(data)
}
}
#[derive(Debug, Default)]
pub struct Constants {
values: Vec<Constant>,
strings: StringInterner<Sym>,
}
impl Constants {
pub fn new() -> Constants {
Constants {
values: Vec::new(),
strings: StringInterner::default(),
}
}
pub fn get(&self, id: ConstantId) -> Option<&Constant> {
match self.values.get(id.0) {
Some(constant) => Some(&constant),
None => None,
}
}
pub fn new_i64(&mut self, class_id: ClassId, i: i64) -> ConstantId {
let value = ConstantInner::I64(i);
let constant = Constant { class_id, value };
let id = self.values.len();
self.values.push(constant);
ConstantId(id)
}
pub fn get_i64(&self, id: ConstantId) -> Option<i64> {
let idx = id.0;
let constant = self.values[idx].clone();
match constant.value {
ConstantInner::I64(i) => Some(i),
_ => None,
}
}
pub fn new_f64(&mut self, class_id: ClassId, f: f64) -> ConstantId {
let value = ConstantInner::F64(f);
let constant = Constant { class_id, value };
let id = self.values.len();
self.values.push(constant);
ConstantId(id)
}
pub fn get_f64(&self, id: ConstantId) -> Option<f64> {
let idx = id.0;
let constant = self.values[idx].clone();
match constant.value {
ConstantInner::F64(f) => Some(f),
_ => None,
}
}
pub fn new_string(&mut self, class_id: ClassId, s: &str) -> ConstantId {
let sym = self.strings.get_or_intern(s);
let value = ConstantInner::String(sym);
let constant = Constant { class_id, value };
let id = self.values.len();
self.values.push(constant);
ConstantId(id)
}
pub fn get_string(&self, id: ConstantId) -> Option<&str> {
let idx = id.0;
let constant = self.values[idx].clone();
match constant.value {
ConstantInner::String(s) => self.strings.resolve(s),
_ => None,
}
}
pub fn is_empty(&self) -> bool {
self.values.is_empty() && self.strings.is_empty()
}
}
#[derive(Debug, PartialEq, PartialOrd, Clone)]
pub struct Constant {
class_id: ClassId,
value: ConstantInner,
}
impl Constant {
pub fn is_i64(&self) -> bool {
match self.value {
ConstantInner::I64(_) => true,
_ => false,
}
}
pub fn is_f64(&self) -> bool {
match self.value {
ConstantInner::F64(_) => true,
_ => false,
}
}
pub fn is_string(&self) -> bool {
match self.value {
ConstantInner::String(_) => true,
_ => false,
}
}
}
#[derive(Debug, PartialEq, PartialOrd, Clone)]
enum ConstantInner {
I64(i64),
F64(f64),
String(Sym),
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
let mut constants = Constants::new();
assert!(constants.is_empty());
let class_id = ClassId::from(0);
let i = constants.new_i64(class_id, 123);
assert!(constants.get(i).unwrap().is_i64());
assert_eq!(constants.get_i64(i).unwrap(), 123);
let f = constants.new_f64(class_id, 1.21);
assert!(constants.get(f).unwrap().is_f64());
let f0 = constants.get_f64(f).unwrap() - 1.21;
assert!(f0 < std::f64::EPSILON);
let s = constants.new_string(class_id, "Marty McFly");
assert!(constants.get(s).unwrap().is_string());
assert_eq!(constants.get_string(s).unwrap(), "Marty McFly");
}
}

View file

@ -1,65 +1,81 @@
use crate::class::{Class, Classes}; use crate::classes::Class;
use crate::constant::Constants;
use crate::function::Functions; use crate::function::Functions;
use crate::identifier::Identifiers; use crate::identifier::{Identifier, Identifiers};
use crate::r#trait::{Trait, Traits}; use crate::traits::Trait;
use crate::types::{Type, TypeId, TypeTable};
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Context { pub struct Context {
classes: Classes, types: TypeTable,
traits: Traits,
identifiers: Identifiers, identifiers: Identifiers,
constants: Constants,
functions: Functions, functions: Functions,
} }
impl Context { impl Context {
pub fn new() -> Context { pub fn new() -> Context {
Context { Context {
classes: Classes::new(), types: TypeTable::new(),
traits: Traits::new(),
identifiers: Identifiers::new(), identifiers: Identifiers::new(),
constants: Constants::new(),
functions: Functions::new(), functions: Functions::new(),
} }
} }
pub fn new_class(&mut self, name: &str) -> Class { pub fn ensure_class(&self, name: Identifier) -> Class {
let name = self.identifiers.get(name); match self.get_type_by_name(name) {
let id = self.classes.next_id(); Some(ty) => match ty.as_class() {
let class = Class::new(id, name); Some(ty) => ty,
self.classes.push(class); None => self.create_class(name),
self.classes.get(id).unwrap() },
None => self.create_class(name),
}
} }
pub fn new_trait(&mut self, name: &str) -> Trait { pub fn ensure_trait(&self, name: Identifier) -> Trait {
let name = self.identifiers.get(name); match self.get_type_by_name(name) {
let id = self.traits.next_id(); Some(ty) => match ty.as_trait() {
Some(ty) => ty,
None => self.create_trait(name),
},
None => self.create_trait(name),
}
}
fn create_class(&self, name: Identifier) -> Class {
let id = self.types.next_id();
let class = Class::new(id, name);
self.types.push(class.clone());
class
}
fn create_trait(&self, name: Identifier) -> Trait {
let id = self.types.next_id();
let tr = Trait::new(id, name); let tr = Trait::new(id, name);
self.traits.push(tr); self.types.push(tr.clone());
self.traits.get(id).unwrap() tr
}
pub fn get_type(&self, id: TypeId) -> Option<Type> {
self.types.get(id)
}
pub fn get_type_by_name(&self, name: Identifier) -> Option<Type> {
self.types.find(name)
}
pub fn ident(&self, name: &str) -> Identifier {
self.identifiers().get(name)
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
// Traits and Classes must be empty if identifiers is empty because self.identifiers.is_empty() && self.types.is_empty()
// classes and traits must be initialised with identifier names.
self.identifiers.is_empty() && self.constants.is_empty()
} }
pub fn identifiers(&self) -> &Identifiers { pub fn identifiers(&self) -> &Identifiers {
&self.identifiers &self.identifiers
} }
pub fn constants(&self) -> &Constants { pub fn types(&self) -> &TypeTable {
&self.constants &self.types
}
pub fn classes(&self) -> &Classes {
&self.classes
}
pub fn traits(&self) -> &Traits {
&self.traits
} }
pub fn functions(&self) -> &Functions { pub fn functions(&self) -> &Functions {
@ -73,16 +89,16 @@ mod test {
#[test] #[test]
fn new() { fn new() {
let mut context = Context::new(); let context = Context::new();
let class0 = context.new_class("Marty McFly"); let class0 = context.ensure_class(context.ident("Marty McFly"));
let class1 = context.classes().get(class0.id()).unwrap(); let class1 = context.types().get(class0.id()).unwrap();
assert_eq!(class0, class1); assert_eq!(class0, class1);
let tr0 = context.new_trait("Doc Brown"); let tr0 = context.ensure_trait(context.ident("Doc Brown"));
let tr1 = context.traits().get(tr0.id()).unwrap(); let tr1 = context.types().get(tr0.id()).unwrap();
assert_eq!(tr0, tr1); assert_eq!(tr0, tr1);
let id = context.identifiers().get("Einstein Brown"); let id = context.ident("Einstein Brown");
assert_eq!(context.identifiers().resolve(id).unwrap(), "Einstein Brown"); assert_eq!(context.identifiers().resolve(id).unwrap(), "Einstein Brown");
} }
} }

View file

@ -1,5 +1,4 @@
use crate::function::{Clause, ClauseId, FunctionId}; use crate::function::{Clause, ClauseId, FunctionId};
use crate::identifier::Identifier;
use std::sync::RwLock; use std::sync::RwLock;
use wrc::WRC; use wrc::WRC;
@ -9,7 +8,6 @@ pub struct Function(WRC<RwLock<FunctionInner>>);
#[derive(Debug)] #[derive(Debug)]
struct FunctionInner { struct FunctionInner {
id: FunctionId, id: FunctionId,
name: Identifier,
clauses: Vec<Clause>, clauses: Vec<Clause>,
} }
@ -18,14 +16,6 @@ impl FunctionInner {
self.id self.id
} }
fn name(&self) -> Identifier {
self.name
}
fn set_name(&mut self, name: Identifier) {
self.name = name
}
fn add_clause(&mut self, clause: Clause) -> ClauseId { fn add_clause(&mut self, clause: Clause) -> ClauseId {
let idx = self.clauses.len(); let idx = self.clauses.len();
self.clauses.push(clause); self.clauses.push(clause);
@ -38,9 +28,9 @@ impl FunctionInner {
} }
impl Function { impl Function {
pub fn new(id: FunctionId, name: Identifier) -> Function { pub fn new(id: FunctionId) -> Function {
let clauses = Vec::new(); let clauses = Vec::new();
Function(WRC::new(RwLock::new(FunctionInner { id, name, clauses }))) Function(WRC::new(RwLock::new(FunctionInner { id, clauses })))
} }
pub fn id(&self) -> FunctionId { pub fn id(&self) -> FunctionId {
@ -48,16 +38,6 @@ impl Function {
fun.id() fun.id()
} }
pub fn name(&self) -> Identifier {
let fun = self.0.read().unwrap();
fun.name()
}
pub fn set_name(&self, name: Identifier) {
let mut fun = self.0.write().unwrap();
fun.set_name(name);
}
pub fn add_clause(&self, clause: Clause) -> ClauseId { pub fn add_clause(&self, clause: Clause) -> ClauseId {
let mut fun = self.0.write().unwrap(); let mut fun = self.0.write().unwrap();
fun.add_clause(clause) fun.add_clause(clause)

View file

@ -1,8 +1,9 @@
use crate::function::{Argument, ClauseId}; use crate::argument::Argument;
use crate::function::ClauseId;
use std::sync::RwLock; use std::sync::RwLock;
use wrc::WRC; use wrc::WRC;
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Clause(WRC<RwLock<ClauseInner>>); pub struct Clause(WRC<RwLock<ClauseInner>>);
#[derive(Debug)] #[derive(Debug)]

View file

@ -1,5 +1,4 @@
use crate::function::{Function, FunctionId}; use crate::function::{Function, FunctionId};
use crate::identifier::Identifier;
use std::sync::RwLock; use std::sync::RwLock;
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -30,15 +29,6 @@ impl Functions {
FunctionId::from(elements.len()) FunctionId::from(elements.len())
} }
pub fn find(&self, name: Identifier) -> Option<FunctionId> {
let elements = self.0.read().unwrap();
let function = elements.iter().find(|function| function.name() == name);
match function {
Some(function) => Some(function.id()),
None => None,
}
}
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
let elements = self.0.read().unwrap(); let elements = self.0.read().unwrap();
elements.is_empty() elements.is_empty()
@ -48,22 +38,18 @@ impl Functions {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::identifier::Identifiers;
#[test] #[test]
fn test() { fn test() {
let identifiers = Identifiers::new();
let mut functions = Functions::new(); let mut functions = Functions::new();
let id = functions.next_id(); let id = functions.next_id();
let name = identifiers.get("Marty McFly"); let function0 = Function::new(id);
let function0 = Function::new(id, name);
let idx = functions.push(function0); let idx = functions.push(function0);
assert_eq!(usize::from(idx), 0); assert_eq!(usize::from(idx), 0);
let function1 = functions.get(idx).unwrap(); let function1 = functions.get(idx).unwrap();
assert_eq!(function1.id(), id); assert_eq!(function1.id(), id);
assert_eq!(function1.name(), identifiers.get("Marty McFly"));
} }
} }

View file

@ -3,11 +3,9 @@ mod clause;
mod clause_id; mod clause_id;
mod function_id; mod function_id;
mod functions; mod functions;
mod argument;
pub use actual::Function; pub use actual::Function;
pub use clause::Clause; pub use clause::Clause;
pub use clause_id::ClauseId; pub use clause_id::ClauseId;
pub use function_id::FunctionId; pub use function_id::FunctionId;
pub use functions::Functions; pub use functions::Functions;
pub use argument::Argument;

View file

@ -1 +1,12 @@
pub enum Instruction {
Noop = 0,
InvokePrimitive,
Pop,
PushFalse,
PushInteger,
PushLocal,
PushSelf,
PushTrue,
Return,
SetLocal,
}

View file

@ -1,17 +1,25 @@
mod class; mod argument;
mod constant; mod bootstrap;
mod classes;
mod context; mod context;
mod function; mod function;
mod identifier; mod identifier;
mod instructions; mod instructions;
mod property_type_map; mod method;
mod r#trait; mod object;
mod r#type; mod parse_consumer;
mod scope;
mod stack;
mod traits;
mod type_spec; mod type_spec;
mod types;
mod vtable;
pub use class::{Class, ClassId}; pub use argument::Argument;
pub use classes::Class;
pub use context::Context; pub use context::Context;
pub use identifier::Identifier; pub use identifier::Identifier;
pub use r#trait::{Trait, TraitId}; pub use object::Object;
pub use r#type::Type; pub use traits::Trait;
pub use type_spec::TypeSpec; pub use type_spec::TypeSpec;
pub use types::TypeId;

View file

@ -0,0 +1,50 @@
use crate::function::FunctionId;
use crate::identifier::Identifier;
#[derive(Debug, Clone)]
pub struct Method {
name: Identifier,
function: FunctionId,
flag: Flag,
}
#[derive(Debug, Copy, Clone)]
pub enum Flag {
Public,
Private,
Static,
}
impl Method {
pub fn new(name: Identifier, function: FunctionId, flag: Flag) -> Method {
Method {
name,
function,
flag,
}
}
pub fn name(&self) -> Identifier {
self.name
}
pub fn set_name(&mut self, name: Identifier) {
self.name = name;
}
pub fn function(&self) -> FunctionId {
self.function
}
pub fn set_function(&mut self, function: FunctionId) {
self.function = function
}
pub fn flag(&self) -> Flag {
self.flag
}
pub fn set_flag(&mut self, flag: Flag) {
self.flag = flag;
}
}

View file

@ -0,0 +1,14 @@
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct MethodId(usize);
impl From<MethodId> for usize {
fn from(data: MethodId) -> usize {
data.0
}
}
impl From<usize> for MethodId {
fn from(data: usize) -> MethodId {
MethodId(data)
}
}

View file

@ -0,0 +1,5 @@
mod actual;
mod method_id;
pub use actual::{Flag, Method};
pub use method_id::MethodId;

View file

@ -0,0 +1,94 @@
use crate::classes::Class;
use crate::types::TypeId;
use std::hash;
use string_interner::Sym;
use wrc::WRC;
#[derive(Debug, PartialOrd, Clone)]
pub struct Object(WRC<ObjectInner>);
#[derive(Debug, PartialEq, PartialOrd)]
struct ObjectInner {
type_id: TypeId,
value: ObjectValue,
}
#[derive(Debug, PartialEq, PartialOrd)]
pub enum ObjectValue {
Array(Vec<Object>),
Atom(Sym),
False,
Float(f64),
Integer(i64),
String(Sym),
True,
}
impl From<Vec<Object>> for ObjectValue {
fn from(data: Vec<Object>) -> ObjectValue {
ObjectValue::Array(data)
}
}
impl From<bool> for ObjectValue {
fn from(data: bool) -> ObjectValue {
if data {
ObjectValue::True
} else {
ObjectValue::False
}
}
}
impl From<f64> for ObjectValue {
fn from(data: f64) -> ObjectValue {
ObjectValue::Float(data)
}
}
impl From<i64> for ObjectValue {
fn from(data: i64) -> ObjectValue {
ObjectValue::Integer(data)
}
}
impl Object {
pub fn alloc(class: Class, data: ObjectValue) -> Object {
Object(WRC::new(ObjectInner {
type_id: class.id(),
value: data,
}))
}
pub fn type_id(&self) -> TypeId {
self.0.type_id
}
}
impl hash::Hash for Object {
fn hash<H: hash::Hasher>(&self, mut h: &mut H) {
self.0.type_id.hash(&mut h);
match &self.0.value {
ObjectValue::Array(objs) => {
for o in objs {
o.hash(&mut h)
}
}
ObjectValue::Atom(s) => s.hash(&mut h),
ObjectValue::False => false.hash(&mut h),
ObjectValue::Float(f) => {
let bitpattern = unsafe { std::mem::transmute::<f64, u64>(*f) };
bitpattern.hash(&mut h);
}
ObjectValue::Integer(i) => i.hash(&mut h),
ObjectValue::String(s) => s.hash(&mut h),
ObjectValue::True => true.hash(&mut h),
}
}
}
impl PartialEq for Object {
fn eq(&self, other: &Object) -> bool {
self.0.type_id == other.0.type_id && self.0.value == other.0.value
}
}

View file

@ -0,0 +1,56 @@
use crate::argument::Argument;
use crate::context::Context;
use crate::types::TypeId;
use huia_parser::ast::{Term, Value};
pub fn consume(context: &mut Context, term: &Term) -> DefinitionId {
let (deftype, defname, args, body, reqs) = term.definition().unwrap();
match deftype.value_ref().as_str() {
"type" => {
let name = context
.identifiers()
.get(defname.typename().unwrap().value_ref().as_str());
let class = context.ensure_class(name);
for (name, term) in args {
let name = context.ident(name.value_ref());
let mut argument = Argument::new(name);
println!("argument: {:?}", term);
class.add_property(argument);
}
DefinitionId::from(class.id())
}
_ => panic!("Unexpected define type {:?}", deftype),
}
}
#[derive(Debug, Copy, Clone)]
pub enum DefinitionId {
TypeId(TypeId),
}
impl From<TypeId> for DefinitionId {
fn from(id: TypeId) -> DefinitionId {
DefinitionId::TypeId(id)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn class_definition() {
let mut context = Context::new();
let terms = Term::input("type Delorean(speed: Integer)").unwrap();
consume(&mut context, &terms[0]);
let class = context
.types()
.find(context.ident("Delorean"))
.unwrap()
.as_class()
.unwrap();
assert!(class.has_property(context.ident("speed")))
}
}

View file

@ -0,0 +1,12 @@
use crate::argument::Argument;
use crate::context::Context;
use huia_parser::ast::{NodeType, Term, Value};
mod definition;
pub fn consume(mut context: &mut Context, term: &Term) {
match term.node_type() {
NodeType::Definition => definition::consume(&mut context, term),
_ => panic!("Unexpected node {:?}", term.node_type()),
};
}

View file

@ -1,44 +0,0 @@
use crate::identifier::Identifier;
use crate::type_spec::TypeSpec;
use std::collections::BTreeMap;
#[derive(Debug, Default)]
pub struct PropertyTypeMap(BTreeMap<Identifier, TypeSpec>);
impl PropertyTypeMap {
pub fn new() -> PropertyTypeMap {
PropertyTypeMap(BTreeMap::new())
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn insert(&mut self, name: Identifier, ts: TypeSpec) {
self.0.insert(name, ts);
}
pub fn has_property(&self, name: Identifier) -> bool {
self.0.contains_key(&name)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::context::Context;
#[test]
fn test() {
let mut context = Context::new();
let mut ptm = PropertyTypeMap::new();
assert!(ptm.is_empty());
let pname = context.identifiers().get("character");
let ptype = TypeSpec::from(context.new_trait("Character"));
ptm.insert(pname, ptype);
assert!(ptm.has_property(pname));
}
}

View file

@ -0,0 +1,32 @@
use crate::identifier::Identifier;
use crate::object::Object;
use std::sync::RwLock;
// Uses a vec of ident-object pairs to ensure that assignments are in SSA form.
#[derive(Debug, Default)]
pub struct Scope(RwLock<Vec<(Identifier, Object)>>);
impl Scope {
pub fn new() -> Scope {
Scope(RwLock::new(Vec::new()))
}
pub fn is_empty(&self) -> bool {
let scope = self.0.read().unwrap();
scope.is_empty()
}
pub fn set(&self, name: Identifier, value: Object) {
let mut scope = self.0.write().unwrap();
scope.push((name, value))
}
pub fn get(&self, name: Identifier) -> Option<Object> {
let scope = self.0.write().unwrap();
match scope.iter().rev().find(|(n, _)| n == &name) {
Some((_, o)) => Some(o.clone()),
None => None,
}
}
}

View file

@ -0,0 +1,23 @@
use std::fmt::Debug;
#[derive(Debug, Default)]
pub struct Stack<T: Debug + Default>(Vec<T>);
impl<T: Debug + Default> Stack<T> {
pub fn new() -> Stack<T> {
Stack(Vec::new())
}
pub fn push(&mut self) {
self.0.push(T::default())
}
pub fn pop(&mut self) -> Option<T> {
self.0.pop()
}
pub fn current(&self) -> &T {
let idx = self.0.len() - 1;
self.0.get(idx).unwrap()
}
}

View file

@ -1,99 +0,0 @@
use crate::identifier::Identifier;
use crate::r#trait::TraitId;
use crate::r#type::Type;
use crate::type_spec::TypeSpec;
use std::sync::RwLock;
use wrc::WRC;
#[derive(Debug, Clone)]
pub struct Trait(WRC<RwLock<TraitInner>>);
#[derive(Debug)]
pub struct TraitInner {
id: TraitId,
name: Identifier,
requires: TypeSpec,
}
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 {
let requires = TypeSpec::new();
Trait(WRC::new(RwLock::new(TraitInner { id, name, requires })))
}
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);
}
pub fn require<T: Into<Type>>(&self, r#type: T) {
let ty: Type = r#type.into();
let mut tr = self.0.write().unwrap();
tr.requires.push(ty);
}
pub fn requires<T: Into<Type>>(&self, r#type: T) -> bool {
let ty: Type = r#type.into();
let tr = self.0.read().unwrap();
tr.requires.matches(ty)
}
}
impl PartialEq for Trait {
fn eq(&self, other: &Trait) -> bool {
self.id() == other.id()
}
}
#[cfg(test)]
mod test {
use crate::context::Context;
#[test]
fn set_name() {
let mut context = Context::new();
let tr = context.new_trait("Marty McFly");
assert_eq!(tr.name(), context.identifiers().get("Marty McFly"));
tr.set_name(context.identifiers().get("Doc Brown"));
assert_eq!(tr.name(), context.identifiers().get("Doc Brown"));
}
#[test]
fn requires() {
let mut context = Context::new();
let tr0 = context.new_trait("Marty McFly");
let tr1 = context.new_trait("Doc Brown");
let cl0 = context.new_class("Einstein Brown");
tr0.require(tr1.id());
tr0.require(cl0.id());
assert!(tr0.requires(tr1));
assert!(tr0.requires(cl0));
}
}

View file

@ -1,6 +0,0 @@
mod actual;
mod trait_id;
mod traits;
pub use actual::Trait;
pub use trait_id::TraitId;
pub use traits::Traits;

View file

@ -1,14 +0,0 @@
#[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)
}
}

View file

@ -1,70 +0,0 @@
use crate::identifier::Identifier;
use crate::r#trait::{Trait, TraitId};
use std::sync::RwLock;
#[derive(Default, Debug)]
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(usize::from(idx)) {
Some(tr) => Some(tr.clone()),
None => None,
}
}
pub fn next_id(&self) -> TraitId {
let elements = self.0.read().unwrap();
TraitId::from(elements.len())
}
pub fn find(&self, name: Identifier) -> Option<TraitId> {
let elements = self.0.read().unwrap();
let tr = elements.iter().find(|tr| tr.name() == name);
match tr {
Some(tr) => Some(tr.id()),
None => None,
}
}
pub fn is_empty(&self) -> bool {
let elements = self.0.read().unwrap();
elements.is_empty()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::identifier::Identifiers;
#[test]
fn test() {
let 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!(usize::from(idx), 0);
let trait1 = traits.get(idx).unwrap();
assert_eq!(trait1.id(), id);
assert_eq!(trait1.name(), identifiers.get("Marty McFly"));
}
}

View file

@ -0,0 +1,123 @@
use crate::identifier::Identifier;
use crate::method::{Method, MethodId};
use crate::type_spec::TypeSpec;
use crate::types::TypeId;
use crate::vtable::VTable;
use std::sync::RwLock;
use wrc::WRC;
#[derive(Debug, Clone)]
pub struct Trait(WRC<RwLock<TraitInner>>);
#[derive(Debug)]
pub struct TraitInner {
id: TypeId,
name: Identifier,
requires: TypeSpec,
vtable: VTable,
}
impl TraitInner {
fn id(&self) -> TypeId {
self.id
}
fn name(&self) -> Identifier {
self.name
}
fn set_name(&mut self, name: Identifier) {
self.name = name
}
fn add_method(&mut self, method: Method) -> MethodId {
self.vtable.add_method(method)
}
fn next_id(&self) -> MethodId {
self.vtable.next_id()
}
}
impl Trait {
pub fn new(id: TypeId, name: Identifier) -> Trait {
let requires = TypeSpec::new();
let vtable = VTable::new();
Trait(WRC::new(RwLock::new(TraitInner {
id,
name,
requires,
vtable,
})))
}
pub fn id(&self) -> TypeId {
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);
}
pub fn require(&self, ty: TypeId) {
let mut tr = self.0.write().unwrap();
tr.requires.push(ty);
}
pub fn requires<T: Into<TypeId>>(&self, ty: T) -> bool {
let tr = self.0.read().unwrap();
tr.requires.matches(ty.into())
}
pub fn add_method(&self, method: Method) -> MethodId {
let mut tr = self.0.write().unwrap();
tr.add_method(method)
}
pub fn next_id(&self) -> MethodId {
let tr = self.0.read().unwrap();
tr.next_id()
}
}
impl PartialEq for Trait {
fn eq(&self, other: &Trait) -> bool {
self.id() == other.id()
}
}
#[cfg(test)]
mod test {
use crate::context::Context;
#[test]
fn set_name() {
let mut context = Context::new();
let tr = context.ensure_trait(context.ident("Marty McFly"));
assert_eq!(tr.name(), context.ident("Marty McFly"));
tr.set_name(context.ident("Doc Brown"));
assert_eq!(tr.name(), context.ident("Doc Brown"));
}
#[test]
fn requires() {
let mut context = Context::new();
let tr0 = context.ensure_trait(context.ident("Marty McFly"));
let tr1 = context.ensure_trait(context.ident("Doc Brown"));
let cl0 = context.ensure_class(context.ident("Einstein Brown"));
tr0.require(tr1.id());
tr0.require(cl0.id());
assert!(tr0.requires(tr1));
assert!(tr0.requires(cl0));
}
}

View file

@ -0,0 +1,2 @@
mod actual;
pub use actual::Trait;

View file

@ -1,80 +0,0 @@
use crate::class::{Class, ClassId};
use crate::r#trait::{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),
_ => None,
}
}
pub fn trait_id(&self) -> Option<TraitId> {
match self {
Type::Trait(id) => Some(*id),
_ => 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)
}
}
impl From<Class> for Type {
fn from(class: Class) -> Type {
Type::Class(class.id())
}
}
impl From<Trait> for Type {
fn from(tr: Trait) -> Type {
Type::Trait(tr.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

@ -1,45 +1,27 @@
use crate::r#type::Type; use crate::types::TypeId;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct TypeSpec(Vec<Type>); pub struct TypeSpec(Vec<TypeId>);
impl TypeSpec { impl TypeSpec {
pub fn new() -> TypeSpec { pub fn new() -> TypeSpec {
TypeSpec(Vec::new()) TypeSpec(Vec::new())
} }
pub fn push(&mut self, ty: Type) { pub fn push(&mut self, ty: TypeId) {
self.0.push(ty) self.0.push(ty)
} }
pub fn matches(&self, ty: Type) -> bool { pub fn matches(&self, ty: TypeId) -> bool {
self.0.iter().any(|i| i == &ty) self.0.iter().any(|i| i == &ty)
} }
} }
impl<T: Into<Type>> From<T> for TypeSpec { impl<T: Into<TypeId>> From<T> for TypeSpec {
fn from(ty: T) -> TypeSpec { fn from(ty: T) -> TypeSpec {
let ty: Type = ty.into(); let ty: TypeId = ty.into();
let mut ts = TypeSpec::new(); let mut ts = TypeSpec::new();
ts.push(ty); ts.push(ty);
ts ts
} }
} }
#[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

@ -0,0 +1,112 @@
use crate::classes::Class;
use crate::identifier::Identifier;
use crate::traits::Trait;
use crate::types::TypeId;
#[derive(Debug, Clone)]
pub enum Type {
Class(Class),
Trait(Trait),
}
impl Type {
pub fn new<T: Into<Type>>(inner: T) -> Type {
inner.into()
}
pub fn id(&self) -> TypeId {
match self {
Type::Class(t) => t.id(),
Type::Trait(t) => t.id(),
}
}
pub fn name(&self) -> Identifier {
match self {
Type::Class(t) => t.name(),
Type::Trait(t) => t.name(),
}
}
pub fn as_class(&self) -> Option<Class> {
match self {
Type::Class(t) => Some(t.clone()),
_ => None,
}
}
pub fn as_trait(&self) -> Option<Trait> {
match self {
Type::Trait(t) => Some(t.clone()),
_ => None,
}
}
pub fn is_class(&self) -> bool {
match self {
Type::Class(_) => true,
_ => false,
}
}
pub fn is_trait(&self) -> bool {
match self {
Type::Trait(_) => true,
_ => false,
}
}
}
impl From<Class> for Type {
fn from(class: Class) -> Type {
Type::Class(class)
}
}
impl From<Trait> for Type {
fn from(tr: Trait) -> Type {
Type::Trait(tr)
}
}
impl PartialEq for Type {
fn eq(&self, other: &Type) -> bool {
self.id() == other.id()
}
}
impl PartialEq<Class> for Type {
fn eq(&self, other: &Class) -> bool {
match self {
Type::Class(c) => c.id() == other.id(),
_ => false,
}
}
}
impl PartialEq<Trait> for Type {
fn eq(&self, other: &Trait) -> bool {
match self {
Type::Trait(c) => c.id() == other.id(),
_ => false,
}
}
}
impl PartialEq<Type> for Trait {
fn eq(&self, other: &Type) -> bool {
match other {
Type::Trait(c) => c.id() == self.id(),
_ => false,
}
}
}
impl PartialEq<Type> for Class {
fn eq(&self, other: &Type) -> bool {
match other {
Type::Class(c) => c.id() == self.id(),
_ => false,
}
}
}

View file

@ -0,0 +1,6 @@
mod actual;
mod type_id;
mod table;
pub use actual::Type;
pub use type_id::TypeId;
pub use table::TypeTable;

View file

@ -0,0 +1,45 @@
use crate::identifier::Identifier;
use crate::types::{Type, TypeId};
use std::sync::RwLock;
#[derive(Default, Debug)]
pub struct TypeTable(RwLock<Vec<Type>>);
impl TypeTable {
pub fn new() -> TypeTable {
TypeTable(RwLock::new(Vec::new()))
}
pub fn push<T: Into<Type>>(&self, ty: T) -> TypeId {
let mut elements = self.0.write().unwrap();
let ty: Type = ty.into();
elements.push(ty.clone());
ty.id()
}
pub fn get(&self, idx: TypeId) -> Option<Type> {
let elements = self.0.read().unwrap();
match elements.get(usize::from(idx)) {
Some(ty) => Some(ty.clone()),
None => None,
}
}
pub fn next_id(&self) -> TypeId {
let elements = self.0.read().unwrap();
TypeId::from(elements.len())
}
pub fn find(&self, name: Identifier) -> Option<Type> {
let elements = self.0.read().unwrap();
match elements.iter().find(|ty| ty.name() == name) {
Some(ty) => Some(ty.clone()),
None => None,
}
}
pub fn is_empty(&self) -> bool {
let elements = self.0.read().unwrap();
elements.is_empty()
}
}

View file

@ -0,0 +1,29 @@
use crate::classes::Class;
use crate::traits::Trait;
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct TypeId(usize);
impl From<Class> for TypeId {
fn from(cl: Class) -> TypeId {
cl.id()
}
}
impl From<Trait> for TypeId {
fn from(tr: Trait) -> TypeId {
tr.id()
}
}
impl From<TypeId> for usize {
fn from(id: TypeId) -> usize {
id.0
}
}
impl From<usize> for TypeId {
fn from(id: usize) -> TypeId {
TypeId(id)
}
}

View file

@ -0,0 +1,31 @@
use crate::method::{Method, MethodId};
#[derive(Debug, Default)]
pub struct VTable(Vec<Method>);
impl VTable {
pub fn new() -> VTable {
VTable(Vec::new())
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn add_method(&mut self, method: Method) -> MethodId {
let idx = self.0.len();
self.0.push(method);
MethodId::from(idx)
}
pub fn get(&self, idx: MethodId) -> Option<Method> {
match self.0.get(usize::from(idx)) {
Some(method) => Some(method.clone()),
None => None,
}
}
pub fn next_id(&self) -> MethodId {
MethodId::from(self.0.len())
}
}

View file

@ -55,6 +55,6 @@ mod test {
.next() .next()
.unwrap(); .unwrap();
let float = Float::from(pair); let float = Float::from(pair);
assert_eq!(float.value(), 123.456); assert!(float.value() - 123.456 < std::f64::EPSILON);
} }
} }

View file

@ -1,25 +1,25 @@
mod atom; mod atom;
mod binary; mod binary;
mod boolean; mod boolean;
mod constant;
mod float; mod float;
mod identifier; mod identifier;
mod integer; mod integer;
mod local; mod local;
mod string; mod string;
mod term; mod term;
mod typename;
mod unary; mod unary;
pub use atom::Atom; pub use atom::Atom;
pub use binary::Binary; pub use binary::Binary;
pub use boolean::Boolean; pub use boolean::Boolean;
pub use constant::Constant;
pub use float::Float; pub use float::Float;
pub use identifier::Identifier; pub use identifier::Identifier;
pub use integer::Integer; pub use integer::Integer;
pub use local::Local; pub use local::Local;
pub use string::String; pub use string::String;
pub use term::{NodeType, Term}; pub use term::{NodeType, Term};
pub use typename::Type;
pub use unary::Unary; pub use unary::Unary;
use crate::input_location::InputLocation; use crate::input_location::InputLocation;

View file

@ -23,7 +23,7 @@ pub enum NodeType {
Binary, Binary,
Boolean, Boolean,
Call, Call,
Constant, Type,
Constructor, Constructor,
Declaration, Declaration,
Definition, Definition,
@ -43,8 +43,8 @@ enum Inner {
Binary(Binary, Box<Term>, Box<Term>), Binary(Binary, Box<Term>, Box<Term>),
Boolean(Boolean), Boolean(Boolean),
Call(Identifier, Vec<Term>), Call(Identifier, Vec<Term>),
Constant(Constant), Type(Type),
Constructor(Constant, Vec<(Identifier, Term)>), Constructor(Type, Vec<(Identifier, Term)>),
Declaration(Identifier, Box<Term>), Declaration(Identifier, Box<Term>),
Definition( Definition(
Identifier, Identifier,
@ -68,9 +68,8 @@ impl Term {
match result { match result {
Ok(pairs) => { Ok(pairs) => {
let terms: Vec<Term> = pairs let terms: Vec<Term> = pairs
.into_iter()
.take_while(|pair| pair.as_rule() != Rule::EOI) .take_while(|pair| pair.as_rule() != Rule::EOI)
.map(|pair| Term::from(pair)) .map(Term::from)
.collect(); .collect();
Ok(terms) Ok(terms)
} }
@ -92,7 +91,7 @@ impl Term {
Inner::Boolean(_) => NodeType::Boolean, Inner::Boolean(_) => NodeType::Boolean,
Inner::Binary(_, _, _) => NodeType::Binary, Inner::Binary(_, _, _) => NodeType::Binary,
Inner::Call(_, _) => NodeType::Call, Inner::Call(_, _) => NodeType::Call,
Inner::Constant(_) => NodeType::Constant, Inner::Type(_) => NodeType::Type,
Inner::Constructor(_, _) => NodeType::Constructor, Inner::Constructor(_, _) => NodeType::Constructor,
Inner::Definition(_, _, _, _, _) => NodeType::Definition, Inner::Definition(_, _, _, _, _) => NodeType::Definition,
Inner::Declaration(_, _) => NodeType::Declaration, Inner::Declaration(_, _) => NodeType::Declaration,
@ -141,16 +140,16 @@ impl Term {
} }
} }
pub fn constant(&self) -> Option<&Constant> { pub fn typename(&self) -> Option<&Type> {
match self.inner { match self.inner {
Inner::Constant(ref node) => Some(node), Inner::Type(ref node) => Some(node),
_ => None, _ => None,
} }
} }
pub fn constructor(&self) -> Option<(&Constant, &Vec<(Identifier, Term)>)> { pub fn constructor(&self) -> Option<(&Type, &Vec<(Identifier, Term)>)> {
match self.inner { match self.inner {
Inner::Constructor(ref constant, ref properties) => Some((constant, properties)), Inner::Constructor(ref typename, ref properties) => Some((typename, properties)),
_ => None, _ => None,
} }
} }
@ -243,7 +242,7 @@ impl<'a> From<Pair<'a, Rule>> for Term {
Rule::array => { Rule::array => {
let mut result = Vec::new(); let mut result = Vec::new();
for element in pair.clone().into_inner().into_iter() { for element in pair.clone().into_inner() {
result.push(Term::from(element)); result.push(Term::from(element));
} }
@ -264,7 +263,7 @@ impl<'a> From<Pair<'a, Rule>> for Term {
let mut inner = pair.clone().into_inner(); let mut inner = pair.clone().into_inner();
let name = Identifier::from(inner.next().unwrap()); let name = Identifier::from(inner.next().unwrap());
let mut args = Vec::new(); let mut args = Vec::new();
for argument in inner.into_iter() { for argument in inner {
match argument.as_rule() { match argument.as_rule() {
Rule::call_argument => { Rule::call_argument => {
args.push(Term::from(argument.into_inner().next().unwrap())) args.push(Term::from(argument.into_inner().next().unwrap()))
@ -277,16 +276,16 @@ impl<'a> From<Pair<'a, Rule>> for Term {
inner: Inner::Call(name, args), inner: Inner::Call(name, args),
} }
} }
Rule::constant => Term { Rule::typename => Term {
location: InputLocation::from(pair.clone()), location: InputLocation::from(pair.clone()),
inner: Inner::Constant(Constant::from(pair)), inner: Inner::Type(Type::from(pair)),
}, },
Rule::constructor => { Rule::constructor => {
let mut inner = pair.clone().into_inner(); let mut inner = pair.clone().into_inner();
let constant = Constant::from(inner.next().unwrap()); let typename = Type::from(inner.next().unwrap());
let mut properties = Vec::new(); let mut properties = Vec::new();
for property in inner.into_iter() { for property in inner {
match property.as_rule() { match property.as_rule() {
Rule::constructor_property => { Rule::constructor_property => {
let mut proppairs = property.into_inner(); let mut proppairs = property.into_inner();
@ -300,7 +299,7 @@ impl<'a> From<Pair<'a, Rule>> for Term {
Term { Term {
location: InputLocation::from(pair), location: InputLocation::from(pair),
inner: Inner::Constructor(constant, properties), inner: Inner::Constructor(typename, properties),
} }
} }
Rule::declaration => { Rule::declaration => {
@ -329,49 +328,43 @@ impl<'a> From<Pair<'a, Rule>> for Term {
let mut typeargs = Vec::new(); let mut typeargs = Vec::new();
match typeargspair.next() { if let Some(arguments) = typeargspair.next() {
Some(arguments) => { for argument in arguments.into_inner() {
for argument in arguments.into_inner().into_iter() {
let mut argument = argument.into_inner(); let mut argument = argument.into_inner();
let argname = Identifier::from(argument.next().unwrap()); let argname = Identifier::from(argument.next().unwrap());
let argvalue = Term::from(argument.next().unwrap()); let argvalue = Term::from(argument.next().unwrap());
typeargs.push((argname, argvalue)); typeargs.push((argname, argvalue));
} }
} }
None => (),
}
let mut requirements = Vec::new(); let mut requirements = Vec::new();
match typeargspair.next() { if let Some(requirement) = typeargspair.next() {
Some(requirement) => match requirement.as_rule() { match requirement.as_rule() {
Rule::definition_requirement => { Rule::definition_requirement => {
for constant in requirement.clone().into_inner().into_iter() { for typename in requirement.clone().into_inner() {
let constant = Term::from(constant); let typename = Term::from(typename);
requirements.push(constant); requirements.push(typename);
} }
} }
_ => unreachable!("Expected pair to be a Requirement"), _ => unreachable!("Expected pair to be a Requirement"),
}, }
None => (), }
};
let mut bodyargs = Vec::new(); let mut bodyargs = Vec::new();
match inner.next() { if let Some(arguments) = inner.next() {
Some(arguments) => { for argument in arguments.into_inner() {
for argument in arguments.into_inner().into_iter() {
let mut arg_inner = argument.into_inner(); let mut arg_inner = argument.into_inner();
let argname = Identifier::from(arg_inner.next().unwrap()); let argname = Identifier::from(arg_inner.next().unwrap());
let mut body: Vec<Term> = vec![]; let mut body: Vec<Term> = vec![];
for argvalue in arg_inner.into_iter() { for argvalue in arg_inner {
body.push(Term::from(argvalue)); body.push(Term::from(argvalue));
} }
bodyargs.push((argname, body)); bodyargs.push((argname, body));
} }
} }
None => (),
}
Term { Term {
location: InputLocation::from(pair), location: InputLocation::from(pair),
inner: Inner::Definition( inner: Inner::Definition(
@ -399,7 +392,7 @@ impl<'a> From<Pair<'a, Rule>> for Term {
Rule::map => { Rule::map => {
let mut contents = Vec::new(); let mut contents = Vec::new();
for map_pair in pair.clone().into_inner().into_iter() { for map_pair in pair.clone().into_inner() {
let mut inner = map_pair.into_inner(); let mut inner = map_pair.into_inner();
let keypair = inner.next().unwrap(); let keypair = inner.next().unwrap();
let key = match keypair.as_rule() { let key = match keypair.as_rule() {
@ -424,7 +417,7 @@ impl<'a> From<Pair<'a, Rule>> for Term {
let mut call = inner.next().unwrap().into_inner(); let mut call = inner.next().unwrap().into_inner();
let name = Identifier::from(call.next().unwrap()); let name = Identifier::from(call.next().unwrap());
let mut args = Vec::new(); let mut args = Vec::new();
for argument in call.into_iter() { for argument in call {
match argument.as_rule() { match argument.as_rule() {
Rule::call_argument => { Rule::call_argument => {
args.push(Term::from(argument.into_inner().next().unwrap())) args.push(Term::from(argument.into_inner().next().unwrap()))
@ -541,8 +534,8 @@ mod test {
#[test] #[test]
fn test_constant() { fn test_constant() {
let terms = Term::input("Marty").unwrap(); let terms = Term::input("Marty").unwrap();
assert_eq!(terms[0].node_type(), NodeType::Constant); assert_eq!(terms[0].node_type(), NodeType::Type);
let term = terms[0].constant().unwrap().clone(); let term = terms[0].typename().unwrap().clone();
assert_eq!(term.value(), "Marty"); assert_eq!(term.value(), "Marty");
} }
@ -550,16 +543,16 @@ mod test {
fn test_constructor_empty() { fn test_constructor_empty() {
let terms = Term::input("Character {}").unwrap(); let terms = Term::input("Character {}").unwrap();
assert_eq!(terms[0].node_type(), NodeType::Constructor); assert_eq!(terms[0].node_type(), NodeType::Constructor);
let (constant, properties) = terms[0].constructor().unwrap(); let (typename, properties) = terms[0].constructor().unwrap();
assert_eq!(constant.value_ref(), "Character"); assert_eq!(typename.value_ref(), "Character");
assert_eq!(properties.len(), 0); assert_eq!(properties.len(), 0);
} }
#[test] #[test]
fn test_constructor() { fn test_constructor() {
let terms = Term::input("Character { name: \"Marty McFly\" }").unwrap(); let terms = Term::input("Character { name: \"Marty McFly\" }").unwrap();
let (constant, properties) = terms[0].constructor().unwrap(); let (typename, properties) = terms[0].constructor().unwrap();
assert_eq!(constant.value_ref(), "Character"); assert_eq!(typename.value_ref(), "Character");
assert_eq!(properties.len(), 1); assert_eq!(properties.len(), 1);
let (key, value) = &properties[0]; let (key, value) = &properties[0];
assert_eq!(key.value_ref(), "name"); assert_eq!(key.value_ref(), "name");
@ -571,13 +564,13 @@ mod test {
let terms = Term::input("type Delorean(speed: Integer) do\n123\n\n456\nend").unwrap(); let terms = Term::input("type Delorean(speed: Integer) do\n123\n\n456\nend").unwrap();
assert_eq!(terms[0].node_type(), NodeType::Definition); assert_eq!(terms[0].node_type(), NodeType::Definition);
let (deftype, defname, args, body, _reqs) = terms[0].definition().unwrap().clone(); let (deftype, defname, args, body, _reqs) = terms[0].definition().unwrap();
assert_eq!(deftype.value_ref(), "type"); assert_eq!(deftype.value_ref(), "type");
assert_eq!(defname.constant().unwrap().value_ref(), "Delorean"); assert_eq!(defname.typename().unwrap().value_ref(), "Delorean");
let (argname, argvalue) = &args[0]; let (argname, argvalue) = &args[0];
assert_eq!(argname.value_ref(), "speed"); assert_eq!(argname.value_ref(), "speed");
assert_eq!(argvalue.constant().unwrap().value_ref(), "Integer"); assert_eq!(argvalue.typename().unwrap().value_ref(), "Integer");
let (argname, argvalues) = &body[0]; let (argname, argvalues) = &body[0];
assert_eq!(argname.value_ref(), "do"); assert_eq!(argname.value_ref(), "do");
@ -589,9 +582,9 @@ mod test {
#[test] #[test]
fn test_definition_empty() { fn test_definition_empty() {
let terms = Term::input("type Delorean").unwrap(); let terms = Term::input("type Delorean").unwrap();
let (deftype, defname, args, body, _reqs) = terms[0].definition().unwrap().clone(); let (deftype, defname, args, body, _reqs) = terms[0].definition().unwrap();
assert_eq!(deftype.value_ref(), "type"); assert_eq!(deftype.value_ref(), "type");
assert_eq!(defname.constant().unwrap().value_ref(), "Delorean"); assert_eq!(defname.typename().unwrap().value_ref(), "Delorean");
assert_eq!(args.len(), 0); assert_eq!(args.len(), 0);
assert_eq!(body.len(), 0); assert_eq!(body.len(), 0);
} }
@ -599,7 +592,7 @@ mod test {
#[test] #[test]
fn test_definition_empty_fun() { fn test_definition_empty_fun() {
let terms = Term::input("def hello()").unwrap(); let terms = Term::input("def hello()").unwrap();
let (deftype, defname, args, body, _reqs) = terms[0].definition().unwrap().clone(); let (deftype, defname, args, body, _reqs) = terms[0].definition().unwrap();
assert_eq!(deftype.value_ref(), "def"); assert_eq!(deftype.value_ref(), "def");
assert_eq!(defname.atom().unwrap().value_ref(), "hello"); assert_eq!(defname.atom().unwrap().value_ref(), "hello");
assert_eq!(args.len(), 0); assert_eq!(args.len(), 0);
@ -609,7 +602,7 @@ mod test {
#[test] #[test]
fn test_definition_fun() { fn test_definition_fun() {
let terms = Term::input("def example(a: Integer, b: Atom), do: 123").unwrap(); let terms = Term::input("def example(a: Integer, b: Atom), do: 123").unwrap();
let (deftype, defname, args, body, _reqs) = terms[0].definition().unwrap().clone(); let (deftype, defname, args, body, _reqs) = terms[0].definition().unwrap();
assert_eq!(deftype.value_ref(), "def"); assert_eq!(deftype.value_ref(), "def");
assert_eq!(defname.atom().unwrap().value_ref(), "example"); assert_eq!(defname.atom().unwrap().value_ref(), "example");
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
@ -619,27 +612,27 @@ mod test {
#[test] #[test]
fn test_definition_fun_w_return_type() { fn test_definition_fun_w_return_type() {
let terms = Term::input("def example(a: Integer, b: Atom): Integer, do: 123").unwrap(); let terms = Term::input("def example(a: Integer, b: Atom): Integer, do: 123").unwrap();
let (deftype, defname, args, body, reqs) = terms[0].definition().unwrap().clone(); let (deftype, defname, args, body, reqs) = terms[0].definition().unwrap();
assert_eq!(deftype.value_ref(), "def"); assert_eq!(deftype.value_ref(), "def");
assert_eq!(defname.atom().unwrap().value_ref(), "example"); assert_eq!(defname.atom().unwrap().value_ref(), "example");
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert_eq!(body.len(), 1); assert_eq!(body.len(), 1);
assert_eq!(reqs[0].constant().unwrap().value_ref(), "Integer"); assert_eq!(reqs[0].typename().unwrap().value_ref(), "Integer");
} }
#[test] #[test]
fn test_definition_trait_with_bounds() { fn test_definition_trait_with_bounds() {
let terms = Term::input("trait Integer: Add + Subtract + Divide + Multiply").unwrap(); let terms = Term::input("trait Integer: Add + Subtract + Divide + Multiply").unwrap();
let (deftype, defname, args, body, reqs) = terms[0].definition().unwrap().clone(); let (deftype, defname, args, body, reqs) = terms[0].definition().unwrap();
assert_eq!(deftype.value_ref(), "trait"); assert_eq!(deftype.value_ref(), "trait");
assert_eq!(defname.constant().unwrap().value_ref(), "Integer"); assert_eq!(defname.typename().unwrap().value_ref(), "Integer");
assert_eq!(args.len(), 0); assert_eq!(args.len(), 0);
assert_eq!(body.len(), 0); assert_eq!(body.len(), 0);
assert_eq!(reqs.len(), 4); assert_eq!(reqs.len(), 4);
assert_eq!(reqs[0].constant().unwrap().value_ref(), "Add"); assert_eq!(reqs[0].typename().unwrap().value_ref(), "Add");
assert_eq!(reqs[1].constant().unwrap().value_ref(), "Subtract"); assert_eq!(reqs[1].typename().unwrap().value_ref(), "Subtract");
assert_eq!(reqs[2].constant().unwrap().value_ref(), "Divide"); assert_eq!(reqs[2].typename().unwrap().value_ref(), "Divide");
assert_eq!(reqs[3].constant().unwrap().value_ref(), "Multiply"); assert_eq!(reqs[3].typename().unwrap().value_ref(), "Multiply");
} }
#[test] #[test]
@ -658,7 +651,7 @@ mod test {
let terms = Term::input("1.23").unwrap(); let terms = Term::input("1.23").unwrap();
assert_eq!(terms[0].node_type(), NodeType::Float); assert_eq!(terms[0].node_type(), NodeType::Float);
let node = terms[0].float().unwrap(); let node = terms[0].float().unwrap();
assert_eq!(node.value_ref(), &1.23); assert!(node.value_ref() - 1.23 < std::f64::EPSILON);
} }
#[test] #[test]
@ -760,7 +753,7 @@ mod test {
let terms = Term::input("My.Greeter.hello()").unwrap(); let terms = Term::input("My.Greeter.hello()").unwrap();
let (method_name, receiver, arguments) = terms[0].method_call().unwrap(); let (method_name, receiver, arguments) = terms[0].method_call().unwrap();
assert_eq!(method_name.value_ref(), "hello"); assert_eq!(method_name.value_ref(), "hello");
assert_eq!(receiver.constant().unwrap().value_ref(), "My.Greeter"); assert_eq!(receiver.typename().unwrap().value_ref(), "My.Greeter");
assert_eq!(arguments.len(), 0); assert_eq!(arguments.len(), 0);
} }

View file

@ -4,18 +4,18 @@ use crate::input_location::InputLocation;
use pest::iterators::Pair; use pest::iterators::Pair;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Constant { pub struct Type {
value: String, value: String,
location: InputLocation, location: InputLocation,
} }
impl Constant { impl Type {
pub fn value(&self) -> &str { pub fn value(&self) -> &str {
&self.value &self.value
} }
} }
impl Value for Constant { impl Value for Type {
type Item = String; type Item = String;
fn value(self) -> Self::Item { fn value(self) -> Self::Item {
@ -27,23 +27,23 @@ impl Value for Constant {
} }
} }
impl Location for Constant { impl Location for Type {
fn location(&self) -> &InputLocation { fn location(&self) -> &InputLocation {
&self.location &self.location
} }
} }
impl<'a> From<Pair<'a, Rule>> for Constant { impl<'a> From<Pair<'a, Rule>> for Type {
fn from(pair: Pair<'a, Rule>) -> Self { fn from(pair: Pair<'a, Rule>) -> Self {
match pair.as_rule() { match pair.as_rule() {
Rule::constant => { Rule::typename => {
let value = pair.clone().into_span().as_str().to_string(); let value = pair.clone().into_span().as_str().to_string();
Constant { Type {
value: value, value: value,
location: InputLocation::from(pair.into_span()), location: InputLocation::from(pair.into_span()),
} }
} }
_ => unreachable!("Expected pair to be an Constant"), _ => unreachable!("Expected pair to be an Type"),
} }
} }
} }
@ -56,11 +56,11 @@ mod test {
#[test] #[test]
fn it_parses() { fn it_parses() {
let pair = Grammar::parse(Rule::constant, "Marty.McFly") let pair = Grammar::parse(Rule::typename, "Marty.McFly")
.unwrap() .unwrap()
.next() .next()
.unwrap(); .unwrap();
let constant = Constant::from(pair); let r#type = Type::from(pair);
assert_eq!(constant.value(), "Marty.McFly"); assert_eq!(r#type.value(), "Marty.McFly");
} }
} }

View file

@ -20,23 +20,23 @@ call_arguments = _{ "(" ~ (call_argument ~ ("," ~ call_argument)* )? ~ ")" }
call_argument = { expression } call_argument = { expression }
definition = { ident ~ definition_what ~ arguments } definition = { ident ~ definition_what ~ arguments }
definition_what = { (ident | constant) ~ definition_arguments ~ definition_requirement_opt } definition_what = { (ident | typename) ~ definition_arguments ~ definition_requirement_opt }
definition_arguments = { ("(" ~ (definition_argument ~ ("," ~ definition_argument)* )? ~ ")")? } definition_arguments = { ("(" ~ (definition_argument ~ ("," ~ definition_argument)* )? ~ ")")? }
definition_requirement_opt = _{ (":" ~ definition_requirement)? } definition_requirement_opt = _{ (":" ~ definition_requirement)? }
definition_requirement = { constant ~ ("+" ~ constant)* } definition_requirement = { typename ~ ("+" ~ typename)* }
definition_argument = { keyword ~ constant } definition_argument = { keyword ~ typename }
arguments = { argument* } arguments = { argument* }
argument = { argument_block | argument_short } argument = { argument_block | argument_short }
argument_block = _{ ident ~ expression* ~ "end" } argument_block = _{ ident ~ expression* ~ "end" }
argument_short = _{ "," ~ keyword ~ expression } argument_short = _{ "," ~ keyword ~ expression }
literal = _{ constructor | map | array | constant | string | atom | float | integer | boolean } literal = _{ constructor | map | array | typename | string | atom | float | integer | boolean }
ident = @{ !reserved ~ 'a'..'z' ~ ('a'..'z' | 'A'..'Z' | "_")* } ident = @{ !reserved ~ 'a'..'z' ~ ('a'..'z' | 'A'..'Z' | "_")* }
keyword = @{ ident ~ ":" } keyword = @{ ident ~ ":" }
constructor = { constant ~ "{" ~ (constructor_property ~ ("," ~ constructor_property)*)? ~ "}" } constructor = { typename ~ "{" ~ (constructor_property ~ ("," ~ constructor_property)*)? ~ "}" }
constructor_property = { keyword ~ expression } constructor_property = { keyword ~ expression }
map = { "{" ~ (map_pair ~ ("," ~ map_pair)*)? ~ "}" } map = { "{" ~ (map_pair ~ ("," ~ map_pair)*)? ~ "}" }
@ -46,8 +46,8 @@ array = { "[" ~ (expression ~ ("," ~ expression)*)? ~ "]" }
atom = @{ ":" ~ ident } atom = @{ ":" ~ ident }
constant = @{ constant_name ~ ("." ~ constant_name)* } typename = @{ typename_name ~ ("." ~ typename_name)* }
constant_name = @{ 'A'..'Z' ~ ('a'..'z' | 'A'..'Z' | "_")* } typename_name = @{ 'A'..'Z' ~ ('a'..'z' | 'A'..'Z' | "_")* }
float = ${ float_characteristic ~ "." ~ float_mantissa } float = ${ float_characteristic ~ "." ~ float_mantissa }
float_characteristic = { "0" | (('1'..'9') ~ ('0'..'9' | "_")*) } float_characteristic = { "0" | (('1'..'9') ~ ('0'..'9' | "_")*) }

View file

@ -33,11 +33,11 @@ fn build_precedence_climber() -> PrecClimber<Rule> {
]) ])
} }
fn build_binary<'a>(lhs: Term, op: Pair<'a, Rule>, rhs: Term) -> Term { fn build_binary(lhs: Term, op: Pair<'_, Rule>, rhs: Term) -> Term {
let binary = Binary::from(op); let binary = Binary::from(op);
Term::create_infix(binary, lhs, rhs) Term::create_infix(binary, lhs, rhs)
} }
pub fn climb<'a>(pair: Pair<'a, Rule>) -> Term { pub fn climb(pair: Pair<'_, Rule>) -> Term {
PREC_CLIMBER.climb(pair.into_inner(), Term::from, build_binary) PREC_CLIMBER.climb(pair.into_inner(), Term::from, build_binary)
} }