85 lines
2.4 KiB
Rust
85 lines
2.4 KiB
Rust
use std::mem::{Discriminant, discriminant};
|
|
|
|
use crate::{token::Token, ir::{self, IrError, Identifier, BindingScope}};
|
|
|
|
use super::{Parsable, WrappedLexer, ParseError, absorb_token_or_error, expr::Expr};
|
|
|
|
#[derive(Debug)]
|
|
pub struct Declaration {
|
|
name: String,
|
|
type_: Expr,
|
|
name2: String,
|
|
args: Vec<String>,
|
|
value: Expr,
|
|
}
|
|
|
|
impl Parsable for Declaration {
|
|
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
|
(vec![
|
|
discriminant(&Token::Symbol("".to_string())),
|
|
], false)
|
|
}
|
|
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
|
let span = l.span();
|
|
match l.monch() {
|
|
// Symbol Colon <full_type> DeclarationStart Symbol { Symbol } Assign <expr>
|
|
Token::Symbol(name) => {
|
|
absorb_token_or_error(l, discriminant(&Token::Colon))?;
|
|
let type_ = Expr::parse(l)?;
|
|
absorb_token_or_error(l, discriminant(&Token::DeclarationStart))?;
|
|
let name2 = String::parse(l)?;
|
|
let args = Vec::parse(l)?;
|
|
absorb_token_or_error(l, discriminant(&Token::Assign))?;
|
|
let value = Expr::parse(l)?;
|
|
Ok(Self {
|
|
name,
|
|
name2,
|
|
args,
|
|
type_,
|
|
value,
|
|
})
|
|
},
|
|
_ => {
|
|
Err(ParseError {
|
|
expected: Self::expected().0,
|
|
location: span,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Declaration {
|
|
pub fn gen_ir(self, bindings: &BindingScope, index: u32, parent_id: Identifier) -> Result<Option<ir::Declaration>, IrError> {
|
|
let own_id = self.get_identifier(&parent_id, index).unwrap(); //TODO fix me
|
|
let Declaration { name, type_, name2, args, value } = self;
|
|
if name != name2 {
|
|
Err(IrError::MismatchedNames(name, name2))
|
|
} else {
|
|
let args = args.into_iter()
|
|
.enumerate()
|
|
.map(|(i, variable_name)| own_id.subid_with_name(variable_name, i as u32))
|
|
.collect::<Vec<_>>();
|
|
let n_args = args.len() as u32;
|
|
let local_binding = bindings.bind(args.clone());
|
|
let expression_dag = value.gen_ir(&local_binding, &own_id, n_args, false)?;
|
|
let type_dag = type_.gen_ir(&local_binding, &own_id, n_args + 1, true)?;
|
|
Ok(Some(
|
|
ir::Declaration {
|
|
identifier: own_id,
|
|
value_type: ir::value::Value::Function(Vec::new(), type_dag),
|
|
value: ir::value::Value::Function(args, expression_dag),
|
|
}
|
|
))
|
|
}
|
|
}
|
|
|
|
pub fn get_identifier(&self, parent: &Identifier, index: u32) -> Option<Identifier> {
|
|
if self.name.eq("main") {
|
|
Some(Identifier::main())
|
|
} else {
|
|
Some(parent.subid_with_name(self.name.clone(), index))
|
|
}
|
|
}
|
|
}
|