Another attempt.
This commit is contained in:
parent
7277510a72
commit
b07a3ce8ef
8 changed files with 348 additions and 50 deletions
|
@ -5,3 +5,4 @@ authors = ["James Harton <james@automat.nz>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
wrc = "0.3.0"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
mod context;
|
||||
extern crate wrc;
|
||||
// mod context;
|
||||
mod scope;
|
||||
mod symbol;
|
||||
// mod symbol;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
47
huia-compiler/src/scope/local.rs
Normal file
47
huia-compiler/src/scope/local.rs
Normal 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
|
||||
}
|
||||
}
|
100
huia-compiler/src/scope/method.rs
Normal file
100
huia-compiler/src/scope/method.rs
Normal 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,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
30
huia-compiler/src/scope/mod.rs
Normal file
30
huia-compiler/src/scope/mod.rs
Normal 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;
|
||||
}
|
66
huia-compiler/src/scope/trait.rs
Normal file
66
huia-compiler/src/scope/trait.rs
Normal 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,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
101
huia-compiler/src/scope/type.rs
Normal file
101
huia-compiler/src/scope/type.rs
Normal 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);
|
||||
}
|
||||
}
|
Reference in a new issue