Separate method definitions from method specifications in the parser.
This commit is contained in:
parent
dc08e056c7
commit
b52e236c67
7 changed files with 277 additions and 146 deletions
|
@ -159,9 +159,9 @@ impl Builder {
|
||||||
|
|
||||||
self.push_block();
|
self.push_block();
|
||||||
|
|
||||||
for (name, ty) in &arguments {
|
for (name, ty) in &arguments {
|
||||||
self.env_set(name, ty);
|
self.env_set(name, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
for node in clause.body() {
|
for node in clause.body() {
|
||||||
self.build(node.clone(), &mut context);
|
self.build(node.clone(), &mut context);
|
||||||
|
@ -330,26 +330,12 @@ impl Builder {
|
||||||
let current_ty = self.peek_ty().unwrap();
|
let current_ty = self.peek_ty().unwrap();
|
||||||
let location = context.location(&node.location());
|
let location = context.location(&node.location());
|
||||||
|
|
||||||
let (ident, args, return_type, block) = node.private_method().unwrap();
|
let (ident, args, block) = node.private_method().unwrap();
|
||||||
|
|
||||||
let method_name = context.constant_string(ident.value_ref().as_str());
|
let method_name = context.constant_string(ident.value_ref().as_str());
|
||||||
let return_type = match return_type {
|
let return_type = context.unknown_type(location.clone());
|
||||||
Some(rt) => {
|
|
||||||
let types = rt
|
|
||||||
.value_ref()
|
|
||||||
.iter()
|
|
||||||
.map(|node| {
|
|
||||||
let name = context.constant_string(node.value_ref().as_str());
|
|
||||||
let location = context.location(&node.location());
|
|
||||||
context.reference_type(&name, location.clone())
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
context.anonymous_trait(types, location.clone())
|
|
||||||
}
|
|
||||||
None => context.unknown_type(location.clone()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut method = Method::new_private(method_name, return_type, current_ty.clone());
|
let mut method = Method::new_private(method_name, return_type, current_ty.clone(), location.clone());
|
||||||
|
|
||||||
let arguments: Vec<(StringIdx, TyIdx)> = args
|
let arguments: Vec<(StringIdx, TyIdx)> = args
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -390,26 +376,12 @@ impl Builder {
|
||||||
let current_ty = self.peek_ty().unwrap();
|
let current_ty = self.peek_ty().unwrap();
|
||||||
let location = context.location(&node.location());
|
let location = context.location(&node.location());
|
||||||
|
|
||||||
let (ident, args, return_type, block) = node.public_method().unwrap();
|
let (ident, args, block) = node.public_method().unwrap();
|
||||||
|
|
||||||
let method_name = context.constant_string(ident.value_ref().as_str());
|
let method_name = context.constant_string(ident.value_ref().as_str());
|
||||||
let return_type = match return_type {
|
let return_type = context.unknown_type(location.clone());
|
||||||
Some(rt) => {
|
|
||||||
let types = rt
|
|
||||||
.value_ref()
|
|
||||||
.iter()
|
|
||||||
.map(|node| {
|
|
||||||
let name = context.constant_string(node.value_ref().as_str());
|
|
||||||
let location = context.location(&node.location());
|
|
||||||
context.reference_type(&name, location.clone())
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
context.anonymous_trait(types, location.clone())
|
|
||||||
}
|
|
||||||
None => context.unknown_type(location.clone()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut method = Method::new_public(method_name, return_type, current_ty.clone());
|
let mut method = Method::new_public(method_name, return_type, current_ty.clone(), location.clone());
|
||||||
|
|
||||||
let arguments: Vec<(StringIdx, TyIdx)> = args
|
let arguments: Vec<(StringIdx, TyIdx)> = args
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -446,30 +418,55 @@ impl Builder {
|
||||||
|
|
||||||
context.define_method(method);
|
context.define_method(method);
|
||||||
}
|
}
|
||||||
NodeType::StaticMethod => {
|
NodeType::PublicMethodSpec => {
|
||||||
let current_ty = self.peek_ty().unwrap();
|
let current_ty = self.peek_ty().unwrap();
|
||||||
let location = context.location(&node.location());
|
let location = context.location(&node.location());
|
||||||
|
let (ident, args, rval) = node.public_method_spec().unwrap();
|
||||||
let (ident, args, return_type, block) = node.static_method().unwrap();
|
|
||||||
|
|
||||||
let method_name = context.constant_string(ident.value_ref().as_str());
|
let method_name = context.constant_string(ident.value_ref().as_str());
|
||||||
let return_type = match return_type {
|
let types = rval
|
||||||
Some(rt) => {
|
|
||||||
let types = rt
|
|
||||||
.value_ref()
|
.value_ref()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|node| {
|
.map(|node| {
|
||||||
let name = context.constant_string(node.value_ref().as_str());
|
let name = context.constant_string(node.value_ref().as_str());
|
||||||
let location = context.location(&node.location());
|
let location = context.location(&node.location());
|
||||||
context.reference_type(&name, location.clone())
|
context.reference_type(&name, location)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
context.anonymous_trait(types, location.clone())
|
let return_type = context.anonymous_trait(types, location.clone());
|
||||||
}
|
|
||||||
None => context.unknown_type(location.clone()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut method = Method::new_static(method_name, return_type, current_ty.clone());
|
let arguments: Vec<(StringIdx, TyIdx)> = args
|
||||||
|
.iter()
|
||||||
|
.map(|(name, type_spec)| {
|
||||||
|
let name = context.constant_string(name.value_ref().as_str());
|
||||||
|
let location = context.location(&type_spec.location());
|
||||||
|
let types = type_spec
|
||||||
|
.value_ref()
|
||||||
|
.iter()
|
||||||
|
.map(|node| {
|
||||||
|
let name = context.constant_string(node.value_ref().as_str());
|
||||||
|
let location = context.location(&node.location());
|
||||||
|
context.reference_type(&name, location)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let ty = context.anonymous_trait(types, location);
|
||||||
|
(name, ty)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let method = Method::new_public_spec(method_name, arguments, return_type, current_ty.clone(), location);
|
||||||
|
context.define_method(method);
|
||||||
|
}
|
||||||
|
NodeType::StaticMethod => {
|
||||||
|
let current_ty = self.peek_ty().unwrap();
|
||||||
|
let location = context.location(&node.location());
|
||||||
|
|
||||||
|
let (ident, args, block) = node.static_method().unwrap();
|
||||||
|
|
||||||
|
let method_name = context.constant_string(ident.value_ref().as_str());
|
||||||
|
let return_type = context.unknown_type(location.clone());
|
||||||
|
|
||||||
|
let mut method = Method::new_static(method_name, return_type, current_ty.clone(), location);
|
||||||
|
|
||||||
let arguments: Vec<(StringIdx, TyIdx)> = args
|
let arguments: Vec<(StringIdx, TyIdx)> = args
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -506,6 +503,44 @@ impl Builder {
|
||||||
|
|
||||||
context.define_method(method);
|
context.define_method(method);
|
||||||
}
|
}
|
||||||
|
NodeType::StaticMethodSpec => {
|
||||||
|
let current_ty = self.peek_ty().unwrap();
|
||||||
|
let location = context.location(&node.location());
|
||||||
|
let (ident, args, rval) = node.public_method_spec().unwrap();
|
||||||
|
|
||||||
|
let method_name = context.constant_string(ident.value_ref().as_str());
|
||||||
|
let types = rval
|
||||||
|
.value_ref()
|
||||||
|
.iter()
|
||||||
|
.map(|node| {
|
||||||
|
let name = context.constant_string(node.value_ref().as_str());
|
||||||
|
let location = context.location(&node.location());
|
||||||
|
context.reference_type(&name, location)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let return_type = context.anonymous_trait(types, location.clone());
|
||||||
|
let arguments: Vec<(StringIdx, TyIdx)> = args
|
||||||
|
.iter()
|
||||||
|
.map(|(name, type_spec)| {
|
||||||
|
let name = context.constant_string(name.value_ref().as_str());
|
||||||
|
let location = context.location(&type_spec.location());
|
||||||
|
let types = type_spec
|
||||||
|
.value_ref()
|
||||||
|
.iter()
|
||||||
|
.map(|node| {
|
||||||
|
let name = context.constant_string(node.value_ref().as_str());
|
||||||
|
let location = context.location(&node.location());
|
||||||
|
context.reference_type(&name, location)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let ty = context.anonymous_trait(types, location);
|
||||||
|
(name, ty)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let method = Method::new_static_spec(method_name, arguments, return_type, current_ty.clone(), location);
|
||||||
|
context.define_method(method);
|
||||||
|
}
|
||||||
NodeType::String => {
|
NodeType::String => {
|
||||||
let ty_idx = context.constant_string("Huia.Native.String");
|
let ty_idx = context.constant_string("Huia.Native.String");
|
||||||
let location = context.location(&node.location());
|
let location = context.location(&node.location());
|
||||||
|
@ -616,7 +651,11 @@ impl Builder {
|
||||||
|
|
||||||
fn peek_block(&self) -> Option<&Block> {
|
fn peek_block(&self) -> Option<&Block> {
|
||||||
let len = self.blocks.len();
|
let len = self.blocks.len();
|
||||||
self.blocks.get(len - 1)
|
if len > 0 {
|
||||||
|
self.blocks.get(len - 1)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek_block_mut(&mut self) -> Option<&mut Block> {
|
fn peek_block_mut(&mut self) -> Option<&mut Block> {
|
||||||
|
|
|
@ -18,6 +18,7 @@ pub fn compile_file(path: &str) -> Context {
|
||||||
let terms = Term::file(&contents).expect("Unable to parse file");
|
let terms = Term::file(&contents).expect("Unable to parse file");
|
||||||
let mut context = Context::new(path);
|
let mut context = Context::new(path);
|
||||||
let mut builder = ir::builder::Builder::default();
|
let mut builder = ir::builder::Builder::default();
|
||||||
|
|
||||||
for term in terms {
|
for term in terms {
|
||||||
builder.build(term, &mut context);
|
builder.build(term, &mut context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
use crate::block::BlockIdx;
|
use crate::block::BlockIdx;
|
||||||
use crate::function::{Clause, ClauseIdx};
|
use crate::function::{Clause, ClauseIdx};
|
||||||
|
use crate::location::Location;
|
||||||
use crate::stable::StringIdx;
|
use crate::stable::StringIdx;
|
||||||
use crate::ty::TyIdx;
|
use crate::ty::TyIdx;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Method {
|
pub struct Method {
|
||||||
clauses: Vec<Clause>,
|
clauses: Vec<Clause>,
|
||||||
|
kind: MethodKind,
|
||||||
|
location: Location,
|
||||||
name: StringIdx,
|
name: StringIdx,
|
||||||
return_type: TyIdx,
|
return_type: TyIdx,
|
||||||
kind: MethodKind,
|
signature: BTreeMap<StringIdx, TyIdx>,
|
||||||
upon: TyIdx,
|
upon: TyIdx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,32 +41,97 @@ impl Method {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_public(name: StringIdx, return_type: TyIdx, upon: TyIdx) -> Method {
|
pub fn new_private(
|
||||||
|
name: StringIdx,
|
||||||
|
return_type: TyIdx,
|
||||||
|
upon: TyIdx,
|
||||||
|
location: Location,
|
||||||
|
) -> Method {
|
||||||
Method {
|
Method {
|
||||||
clauses: Vec::default(),
|
clauses: Vec::default(),
|
||||||
name,
|
|
||||||
return_type,
|
|
||||||
kind: MethodKind::Public,
|
|
||||||
upon,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_private(name: StringIdx, return_type: TyIdx, upon: TyIdx) -> Method {
|
|
||||||
Method {
|
|
||||||
clauses: Vec::default(),
|
|
||||||
name,
|
|
||||||
return_type,
|
|
||||||
kind: MethodKind::Private,
|
kind: MethodKind::Private,
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
return_type,
|
||||||
|
signature: BTreeMap::default(),
|
||||||
upon,
|
upon,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_static(name: StringIdx, return_type: TyIdx, upon: TyIdx) -> Method {
|
pub fn new_public(
|
||||||
|
name: StringIdx,
|
||||||
|
return_type: TyIdx,
|
||||||
|
upon: TyIdx,
|
||||||
|
location: Location,
|
||||||
|
) -> Method {
|
||||||
Method {
|
Method {
|
||||||
clauses: Vec::default(),
|
clauses: Vec::default(),
|
||||||
|
kind: MethodKind::Public,
|
||||||
|
location,
|
||||||
name,
|
name,
|
||||||
return_type,
|
return_type,
|
||||||
|
signature: BTreeMap::default(),
|
||||||
|
upon,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_public_spec(
|
||||||
|
name: StringIdx,
|
||||||
|
arguments: Vec<(StringIdx, TyIdx)>,
|
||||||
|
return_type: TyIdx,
|
||||||
|
upon: TyIdx,
|
||||||
|
location: Location,
|
||||||
|
) -> Method {
|
||||||
|
let signature = arguments.iter().fold(BTreeMap::new(), |mut args, (k, v)| {
|
||||||
|
args.insert(k.clone(), v.clone());
|
||||||
|
args
|
||||||
|
});
|
||||||
|
Method {
|
||||||
|
clauses: Vec::default(),
|
||||||
|
kind: MethodKind::Public,
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
return_type,
|
||||||
|
signature,
|
||||||
|
upon,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_static(
|
||||||
|
name: StringIdx,
|
||||||
|
return_type: TyIdx,
|
||||||
|
upon: TyIdx,
|
||||||
|
location: Location,
|
||||||
|
) -> Method {
|
||||||
|
Method {
|
||||||
|
clauses: Vec::default(),
|
||||||
kind: MethodKind::Static,
|
kind: MethodKind::Static,
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
return_type,
|
||||||
|
signature: BTreeMap::default(),
|
||||||
|
upon,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_static_spec(
|
||||||
|
name: StringIdx,
|
||||||
|
arguments: Vec<(StringIdx, TyIdx)>,
|
||||||
|
return_type: TyIdx,
|
||||||
|
upon: TyIdx,
|
||||||
|
location: Location,
|
||||||
|
) -> Method {
|
||||||
|
let signature = arguments.iter().fold(BTreeMap::new(), |mut args, (k, v)| {
|
||||||
|
args.insert(k.clone(), v.clone());
|
||||||
|
args
|
||||||
|
});
|
||||||
|
Method {
|
||||||
|
clauses: Vec::default(),
|
||||||
|
kind: MethodKind::Static,
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
return_type,
|
||||||
|
signature,
|
||||||
upon,
|
upon,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ impl StringTable {
|
||||||
self.0.get_or_intern(value).into()
|
self.0.get_or_intern(value).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.is_empty()
|
self.0.is_empty()
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,10 @@ pub enum NodeType {
|
||||||
TraitDef,
|
TraitDef,
|
||||||
ImplDef,
|
ImplDef,
|
||||||
PublicMethod,
|
PublicMethod,
|
||||||
|
PublicMethodSpec,
|
||||||
PrivateMethod,
|
PrivateMethod,
|
||||||
StaticMethod,
|
StaticMethod,
|
||||||
|
StaticMethodSpec,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -69,26 +71,13 @@ enum Inner {
|
||||||
Local(Local),
|
Local(Local),
|
||||||
Map(Vec<(Term, Term)>),
|
Map(Vec<(Term, Term)>),
|
||||||
MethodCall(Box<Term>, Identifier, Vec<Term>),
|
MethodCall(Box<Term>, Identifier, Vec<Term>),
|
||||||
PrivateMethod(
|
PrivateMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
|
||||||
Identifier,
|
|
||||||
Vec<(Identifier, TypeSpec)>,
|
|
||||||
Option<TypeSpec>,
|
|
||||||
Vec<Term>,
|
|
||||||
),
|
|
||||||
PropertyGet(Identifier),
|
PropertyGet(Identifier),
|
||||||
PropertySet(Vec<(Identifier, Term)>),
|
PropertySet(Vec<(Identifier, Term)>),
|
||||||
PublicMethod(
|
PublicMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
|
||||||
Identifier,
|
PublicMethodSpec(Identifier, Vec<(Identifier, TypeSpec)>, TypeSpec),
|
||||||
Vec<(Identifier, TypeSpec)>,
|
StaticMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
|
||||||
Option<TypeSpec>,
|
StaticMethodSpec(Identifier, Vec<(Identifier, TypeSpec)>, TypeSpec),
|
||||||
Vec<Term>,
|
|
||||||
),
|
|
||||||
StaticMethod(
|
|
||||||
Identifier,
|
|
||||||
Vec<(Identifier, TypeSpec)>,
|
|
||||||
Option<TypeSpec>,
|
|
||||||
Vec<Term>,
|
|
||||||
),
|
|
||||||
String(String),
|
String(String),
|
||||||
TraitDef(Ty, Option<TypeSpec>, Vec<Term>),
|
TraitDef(Ty, Option<TypeSpec>, Vec<Term>),
|
||||||
Ty(Ty),
|
Ty(Ty),
|
||||||
|
@ -156,9 +145,11 @@ impl Term {
|
||||||
Inner::TypeDef(..) => NodeType::TypeDef,
|
Inner::TypeDef(..) => NodeType::TypeDef,
|
||||||
Inner::TraitDef(..) => NodeType::TraitDef,
|
Inner::TraitDef(..) => NodeType::TraitDef,
|
||||||
Inner::ImplDef(..) => NodeType::ImplDef,
|
Inner::ImplDef(..) => NodeType::ImplDef,
|
||||||
Inner::PublicMethod(_, _, _, _) => NodeType::PublicMethod,
|
Inner::PublicMethod(..) => NodeType::PublicMethod,
|
||||||
Inner::PrivateMethod(_, _, _, _) => NodeType::PrivateMethod,
|
Inner::PublicMethodSpec(..) => NodeType::PublicMethodSpec,
|
||||||
Inner::StaticMethod(_, _, _, _) => NodeType::StaticMethod,
|
Inner::PrivateMethod(..) => NodeType::PrivateMethod,
|
||||||
|
Inner::StaticMethod(..) => NodeType::StaticMethod,
|
||||||
|
Inner::StaticMethodSpec(..) => NodeType::StaticMethodSpec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,16 +262,9 @@ impl Term {
|
||||||
|
|
||||||
pub fn private_method(
|
pub fn private_method(
|
||||||
&self,
|
&self,
|
||||||
) -> Option<(
|
) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &Vec<Term>)> {
|
||||||
&Identifier,
|
|
||||||
&Vec<(Identifier, TypeSpec)>,
|
|
||||||
Option<&TypeSpec>,
|
|
||||||
&Vec<Term>,
|
|
||||||
)> {
|
|
||||||
match self.inner {
|
match self.inner {
|
||||||
Inner::PrivateMethod(ref name, ref args, ref rval, ref body) => {
|
Inner::PrivateMethod(ref name, ref args, ref body) => Some((name, args, body)),
|
||||||
Some((name, args, rval.as_ref(), body))
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,34 +283,34 @@ impl Term {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn public_method(
|
pub fn public_method(&self) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &Vec<Term>)> {
|
||||||
&self,
|
|
||||||
) -> Option<(
|
|
||||||
&Identifier,
|
|
||||||
&Vec<(Identifier, TypeSpec)>,
|
|
||||||
Option<&TypeSpec>,
|
|
||||||
&Vec<Term>,
|
|
||||||
)> {
|
|
||||||
match self.inner {
|
match self.inner {
|
||||||
Inner::PublicMethod(ref name, ref args, ref rval, ref body) => {
|
Inner::PublicMethod(ref name, ref args, ref body) => Some((name, args, body)),
|
||||||
Some((name, args, rval.as_ref(), body))
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn static_method(
|
pub fn public_method_spec(
|
||||||
&self,
|
&self,
|
||||||
) -> Option<(
|
) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &TypeSpec)> {
|
||||||
&Identifier,
|
|
||||||
&Vec<(Identifier, TypeSpec)>,
|
|
||||||
Option<&TypeSpec>,
|
|
||||||
&Vec<Term>,
|
|
||||||
)> {
|
|
||||||
match self.inner {
|
match self.inner {
|
||||||
Inner::StaticMethod(ref name, ref args, ref rval, ref body) => {
|
Inner::PublicMethodSpec(ref name, ref args, ref rval) => Some((name, args, rval)),
|
||||||
Some((name, args, rval.as_ref(), body))
|
_ => None,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn static_method(&self) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &Vec<Term>)> {
|
||||||
|
match self.inner {
|
||||||
|
Inner::StaticMethod(ref name, ref args, ref body) => Some((name, args, body)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn static_method_spec(
|
||||||
|
&self,
|
||||||
|
) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &TypeSpec)> {
|
||||||
|
match self.inner {
|
||||||
|
Inner::StaticMethodSpec(ref name, ref args, ref rval) => Some((name, args, rval)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -455,7 +439,7 @@ impl<'a> From<Pair<'a, Rule>> for Term {
|
||||||
inner: Inner::Declaration(identifier, Box::new(value)),
|
inner: Inner::Declaration(identifier, Box::new(value)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rule::defprivate => {
|
Rule::defprivatemethod => {
|
||||||
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 args = inner
|
let args = inner
|
||||||
|
@ -469,17 +453,13 @@ impl<'a> From<Pair<'a, Rule>> for Term {
|
||||||
(keyword, typespec)
|
(keyword, typespec)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let rval = match inner.next().unwrap().into_inner().next() {
|
|
||||||
Some(value) => Some(TypeSpec::from(value)),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
let block = inner.next().unwrap().into_inner().map(Term::from).collect();
|
let block = inner.next().unwrap().into_inner().map(Term::from).collect();
|
||||||
Term {
|
Term {
|
||||||
location: InputLocation::from(pair),
|
location: InputLocation::from(pair),
|
||||||
inner: Inner::PrivateMethod(name, args, rval, block),
|
inner: Inner::PrivateMethod(name, args, block),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rule::defpublic => {
|
Rule::defpublicmethod => {
|
||||||
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 args = inner
|
let args = inner
|
||||||
|
@ -493,17 +473,33 @@ impl<'a> From<Pair<'a, Rule>> for Term {
|
||||||
(keyword, typespec)
|
(keyword, typespec)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let rval = match inner.next().unwrap().into_inner().next() {
|
|
||||||
Some(value) => Some(TypeSpec::from(value)),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
let block = inner.next().unwrap().into_inner().map(Term::from).collect();
|
let block = inner.next().unwrap().into_inner().map(Term::from).collect();
|
||||||
Term {
|
Term {
|
||||||
location: InputLocation::from(pair),
|
location: InputLocation::from(pair),
|
||||||
inner: Inner::PublicMethod(name, args, rval, block),
|
inner: Inner::PublicMethod(name, args, block),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rule::defstatic => {
|
Rule::defpublicspec => {
|
||||||
|
let mut inner = pair.clone().into_inner();
|
||||||
|
let name = Identifier::from(inner.next().unwrap());
|
||||||
|
let args = inner
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.into_inner()
|
||||||
|
.map(|p| {
|
||||||
|
let mut inner = p.into_inner();
|
||||||
|
let keyword = Identifier::from(inner.next().unwrap());
|
||||||
|
let typespec = TypeSpec::from(inner.next().unwrap());
|
||||||
|
(keyword, typespec)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let rval = TypeSpec::from(inner.next().unwrap().into_inner().next().unwrap());
|
||||||
|
Term {
|
||||||
|
location: InputLocation::from(pair),
|
||||||
|
inner: Inner::PublicMethodSpec(name, args, rval),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rule::defstaticmethod => {
|
||||||
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 args = inner
|
let args = inner
|
||||||
|
@ -517,14 +513,30 @@ impl<'a> From<Pair<'a, Rule>> for Term {
|
||||||
(keyword, typespec)
|
(keyword, typespec)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let rval = match inner.next().unwrap().into_inner().next() {
|
|
||||||
Some(value) => Some(TypeSpec::from(value)),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
let block = inner.next().unwrap().into_inner().map(Term::from).collect();
|
let block = inner.next().unwrap().into_inner().map(Term::from).collect();
|
||||||
Term {
|
Term {
|
||||||
location: InputLocation::from(pair),
|
location: InputLocation::from(pair),
|
||||||
inner: Inner::StaticMethod(name, args, rval, block),
|
inner: Inner::StaticMethod(name, args, block),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rule::defstaticspec => {
|
||||||
|
let mut inner = pair.clone().into_inner();
|
||||||
|
let name = Identifier::from(inner.next().unwrap());
|
||||||
|
let args = inner
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.into_inner()
|
||||||
|
.map(|p| {
|
||||||
|
let mut inner = p.into_inner();
|
||||||
|
let keyword = Identifier::from(inner.next().unwrap());
|
||||||
|
let typespec = TypeSpec::from(inner.next().unwrap());
|
||||||
|
(keyword, typespec)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let rval = TypeSpec::from(inner.next().unwrap().into_inner().next().unwrap());
|
||||||
|
Term {
|
||||||
|
location: InputLocation::from(pair),
|
||||||
|
inner: Inner::StaticMethodSpec(name, args, rval),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rule::float => Term {
|
Rule::float => Term {
|
||||||
|
@ -876,10 +888,9 @@ mod test {
|
||||||
assert_eq!(key.value_ref(), "speed");
|
assert_eq!(key.value_ref(), "speed");
|
||||||
assert_eq!(value.value_ref()[0].value_ref(), "Integer");
|
assert_eq!(value.value_ref()[0].value_ref(), "Integer");
|
||||||
|
|
||||||
let (name, args, rval, block) = &body[0].static_method().unwrap();
|
let (name, args, block) = &body[0].static_method().unwrap();
|
||||||
assert_eq!(name.value_ref(), "new");
|
assert_eq!(name.value_ref(), "new");
|
||||||
assert!(args.is_empty());
|
assert!(args.is_empty());
|
||||||
assert!(rval.is_none());
|
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,10 @@ impl<'a> From<Pair<'a, Rule>> for TypeSpec {
|
||||||
location: InputLocation::from(pair.into_span()),
|
location: InputLocation::from(pair.into_span()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!("Expected pair to be an TypeSpec"),
|
_ => unreachable!(
|
||||||
|
"Expected pair to be an TypeSpec but was a {:?}",
|
||||||
|
pair.as_rule()
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,11 @@ input = _{ SOI ~ expression+ ~ EOI }
|
||||||
file = _{ SOI ~ definition* ~ EOI }
|
file = _{ SOI ~ definition* ~ EOI }
|
||||||
|
|
||||||
WHITESPACE = _{ (" " | "\t" | "\r" | "\n")+ }
|
WHITESPACE = _{ (" " | "\t" | "\r" | "\n")+ }
|
||||||
|
COMMENT = _{ comment_block | comment_line }
|
||||||
|
comment_block = @{ "###" ~ (!"###" ~ ANY)* ~ "###" }
|
||||||
|
comment_line = @{ "#" ~ (!("\r" | "\n") ~ ANY)* }
|
||||||
newline = _{ (" " | "\t")* ~ ("\n" | "\r")+ ~ (" " | "\t")* }
|
newline = _{ (" " | "\t")* ~ ("\n" | "\r")+ ~ (" " | "\t")* }
|
||||||
reserved = { "end" | "let" | "true" | "false" | "else" }
|
reserved = { "end" | "let" | "true" | "false" | "else" | "def" | "defp" | "defs" | "do" }
|
||||||
|
|
||||||
expression = _{ infix | expression_inner }
|
expression = _{ infix | expression_inner }
|
||||||
infix = { expression_inner ~ (binary_operator ~ expression_inner)+ }
|
infix = { expression_inner ~ (binary_operator ~ expression_inner)+ }
|
||||||
|
@ -45,27 +48,31 @@ typedefblock = { ("do" ~ (methoddef | impldef)* ~ "end")? }
|
||||||
|
|
||||||
traitdef = { "trait" ~ typename ~ traitdefreqs ~ traitdefblock }
|
traitdef = { "trait" ~ typename ~ traitdefreqs ~ traitdefblock }
|
||||||
traitdefreqs = { (":" ~ typespec)? }
|
traitdefreqs = { (":" ~ typespec)? }
|
||||||
traitdefblock = { ("do" ~ methoddef* ~ "end")? }
|
traitdefblock = { ("do" ~ (methoddef | methodspec)* ~ "end")? }
|
||||||
|
|
||||||
impldef = { "impl" ~ typename ~ impldefblock }
|
impldef = { "impl" ~ typename ~ impldefblock }
|
||||||
impldefblock = { ("do" ~ methoddef* ~ "end")? }
|
impldefblock = { ("do" ~ methoddef* ~ "end")? }
|
||||||
|
|
||||||
methoddef = _{ defpublic | defprivate | defstatic }
|
methoddef = _{ defpublicmethod | defprivatemethod | defstaticmethod }
|
||||||
|
methodspec = _{ defpublicspec | defstaticspec }
|
||||||
methodargs = { defargs? }
|
methodargs = { defargs? }
|
||||||
methodname = @{ ident ~ ("?")? }
|
methodname = @{ ident ~ ("?")? }
|
||||||
methodblockstatic = { "do" ~ expression* ~ "end" }
|
methodblockstatic = { "do" ~ expression* ~ "end" }
|
||||||
methodblockinstance = { "do" ~ instance_espression* ~ "end" }
|
methodblockinstance = { "do" ~ instance_espression* ~ "end" }
|
||||||
methodrval = { (":" ~ typespec)? }
|
methodrval = { ":" ~ typespec }
|
||||||
|
|
||||||
defpublic = { "def" ~ methodname ~ methodargs ~ methodrval ~ methodblockinstance }
|
defpublicmethod = { "def" ~ methodname ~ methodargs ~ methodblockinstance }
|
||||||
defprivate = { "defp" ~ methodname ~ methodargs ~ methodrval ~ methodblockinstance }
|
defprivatemethod = { "defp" ~ methodname ~ methodargs ~ methodblockinstance }
|
||||||
defstatic = { "defs" ~ methodname ~ methodargs ~ methodrval ~ methodblockstatic }
|
defstaticmethod = { "defs" ~ methodname ~ methodargs ~ methodblockstatic }
|
||||||
|
|
||||||
|
defpublicspec = { "def" ~ methodname ~ methodargs ~ methodrval }
|
||||||
|
defstaticspec = { "defs" ~ methodname ~ methodargs ~ methodrval }
|
||||||
|
|
||||||
typespec = { typename ~ ("+" ~ typename)* }
|
typespec = { typename ~ ("+" ~ typename)* }
|
||||||
|
|
||||||
literal = _{ constructor | map | array | typename | 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 ~ LOWERCASE_LETTER ~ (LETTER | "_")* }
|
||||||
keyword = @{ ident ~ ":" }
|
keyword = @{ ident ~ ":" }
|
||||||
|
|
||||||
if_expression = { "if" ~ instance_espression ~ if_positive ~ if_negative? ~ "end" }
|
if_expression = { "if" ~ instance_espression ~ if_positive ~ if_negative? ~ "end" }
|
||||||
|
@ -87,7 +94,7 @@ array = { "[" ~ (expression ~ ("," ~ expression)*)? ~ "]"
|
||||||
atom = @{ ":" ~ ident }
|
atom = @{ ":" ~ ident }
|
||||||
|
|
||||||
typename = @{ typename_name ~ ("." ~ typename_name)* }
|
typename = @{ typename_name ~ ("." ~ typename_name)* }
|
||||||
typename_name = @{ 'A'..'Z' ~ ('a'..'z' | 'A'..'Z' | "_")* }
|
typename_name = @{ UPPERCASE_LETTER ~ (LETTER | "_")* }
|
||||||
|
|
||||||
function = { "fn" ~ function_clause ~ ("," ~ function_clause)* }
|
function = { "fn" ~ function_clause ~ ("," ~ function_clause)* }
|
||||||
function_args = { defargs }
|
function_args = { defargs }
|
||||||
|
|
Reference in a new issue