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"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
wrc = "0.3.0"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
mod context;
|
extern crate wrc;
|
||||||
|
// mod context;
|
||||||
mod scope;
|
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