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, value: Expr, } impl Parsable for Declaration { fn expected() -> (Vec>, bool) { (vec![ discriminant(&Token::Symbol("".to_string())), ], false) } fn parse(l: &mut WrappedLexer) -> Result { let span = l.span(); match l.monch() { // Symbol Colon DeclarationStart Symbol { Symbol } Assign 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, 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::>(); 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 { if self.name.eq("main") { Some(Identifier::main()) } else { Some(parent.subid_with_name(self.name.clone(), index)) } } }