type1.rs 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. use crate::{
  2. opcode::{self, opcode},
  3. parser::{choice, comment_scope, take_to_end_of_pkglength, ParseResult, Parser},
  4. pkg_length::{pkg_length, PkgLength},
  5. term_object::{term_arg, term_list},
  6. AmlError,
  7. DebugVerbosity,
  8. };
  9. /// Type 1 opcodes do not return a value and so can't be used in expressions.
  10. pub fn type1_opcode<'a, 'c>() -> impl Parser<'a, 'c, ()>
  11. where
  12. 'c: 'a,
  13. {
  14. /*
  15. * Type1Opcode := DefBreak | DefBreakPoint | DefContinue | DefFatal | DefIfElse | DefLoad | DefNoop |
  16. * DefNotify | DefRelease | DefReset | DefReturn | DefSignal | DefSleep | DefStall |
  17. * DefWhile
  18. */
  19. comment_scope(DebugVerbosity::AllScopes, "Type1Opcode", choice!(def_if_else(), def_return()))
  20. }
  21. fn def_if_else<'a, 'c>() -> impl Parser<'a, 'c, ()>
  22. where
  23. 'c: 'a,
  24. {
  25. /*
  26. * DefIfElse := 0xa0 PkgLength Predicate TermList DefElse
  27. * Predicate := TermArg => Integer (0 = false, >0 = true)
  28. * DefElse := Nothing | <0xa1 PkgLength TermList>
  29. */
  30. opcode(opcode::DEF_IF_ELSE_OP)
  31. .then(comment_scope(
  32. DebugVerbosity::Scopes,
  33. "DefIfElse",
  34. pkg_length()
  35. .then(term_arg())
  36. .feed(|(length, predicate_arg)| {
  37. take_to_end_of_pkglength(length)
  38. .map(move |then_branch| Ok((predicate_arg.as_bool()?, then_branch)))
  39. })
  40. .then(choice!(
  41. opcode(opcode::DEF_ELSE_OP)
  42. .then(comment_scope(
  43. DebugVerbosity::AllScopes,
  44. "DefElse",
  45. pkg_length().feed(|length| take_to_end_of_pkglength(length))
  46. ))
  47. .map(|((), else_branch): ((), &[u8])| Ok(else_branch)),
  48. |input, context| -> ParseResult<'a, 'c, &[u8]> {
  49. /*
  50. * This path parses an DefIfElse that doesn't have an else branch. We simply
  51. * return an empty slice, so if the predicate is false, we don't execute
  52. * anything.
  53. */
  54. Ok((input, context, &[]))
  55. }
  56. ))
  57. .map_with_context(|((predicate, then_branch), else_branch), context| {
  58. let branch = if predicate { then_branch } else { else_branch };
  59. match term_list(PkgLength::from_raw_length(branch, branch.len() as u32)).parse(branch, context)
  60. {
  61. Ok((_, context, result)) => (Ok(result), context),
  62. Err((_, context, err)) => (Err(err), context),
  63. }
  64. }),
  65. ))
  66. .discard_result()
  67. }
  68. fn def_return<'a, 'c>() -> impl Parser<'a, 'c, ()>
  69. where
  70. 'c: 'a,
  71. {
  72. /*
  73. * DefReturn := 0xa4 ArgObject
  74. * ArgObject := TermArg => DataRefObject
  75. */
  76. opcode(opcode::DEF_RETURN_OP)
  77. .then(comment_scope(
  78. DebugVerbosity::Scopes,
  79. "DefReturn",
  80. term_arg().map(|return_arg| -> Result<(), AmlError> {
  81. /*
  82. * To return a value, we want to halt execution of the method and propagate the
  83. * return value all the way up to the start of the method invocation. To do this,
  84. * we emit a special error that is intercepted during method invocation and turned
  85. * into a valid result.
  86. */
  87. Err(AmlError::Return(return_arg))
  88. }),
  89. ))
  90. .discard_result()
  91. }