Break DetailedFunction into a tuple.

Use (Function, Details) in place of the aggregrate DetailedFunction.
It turns out that some tests want to clone and manipulate the function
while the details never change.
This commit is contained in:
Jakob Stoklund Olesen
2016-09-15 08:32:03 -07:00
parent 03170927dd
commit 7e98985ea6
3 changed files with 50 additions and 54 deletions

View File

@@ -7,7 +7,7 @@ extern crate cretonne;
pub use parser::{Result, parse_functions, parse_test}; pub use parser::{Result, parse_functions, parse_test};
pub use testcommand::{TestCommand, TestOption}; pub use testcommand::{TestCommand, TestOption};
pub use testfile::TestFile; pub use testfile::{TestFile, Details};
mod lexer; mod lexer;
mod parser; mod parser;

View File

@@ -19,7 +19,7 @@ use cretonne::ir::immediates::{Imm64, Ieee32, Ieee64};
use cretonne::ir::entities::{AnyEntity, NO_EBB, NO_INST, NO_VALUE}; use cretonne::ir::entities::{AnyEntity, NO_EBB, NO_INST, NO_VALUE};
use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs, JumpData, use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs, JumpData,
BranchData, ReturnData}; BranchData, ReturnData};
use testfile::{TestFile, DetailedFunction, Comment}; use testfile::{TestFile, Details, Comment};
use testcommand::TestCommand; use testcommand::TestCommand;
pub use lexer::Location; pub use lexer::Location;
@@ -30,7 +30,7 @@ pub use lexer::Location;
pub fn parse_functions(text: &str) -> Result<Vec<Function>> { pub fn parse_functions(text: &str) -> Result<Vec<Function>> {
Parser::new(text) Parser::new(text)
.parse_function_list() .parse_function_list()
.map(|list| list.into_iter().map(|dfunc| dfunc.function).collect()) .map(|list| list.into_iter().map(|(func, _)| func).collect())
} }
/// Parse the entire `text` as a test case file. /// Parse the entire `text` as a test case file.
@@ -505,7 +505,7 @@ impl<'a> Parser<'a> {
/// Parse a list of function definitions. /// Parse a list of function definitions.
/// ///
/// This is the top-level parse function matching the whole contents of a file. /// This is the top-level parse function matching the whole contents of a file.
pub fn parse_function_list(&mut self) -> Result<Vec<DetailedFunction<'a>>> { pub fn parse_function_list(&mut self) -> Result<Vec<(Function, Details<'a>)>> {
let mut list = Vec::new(); let mut list = Vec::new();
while self.token().is_some() { while self.token().is_some() {
list.push(try!(self.parse_function())); list.push(try!(self.parse_function()));
@@ -517,7 +517,7 @@ impl<'a> Parser<'a> {
// //
// function ::= * function-spec "{" preamble function-body "}" // function ::= * function-spec "{" preamble function-body "}"
// //
fn parse_function(&mut self) -> Result<DetailedFunction<'a>> { fn parse_function(&mut self) -> Result<(Function, Details<'a>)> {
// Begin gathering comments. // Begin gathering comments.
// Make sure we don't include any comments before the `function` keyword. // Make sure we don't include any comments before the `function` keyword.
self.token(); self.token();
@@ -545,10 +545,7 @@ impl<'a> Parser<'a> {
// references. // references.
try!(ctx.rewrite_references()); try!(ctx.rewrite_references());
Ok(DetailedFunction { Ok((ctx.function, Details { comments: mem::replace(&mut self.comments, Vec::new()) }))
function: ctx.function,
comments: mem::replace(&mut self.comments, Vec::new()),
})
} }
// Parse a function spec. // Parse a function spec.
@@ -1221,7 +1218,7 @@ mod tests {
use super::*; use super::*;
use cretonne::ir::types::{self, ArgumentType, ArgumentExtension}; use cretonne::ir::types::{self, ArgumentType, ArgumentExtension};
use cretonne::ir::entities::AnyEntity; use cretonne::ir::entities::AnyEntity;
use testfile::Comment; use testfile::{Details, Comment};
#[test] #[test]
fn argument_type() { fn argument_type() {
@@ -1261,13 +1258,12 @@ mod tests {
#[test] #[test]
fn stack_slot_decl() { fn stack_slot_decl() {
let func = Parser::new("function foo() { let (func, _) = Parser::new("function foo() {
ss3 = stack_slot 13 ss3 = stack_slot 13
ss1 = stack_slot 1 ss1 = stack_slot 1
}") }")
.parse_function() .parse_function()
.unwrap() .unwrap();
.function;
assert_eq!(func.name, "foo"); assert_eq!(func.name, "foo");
let mut iter = func.stack_slots.keys(); let mut iter = func.stack_slots.keys();
let ss0 = iter.next().unwrap(); let ss0 = iter.next().unwrap();
@@ -1291,13 +1287,12 @@ mod tests {
#[test] #[test]
fn ebb_header() { fn ebb_header() {
let func = Parser::new("function ebbs() { let (func, _) = Parser::new("function ebbs() {
ebb0: ebb0:
ebb4(vx3: i32): ebb4(vx3: i32):
}") }")
.parse_function() .parse_function()
.unwrap() .unwrap();
.function;
assert_eq!(func.name, "ebbs"); assert_eq!(func.name, "ebbs");
let mut ebbs = func.layout.ebbs(); let mut ebbs = func.layout.ebbs();
@@ -1314,38 +1309,39 @@ mod tests {
#[test] #[test]
fn comments() { fn comments() {
let dfunc = Parser::new("; before let (func, Details { comments }) =
function comment() { ; decl Parser::new("; before
ss10 = stack_slot 13 ; stackslot. function comment() { ; decl
; Still stackslot. ss10 = stack_slot 13 ; stackslot.
jt10 = jump_table ebb0 ; Still stackslot.
; Jumptable jt10 = jump_table ebb0
ebb0: ; Basic block ; Jumptable
trap ; Instruction ebb0: ; Basic block
} ; Trailing. trap ; Instruction
; More trailing.") } ; Trailing.
.parse_function() ; More trailing.")
.unwrap(); .parse_function()
assert_eq!(&dfunc.function.name, "comment"); .unwrap();
assert_eq!(dfunc.comments.len(), 8); // no 'before' comment. assert_eq!(&func.name, "comment");
assert_eq!(dfunc.comments[0], assert_eq!(comments.len(), 8); // no 'before' comment.
assert_eq!(comments[0],
Comment { Comment {
entity: AnyEntity::Function, entity: AnyEntity::Function,
text: "; decl", text: "; decl",
}); });
assert_eq!(dfunc.comments[1].entity.to_string(), "ss0"); assert_eq!(comments[1].entity.to_string(), "ss0");
assert_eq!(dfunc.comments[2].entity.to_string(), "ss0"); assert_eq!(comments[2].entity.to_string(), "ss0");
assert_eq!(dfunc.comments[2].text, "; Still stackslot."); assert_eq!(comments[2].text, "; Still stackslot.");
assert_eq!(dfunc.comments[3].entity.to_string(), "jt0"); assert_eq!(comments[3].entity.to_string(), "jt0");
assert_eq!(dfunc.comments[3].text, "; Jumptable"); assert_eq!(comments[3].text, "; Jumptable");
assert_eq!(dfunc.comments[4].entity.to_string(), "ebb0"); assert_eq!(comments[4].entity.to_string(), "ebb0");
assert_eq!(dfunc.comments[4].text, "; Basic block"); assert_eq!(comments[4].text, "; Basic block");
assert_eq!(dfunc.comments[5].entity.to_string(), "inst0"); assert_eq!(comments[5].entity.to_string(), "inst0");
assert_eq!(dfunc.comments[5].text, "; Instruction"); assert_eq!(comments[5].text, "; Instruction");
assert_eq!(dfunc.comments[6].entity, AnyEntity::Function); assert_eq!(comments[6].entity, AnyEntity::Function);
assert_eq!(dfunc.comments[7].entity, AnyEntity::Function); assert_eq!(comments[7].entity, AnyEntity::Function);
} }
#[test] #[test]
@@ -1359,6 +1355,6 @@ mod tests {
assert_eq!(tf.commands[0].command, "cfg"); assert_eq!(tf.commands[0].command, "cfg");
assert_eq!(tf.commands[1].command, "verify"); assert_eq!(tf.commands[1].command, "verify");
assert_eq!(tf.functions.len(), 1); assert_eq!(tf.functions.len(), 1);
assert_eq!(tf.functions[0].function.name, "comment"); assert_eq!(tf.functions[0].0.name, "comment");
} }
} }

View File

@@ -15,14 +15,14 @@ use testcommand::TestCommand;
#[derive(Debug)] #[derive(Debug)]
pub struct TestFile<'a> { pub struct TestFile<'a> {
pub commands: Vec<TestCommand<'a>>, pub commands: Vec<TestCommand<'a>>,
pub functions: Vec<DetailedFunction<'a>>, pub functions: Vec<(Function, Details<'a>)>,
} }
/// A function parsed from a text string along with other details that are useful for running /// Additional details about a function parsed from a text string.
/// tests. /// These are useful for detecting test commands embedded in comments etc.
/// The details to not affect the semantics of the function.
#[derive(Debug)] #[derive(Debug)]
pub struct DetailedFunction<'a> { pub struct Details<'a> {
pub function: Function,
pub comments: Vec<Comment<'a>>, pub comments: Vec<Comment<'a>>,
} }