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();
|
||||
|
||||
for (name, ty) in &arguments {
|
||||
self.env_set(name, ty);
|
||||
}
|
||||
for (name, ty) in &arguments {
|
||||
self.env_set(name, ty);
|
||||
}
|
||||
|
||||
for node in clause.body() {
|
||||
self.build(node.clone(), &mut context);
|
||||
|
@ -330,26 +330,12 @@ impl Builder {
|
|||
let current_ty = self.peek_ty().unwrap();
|
||||
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 return_type = match return_type {
|
||||
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 return_type = 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
|
||||
.iter()
|
||||
|
@ -390,26 +376,12 @@ impl Builder {
|
|||
let current_ty = self.peek_ty().unwrap();
|
||||
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 return_type = match return_type {
|
||||
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 return_type = 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
|
||||
.iter()
|
||||
|
@ -446,30 +418,55 @@ impl Builder {
|
|||
|
||||
context.define_method(method);
|
||||
}
|
||||
NodeType::StaticMethod => {
|
||||
NodeType::PublicMethodSpec => {
|
||||
let current_ty = self.peek_ty().unwrap();
|
||||
let location = context.location(&node.location());
|
||||
|
||||
let (ident, args, return_type, block) = node.static_method().unwrap();
|
||||
let (ident, args, rval) = node.public_method_spec().unwrap();
|
||||
|
||||
let method_name = context.constant_string(ident.value_ref().as_str());
|
||||
let return_type = match return_type {
|
||||
Some(rt) => {
|
||||
let types = rt
|
||||
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.clone())
|
||||
context.reference_type(&name, location)
|
||||
})
|
||||
.collect();
|
||||
context.anonymous_trait(types, location.clone())
|
||||
}
|
||||
None => context.unknown_type(location.clone()),
|
||||
};
|
||||
let return_type = context.anonymous_trait(types, 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
|
||||
.iter()
|
||||
|
@ -506,6 +503,44 @@ impl Builder {
|
|||
|
||||
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 => {
|
||||
let ty_idx = context.constant_string("Huia.Native.String");
|
||||
let location = context.location(&node.location());
|
||||
|
@ -616,7 +651,11 @@ impl Builder {
|
|||
|
||||
fn peek_block(&self) -> Option<&Block> {
|
||||
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> {
|
||||
|
|
|
@ -18,6 +18,7 @@ pub fn compile_file(path: &str) -> Context {
|
|||
let terms = Term::file(&contents).expect("Unable to parse file");
|
||||
let mut context = Context::new(path);
|
||||
let mut builder = ir::builder::Builder::default();
|
||||
|
||||
for term in terms {
|
||||
builder.build(term, &mut context);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
use crate::block::BlockIdx;
|
||||
use crate::function::{Clause, ClauseIdx};
|
||||
use crate::location::Location;
|
||||
use crate::stable::StringIdx;
|
||||
use crate::ty::TyIdx;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Method {
|
||||
clauses: Vec<Clause>,
|
||||
kind: MethodKind,
|
||||
location: Location,
|
||||
name: StringIdx,
|
||||
return_type: TyIdx,
|
||||
kind: MethodKind,
|
||||
signature: BTreeMap<StringIdx, 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 {
|
||||
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,
|
||||
location,
|
||||
name,
|
||||
return_type,
|
||||
signature: BTreeMap::default(),
|
||||
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 {
|
||||
clauses: Vec::default(),
|
||||
kind: MethodKind::Public,
|
||||
location,
|
||||
name,
|
||||
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,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ impl StringTable {
|
|||
self.0.get_or_intern(value).into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
|
|
@ -48,8 +48,10 @@ pub enum NodeType {
|
|||
TraitDef,
|
||||
ImplDef,
|
||||
PublicMethod,
|
||||
PublicMethodSpec,
|
||||
PrivateMethod,
|
||||
StaticMethod,
|
||||
StaticMethodSpec,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -69,26 +71,13 @@ enum Inner {
|
|||
Local(Local),
|
||||
Map(Vec<(Term, Term)>),
|
||||
MethodCall(Box<Term>, Identifier, Vec<Term>),
|
||||
PrivateMethod(
|
||||
Identifier,
|
||||
Vec<(Identifier, TypeSpec)>,
|
||||
Option<TypeSpec>,
|
||||
Vec<Term>,
|
||||
),
|
||||
PrivateMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
|
||||
PropertyGet(Identifier),
|
||||
PropertySet(Vec<(Identifier, Term)>),
|
||||
PublicMethod(
|
||||
Identifier,
|
||||
Vec<(Identifier, TypeSpec)>,
|
||||
Option<TypeSpec>,
|
||||
Vec<Term>,
|
||||
),
|
||||
StaticMethod(
|
||||
Identifier,
|
||||
Vec<(Identifier, TypeSpec)>,
|
||||
Option<TypeSpec>,
|
||||
Vec<Term>,
|
||||
),
|
||||
PublicMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
|
||||
PublicMethodSpec(Identifier, Vec<(Identifier, TypeSpec)>, TypeSpec),
|
||||
StaticMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
|
||||
StaticMethodSpec(Identifier, Vec<(Identifier, TypeSpec)>, TypeSpec),
|
||||
String(String),
|
||||
TraitDef(Ty, Option<TypeSpec>, Vec<Term>),
|
||||
Ty(Ty),
|
||||
|
@ -156,9 +145,11 @@ impl Term {
|
|||
Inner::TypeDef(..) => NodeType::TypeDef,
|
||||
Inner::TraitDef(..) => NodeType::TraitDef,
|
||||
Inner::ImplDef(..) => NodeType::ImplDef,
|
||||
Inner::PublicMethod(_, _, _, _) => NodeType::PublicMethod,
|
||||
Inner::PrivateMethod(_, _, _, _) => NodeType::PrivateMethod,
|
||||
Inner::StaticMethod(_, _, _, _) => NodeType::StaticMethod,
|
||||
Inner::PublicMethod(..) => NodeType::PublicMethod,
|
||||
Inner::PublicMethodSpec(..) => NodeType::PublicMethodSpec,
|
||||
Inner::PrivateMethod(..) => NodeType::PrivateMethod,
|
||||
Inner::StaticMethod(..) => NodeType::StaticMethod,
|
||||
Inner::StaticMethodSpec(..) => NodeType::StaticMethodSpec,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,16 +262,9 @@ impl Term {
|
|||
|
||||
pub fn private_method(
|
||||
&self,
|
||||
) -> Option<(
|
||||
&Identifier,
|
||||
&Vec<(Identifier, TypeSpec)>,
|
||||
Option<&TypeSpec>,
|
||||
&Vec<Term>,
|
||||
)> {
|
||||
) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &Vec<Term>)> {
|
||||
match self.inner {
|
||||
Inner::PrivateMethod(ref name, ref args, ref rval, ref body) => {
|
||||
Some((name, args, rval.as_ref(), body))
|
||||
}
|
||||
Inner::PrivateMethod(ref name, ref args, ref body) => Some((name, args, body)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -299,34 +283,34 @@ impl Term {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn public_method(
|
||||
&self,
|
||||
) -> Option<(
|
||||
&Identifier,
|
||||
&Vec<(Identifier, TypeSpec)>,
|
||||
Option<&TypeSpec>,
|
||||
&Vec<Term>,
|
||||
)> {
|
||||
pub fn public_method(&self) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &Vec<Term>)> {
|
||||
match self.inner {
|
||||
Inner::PublicMethod(ref name, ref args, ref rval, ref body) => {
|
||||
Some((name, args, rval.as_ref(), body))
|
||||
}
|
||||
Inner::PublicMethod(ref name, ref args, ref body) => Some((name, args, body)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn static_method(
|
||||
pub fn public_method_spec(
|
||||
&self,
|
||||
) -> Option<(
|
||||
&Identifier,
|
||||
&Vec<(Identifier, TypeSpec)>,
|
||||
Option<&TypeSpec>,
|
||||
&Vec<Term>,
|
||||
)> {
|
||||
) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &TypeSpec)> {
|
||||
match self.inner {
|
||||
Inner::StaticMethod(ref name, ref args, ref rval, ref body) => {
|
||||
Some((name, args, rval.as_ref(), body))
|
||||
}
|
||||
Inner::PublicMethodSpec(ref name, ref args, ref rval) => Some((name, args, rval)),
|
||||
_ => 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,
|
||||
}
|
||||
}
|
||||
|
@ -455,7 +439,7 @@ impl<'a> From<Pair<'a, Rule>> for Term {
|
|||
inner: Inner::Declaration(identifier, Box::new(value)),
|
||||
}
|
||||
}
|
||||
Rule::defprivate => {
|
||||
Rule::defprivatemethod => {
|
||||
let mut inner = pair.clone().into_inner();
|
||||
let name = Identifier::from(inner.next().unwrap());
|
||||
let args = inner
|
||||
|
@ -469,17 +453,13 @@ impl<'a> From<Pair<'a, Rule>> for Term {
|
|||
(keyword, typespec)
|
||||
})
|
||||
.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();
|
||||
Term {
|
||||
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 name = Identifier::from(inner.next().unwrap());
|
||||
let args = inner
|
||||
|
@ -493,17 +473,33 @@ impl<'a> From<Pair<'a, Rule>> for Term {
|
|||
(keyword, typespec)
|
||||
})
|
||||
.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();
|
||||
Term {
|
||||
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 name = Identifier::from(inner.next().unwrap());
|
||||
let args = inner
|
||||
|
@ -517,14 +513,30 @@ impl<'a> From<Pair<'a, Rule>> for Term {
|
|||
(keyword, typespec)
|
||||
})
|
||||
.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();
|
||||
Term {
|
||||
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 {
|
||||
|
@ -876,10 +888,9 @@ mod test {
|
|||
assert_eq!(key.value_ref(), "speed");
|
||||
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!(args.is_empty());
|
||||
assert!(rval.is_none());
|
||||
assert_eq!(block.len(), 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,10 @@ impl<'a> From<Pair<'a, Rule>> for TypeSpec {
|
|||
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 }
|
||||
|
||||
WHITESPACE = _{ (" " | "\t" | "\r" | "\n")+ }
|
||||
COMMENT = _{ comment_block | comment_line }
|
||||
comment_block = @{ "###" ~ (!"###" ~ ANY)* ~ "###" }
|
||||
comment_line = @{ "#" ~ (!("\r" | "\n") ~ ANY)* }
|
||||
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 }
|
||||
infix = { expression_inner ~ (binary_operator ~ expression_inner)+ }
|
||||
|
@ -45,27 +48,31 @@ typedefblock = { ("do" ~ (methoddef | impldef)* ~ "end")? }
|
|||
|
||||
traitdef = { "trait" ~ typename ~ traitdefreqs ~ traitdefblock }
|
||||
traitdefreqs = { (":" ~ typespec)? }
|
||||
traitdefblock = { ("do" ~ methoddef* ~ "end")? }
|
||||
traitdefblock = { ("do" ~ (methoddef | methodspec)* ~ "end")? }
|
||||
|
||||
impldef = { "impl" ~ typename ~ impldefblock }
|
||||
impldefblock = { ("do" ~ methoddef* ~ "end")? }
|
||||
|
||||
methoddef = _{ defpublic | defprivate | defstatic }
|
||||
methoddef = _{ defpublicmethod | defprivatemethod | defstaticmethod }
|
||||
methodspec = _{ defpublicspec | defstaticspec }
|
||||
methodargs = { defargs? }
|
||||
methodname = @{ ident ~ ("?")? }
|
||||
methodblockstatic = { "do" ~ expression* ~ "end" }
|
||||
methodblockinstance = { "do" ~ instance_espression* ~ "end" }
|
||||
methodrval = { (":" ~ typespec)? }
|
||||
methodrval = { ":" ~ typespec }
|
||||
|
||||
defpublic = { "def" ~ methodname ~ methodargs ~ methodrval ~ methodblockinstance }
|
||||
defprivate = { "defp" ~ methodname ~ methodargs ~ methodrval ~ methodblockinstance }
|
||||
defstatic = { "defs" ~ methodname ~ methodargs ~ methodrval ~ methodblockstatic }
|
||||
defpublicmethod = { "def" ~ methodname ~ methodargs ~ methodblockinstance }
|
||||
defprivatemethod = { "defp" ~ methodname ~ methodargs ~ methodblockinstance }
|
||||
defstaticmethod = { "defs" ~ methodname ~ methodargs ~ methodblockstatic }
|
||||
|
||||
defpublicspec = { "def" ~ methodname ~ methodargs ~ methodrval }
|
||||
defstaticspec = { "defs" ~ methodname ~ methodargs ~ methodrval }
|
||||
|
||||
typespec = { typename ~ ("+" ~ typename)* }
|
||||
|
||||
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 ~ ":" }
|
||||
|
||||
if_expression = { "if" ~ instance_espression ~ if_positive ~ if_negative? ~ "end" }
|
||||
|
@ -87,7 +94,7 @@ array = { "[" ~ (expression ~ ("," ~ expression)*)? ~ "]"
|
|||
atom = @{ ":" ~ ident }
|
||||
|
||||
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_args = { defargs }
|
||||
|
|
Reference in a new issue