Another attempt.

This commit is contained in:
James Harton 2019-02-14 21:07:17 +13:00
parent 7277510a72
commit b07a3ce8ef
8 changed files with 348 additions and 50 deletions

View file

@ -5,3 +5,4 @@ authors = ["James Harton <james@automat.nz>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
wrc = "0.3.0"

View file

@ -1,3 +1,4 @@
mod context; extern crate wrc;
// mod context;
mod scope; mod scope;
mod symbol; // mod symbol;

View file

@ -1,48 +0,0 @@
use crate::symbol::Symbol;
use std::collections::HashMap;
pub struct Scope {
symbols: HashMap<String, Symbol>,
}
impl Scope {
pub fn define(&mut self, symbol: Symbol) {
self.symbols.insert(symbol.identifier().to_string(), symbol);
}
pub fn reference(&self, identifier: &str) -> Option<&Symbol> {
self.symbols.get(identifier)
}
pub fn has_symbol(&self, identifier: &str) -> bool {
self.symbols.contains_key(identifier)
}
pub fn is_empty(&self) -> bool {
self.symbols.is_empty()
}
}
impl Default for Scope {
fn default() -> Scope {
Scope {
symbols: HashMap::new(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn add_and_get() {
let mut scope = Scope::default();
let symbol = Symbol::local("marty");
assert!(scope.is_empty());
assert!(!scope.has_symbol("marty"));
scope.define(symbol.clone());
assert!(scope.has_symbol("marty"));
assert_eq!(scope.reference("marty").unwrap(), &symbol);
}
}

View file

@ -0,0 +1,47 @@
use super::{Identifiable, Type};
use std::ops::{Deref, DerefMut};
use wrc::WRC;
#[derive(Debug, Clone)]
pub struct Local(WRC<LocalInner>);
impl Local {
fn new(identifier: &str, r#type: Type) -> Local {
Local(WRC::new(LocalInner {
identifier: identifier.to_string(),
r#type: r#type,
}))
}
}
impl Deref for Local {
type Target = WRC<LocalInner>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Local {
fn deref_mut(&mut self) -> &mut WRC<LocalInner> {
&mut self.0
}
}
#[derive(Debug, Clone)]
pub struct LocalInner {
identifier: String,
r#type: Type,
}
impl LocalInner {
fn r#type(&self) -> Type {
self.r#type.clone()
}
}
impl Identifiable for Local {
fn identifier(&self) -> &str {
&self.identifier
}
}

View file

@ -0,0 +1,100 @@
use super::{Identifiable, Local, Scope, Type};
use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
use wrc::WRC;
#[derive(Debug, Clone)]
pub struct Method(WRC<MethodInner>);
#[derive(Debug, Clone)]
pub struct MethodInner {
identifier: String,
result: Type,
visibility: Visibility,
arguments: HashMap<String, Local>,
locals: HashMap<String, Local>,
}
impl Method {
fn new(identifier: &str, result: Type, public: bool, arguments: Vec<Local>) -> Method {
let visibility = match public {
true => Visibility::Public,
false => Visibility::Private,
};
let mut args_hash = HashMap::new();
for local in arguments {
args_hash.insert(local.identifier().to_string(), local);
}
Method(WRC::new(MethodInner {
identifier: identifier.to_string(),
result,
visibility,
arguments: args_hash,
locals: HashMap::new(),
}))
}
}
impl Deref for Method {
type Target = WRC<MethodInner>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Method {
fn deref_mut(&mut self) -> &mut WRC<MethodInner> {
&mut self.0
}
}
impl MethodInner {
pub fn result(&self) -> Type {
self.result.clone()
}
pub fn is_public(&self) -> bool {
match self.visibility {
Visibility::Public => true,
_ => false,
}
}
pub fn is_private(&self) -> bool {
match self.visibility {
Visibility::Private => true,
_ => false,
}
}
}
#[derive(Debug, Clone)]
pub enum Visibility {
Public,
Private,
}
impl Identifiable for MethodInner {
fn identifier(&self) -> &str {
&self.identifier
}
}
impl Scope<Local> for MethodInner {
fn define(&mut self, local: Local) {
self.locals.insert(local.identifier().to_string(), local);
}
fn reference(&self, identifier: &str) -> Option<Local> {
match self.locals.get(identifier) {
Some(local) => Some(local.clone()),
None => match self.arguments.get(identifier) {
Some(local) => Some(local.clone()),
None => None,
},
}
}
}

View file

@ -0,0 +1,30 @@
use std::collections::HashMap;
use wrc::WRC;
mod local;
mod method;
mod r#trait;
mod r#type;
pub use local::Local;
pub use method::Method;
pub use r#trait::Trait;
pub use r#type::Type;
pub enum Constant {
Type(Type),
Trait(Trait),
}
pub struct Context {
globals: Constant,
}
pub trait Scope<T> {
fn define(&mut self, symbol: T);
fn reference(&self, identifier: &str) -> Option<T>;
}
pub trait Identifiable {
fn identifier(&self) -> &str;
}

View file

@ -0,0 +1,66 @@
use super::{Identifiable, Method, Scope};
use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
use wrc::WRC;
#[derive(Debug, Clone)]
pub struct Trait(WRC<TraitInner>);
impl Trait {
pub fn new(identifier: &str) -> Trait {
Trait(WRC::new(TraitInner {
identifier: identifier.to_string(),
public_methods: HashMap::new(),
private_methods: HashMap::new(),
}))
}
}
impl Deref for Trait {
type Target = WRC<TraitInner>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Trait {
fn deref_mut(&mut self) -> &mut WRC<TraitInner> {
&mut self.0
}
}
#[derive(Debug, Clone)]
pub struct TraitInner {
identifier: String,
public_methods: HashMap<String, Method>,
private_methods: HashMap<String, Method>,
}
impl Identifiable for TraitInner {
fn identifier(&self) -> &str {
&self.identifier
}
}
impl Scope<Method> for TraitInner {
fn define(&mut self, method: Method) {
if method.is_public() {
self.public_methods
.insert(method.identifier().to_string(), method);
} else {
self.private_methods
.insert(method.identifier().to_string(), method);
}
}
fn reference(&self, identifier: &str) -> Option<Method> {
match self.public_methods.get(identifier) {
Some(method) => Some(method.clone()),
None => match self.private_methods.get(identifier) {
Some(method) => Some(method.clone()),
None => None,
},
}
}
}

View file

@ -0,0 +1,101 @@
use super::{Identifiable, Method, Scope, Trait};
use std::collections::HashMap;
use wrc::WRC;
#[derive(Debug, Clone)]
pub struct Type(WRC<TypeInner>);
impl Type {
fn new(identifier: &str) -> Type {
Type(WRC::new(TypeInner {
identifier: identifier.to_string(),
public_methods: HashMap::new(),
private_methods: HashMap::new(),
traits: HashMap::new(),
}))
}
}
#[derive(Debug, Clone)]
pub struct TypeInner {
identifier: String,
public_methods: HashMap<String, Method>,
private_methods: HashMap<String, Method>,
traits: HashMap<String, Trait>,
}
impl Scope<Method> for Type {
fn define(&mut self, method: Method) {
self.0.define(method);
}
fn reference(&self, identifier: &str) -> Option<Method> {
self.0.reference(identifier)
}
}
impl Identifiable for Type {
fn identifier(&self) -> &str {
self.0.identifier()
}
}
impl Scope<Method> for TypeInner {
fn define(&mut self, method: Method) {
if method.is_public() {
self.public_methods
.insert(method.identifier().to_string(), method);
} else {
self.private_methods
.insert(method.identifier().to_string(), method);
}
}
fn reference(&self, identifier: &str) -> Option<Method> {
match self.public_methods.get(identifier) {
Some(method) => Some(method.clone()),
None => match self.private_methods.get(identifier) {
Some(method) => Some(method.clone()),
None => None,
},
}
}
}
impl Scope<Trait> for TypeInner {
fn define(&mut self, r#trait: Trait) {
self.traits
.insert(r#trait.identifier().to_string(), r#trait);
}
fn reference(&self, identifier: &str) -> Option<Trait> {
match self.traits.get(identifier) {
Some(r#trait) => Some(r#trait.clone()),
None => None,
}
}
}
impl Identifiable for TypeInner {
fn identifier(&self) -> &str {
&self.identifier
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_new() {
let ty = Type::new("Marty.McFly");
assert_eq!(ty.identifier(), "Marty.McFly");
}
#[test]
fn trait_scope() {
let tr = Trait::new("Character");
let mut ty = Type::new("Marty.McFly");
ty.define(tr);
}
}