1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- use crate::{
- opcode::{self, opcode},
- parser::{choice, comment_scope, take_to_end_of_pkglength, ParseResult, Parser},
- pkg_length::{pkg_length, PkgLength},
- term_object::{term_arg, term_list},
- AmlError,
- DebugVerbosity,
- };
- /// Type 1 opcodes do not return a value and so can't be used in expressions.
- pub fn type1_opcode<'a, 'c>() -> impl Parser<'a, 'c, ()>
- where
- 'c: 'a,
- {
- /*
- * Type1Opcode := DefBreak | DefBreakPoint | DefContinue | DefFatal | DefIfElse | DefLoad | DefNoop |
- * DefNotify | DefRelease | DefReset | DefReturn | DefSignal | DefSleep | DefStall |
- * DefWhile
- */
- comment_scope(DebugVerbosity::AllScopes, "Type1Opcode", choice!(def_if_else(), def_return()))
- }
- fn def_if_else<'a, 'c>() -> impl Parser<'a, 'c, ()>
- where
- 'c: 'a,
- {
- /*
- * DefIfElse := 0xa0 PkgLength Predicate TermList DefElse
- * Predicate := TermArg => Integer (0 = false, >0 = true)
- * DefElse := Nothing | <0xa1 PkgLength TermList>
- */
- opcode(opcode::DEF_IF_ELSE_OP)
- .then(comment_scope(
- DebugVerbosity::Scopes,
- "DefIfElse",
- pkg_length()
- .then(term_arg())
- .feed(|(length, predicate_arg)| {
- take_to_end_of_pkglength(length)
- .map(move |then_branch| Ok((predicate_arg.as_bool()?, then_branch)))
- })
- .then(choice!(
- opcode(opcode::DEF_ELSE_OP)
- .then(comment_scope(
- DebugVerbosity::AllScopes,
- "DefElse",
- pkg_length().feed(|length| take_to_end_of_pkglength(length))
- ))
- .map(|((), else_branch): ((), &[u8])| Ok(else_branch)),
- |input, context| -> ParseResult<'a, 'c, &[u8]> {
- /*
- * This path parses an DefIfElse that doesn't have an else branch. We simply
- * return an empty slice, so if the predicate is false, we don't execute
- * anything.
- */
- Ok((input, context, &[]))
- }
- ))
- .map_with_context(|((predicate, then_branch), else_branch), context| {
- let branch = if predicate { then_branch } else { else_branch };
- match term_list(PkgLength::from_raw_length(branch, branch.len() as u32)).parse(branch, context)
- {
- Ok((_, context, result)) => (Ok(result), context),
- Err((_, context, err)) => (Err(err), context),
- }
- }),
- ))
- .discard_result()
- }
- fn def_return<'a, 'c>() -> impl Parser<'a, 'c, ()>
- where
- 'c: 'a,
- {
- /*
- * DefReturn := 0xa4 ArgObject
- * ArgObject := TermArg => DataRefObject
- */
- opcode(opcode::DEF_RETURN_OP)
- .then(comment_scope(
- DebugVerbosity::Scopes,
- "DefReturn",
- term_arg().map(|return_arg| -> Result<(), AmlError> {
- /*
- * To return a value, we want to halt execution of the method and propagate the
- * return value all the way up to the start of the method invocation. To do this,
- * we emit a special error that is intercepted during method invocation and turned
- * into a valid result.
- */
- Err(AmlError::Return(return_arg))
- }),
- ))
- .discard_result()
- }
|