diff --git a/hercules_ir/src/parse.rs b/hercules_ir/src/parse.rs index 5f3e83c8f2202fed3fd0ed9030720a89f9f9e89b..16e862c0ec0da0bc9b29968633fe789571e3a9fe 100644 --- a/hercules_ir/src/parse.rs +++ b/hercules_ir/src/parse.rs @@ -17,6 +17,16 @@ struct Context<'a> { } impl<'a> Context<'a> { + fn get_function_id(&mut self, name: &'a str) -> FunctionID { + if let Some(id) = self.function_ids.get(name) { + *id + } else { + let id = FunctionID::new(self.function_ids.len()); + self.function_ids.insert(name, id); + id + } + } + fn get_node_id(&mut self, name: &'a str) -> NodeID { if let Some(id) = self.node_ids.get(name) { *id @@ -26,6 +36,26 @@ impl<'a> Context<'a> { id } } + + fn get_type_id(&mut self, ty: Type) -> TypeID { + if let Some(id) = self.interned_types.get(&ty) { + *id + } else { + let id = TypeID::new(self.interned_types.len()); + self.interned_types.insert(ty, id); + id + } + } + + fn get_constant_id(&mut self, constant: Constant) -> ConstantID { + if let Some(id) = self.interned_constants.get(&constant) { + *id + } else { + let id = ConstantID::new(self.interned_constants.len()); + self.interned_constants.insert(constant, id); + id + } + } } fn parse_module<'a>(ir_text: &'a str, mut context: Context<'a>) -> nom::IResult<&'a str, Module> { @@ -69,7 +99,7 @@ fn parse_function<'a>( nom::character::complete::multispace0, nom::character::complete::char(':'), nom::character::complete::multispace0, - |x| parse_type(x, context), + |x| parse_type_id(x, context), nom::character::complete::multispace0, )), )(ir_text)?; @@ -82,7 +112,7 @@ fn parse_function<'a>( let ir_text = nom::character::complete::char(')')(ir_text)?.0; let ir_text = nom::character::complete::multispace0(ir_text)?.0; let ir_text = nom::bytes::complete::tag("->")(ir_text)?.0; - let (ir_text, return_type) = parse_type(ir_text, context)?; + let (ir_text, return_type) = parse_type_id(ir_text, context)?; let (ir_text, nodes) = nom::multi::many1(|x| parse_node(x, context))(ir_text)?; let mut fixed_nodes = vec![Node::Start; context.node_ids.len()]; for (name, node) in nodes { @@ -151,7 +181,11 @@ fn parse_constant_node<'a>( let ir_text = nom::character::complete::multispace0(ir_text)?.0; let ir_text = nom::character::complete::char('(')(ir_text)?.0; let ir_text = nom::character::complete::multispace0(ir_text)?.0; - let (ir_text, id) = parse_constant(ir_text, context)?; + let (ir_text, ty) = parse_type(ir_text)?; + let ir_text = nom::character::complete::multispace0(ir_text)?.0; + let ir_text = nom::character::complete::char(',')(ir_text)?.0; + let ir_text = nom::character::complete::multispace0(ir_text)?.0; + let (ir_text, id) = parse_constant_id(ir_text, ty, context)?; let ir_text = nom::character::complete::multispace0(ir_text)?.0; let ir_text = nom::character::complete::char(')')(ir_text)?.0; Ok((ir_text, Node::Constant { id })) @@ -182,35 +216,46 @@ fn parse_add<'a>(ir_text: &'a str, context: &mut Context<'a>) -> nom::IResult<&' )) } -fn parse_type<'a>(ir_text: &'a str, context: &mut Context<'a>) -> nom::IResult<&'a str, TypeID> { +fn parse_type_id<'a>(ir_text: &'a str, context: &mut Context<'a>) -> nom::IResult<&'a str, TypeID> { let ir_text = nom::character::complete::multispace0(ir_text)?.0; - let (ir_text, ty) = - nom::combinator::map(nom::bytes::complete::tag("i32"), |_| Type::Integer32)(ir_text)?; - let id = if let Some(id) = context.interned_types.get(&ty) { - *id - } else { - let id = TypeID::new(context.interned_types.len()); - context.interned_types.insert(ty, id); - id - }; + let (ir_text, ty) = parse_type(ir_text)?; + let id = context.get_type_id(ty); Ok((ir_text, id)) } -fn parse_constant<'a>( +fn parse_type<'a>(ir_text: &'a str) -> nom::IResult<&'a str, Type> { + let ir_text = nom::character::complete::multispace0(ir_text)?.0; + let (ir_text, ty) = nom::branch::alt(( + nom::combinator::map(nom::bytes::complete::tag("i8"), |_| Type::Integer8), + nom::combinator::map(nom::bytes::complete::tag("i32"), |_| Type::Integer32), + ))(ir_text)?; + Ok((ir_text, ty)) +} + +fn parse_constant_id<'a>( ir_text: &'a str, + ty: Type, context: &mut Context<'a>, ) -> nom::IResult<&'a str, ConstantID> { - let (ir_text, constant) = nom::branch::alt((parse_integer8,))(ir_text)?; - let id = if let Some(id) = context.interned_constants.get(&constant) { - *id - } else { - let id = ConstantID::new(context.interned_constants.len()); - context.interned_constants.insert(constant, id); - id - }; + let (ir_text, constant) = parse_constant(ir_text, ty, context)?; + let id = context.get_constant_id(constant); Ok((ir_text, id)) } +fn parse_constant<'a>( + ir_text: &'a str, + ty: Type, + context: &mut Context<'a>, +) -> nom::IResult<&'a str, Constant> { + let (ir_text, constant) = match ty { + Type::Integer8 => parse_integer8(ir_text)?, + Type::Integer32 => parse_integer32(ir_text)?, + _ => todo!(), + }; + context.get_type_id(ty); + Ok((ir_text, constant)) +} + fn parse_integer8<'a>(ir_text: &'a str) -> nom::IResult<&'a str, Constant> { let (ir_text, num_text) = nom::bytes::complete::is_a("-1234567890")(ir_text)?; let num = num_text.parse::<i8>().map_err(|_| { @@ -222,6 +267,17 @@ fn parse_integer8<'a>(ir_text: &'a str) -> nom::IResult<&'a str, Constant> { Ok((ir_text, Constant::Integer8(num))) } +fn parse_integer32<'a>(ir_text: &'a str) -> nom::IResult<&'a str, Constant> { + let (ir_text, num_text) = nom::bytes::complete::is_a("-1234567890")(ir_text)?; + let num = num_text.parse::<i32>().map_err(|_| { + nom::Err::Error(nom::error::Error { + input: num_text, + code: nom::error::ErrorKind::IsNot, + }) + })?; + Ok((ir_text, Constant::Integer32(num))) +} + mod tests { #[allow(unused_imports)] use super::*; @@ -229,7 +285,7 @@ mod tests { #[test] fn parse_ir1() { let module = - parse("fn add(x: i32, y: i32) -> i32 r = return(start, z) z = add(start, x, y)"); + parse("fn add(x: i32, y: i32) -> i32 c = constant(i8, 5) r = return(start, w) w = add(start, z, c) z = add(start, x, y)"); println!("{:?}", module); } }