type2.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. use crate::{
  2. name_object::{name_string, super_name, Target},
  3. opcode::{self, opcode},
  4. parser::{choice, comment_scope, comment_scope_verbose, id, try_with_context, Parser},
  5. term_object::term_arg,
  6. value::AmlValue,
  7. AmlError,
  8. };
  9. use alloc::boxed::Box;
  10. /// Type 2 opcodes return a value and so can be used in expressions.
  11. pub fn type2_opcode<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  12. where
  13. 'c: 'a,
  14. {
  15. /*
  16. * Type2Opcode := DefAquire | DefAdd | DefAnd | DefBuffer | DefConcat | DefConcatRes |
  17. * DefCondRefOf | DefCopyObject | DefDecrement | DefDerefOf | DefDivide |
  18. * DefFindSetLeftBit | DefFindSetRightBit | DefFromBCD | DefIncrement | DefIndex |
  19. * DefLAnd | DefLEqual | DefLGreater | DefLGreaterEqual | DefLLess | DefLLessEqual |
  20. * DefMid | DefLNot | DefLNotEqual | DefLoadTable | DefLOr | DefMatch | DefMod |
  21. * DefMultiply | DefNAnd | DefNOr | DefNot | DefObjectType | DefOr | DefPackage |
  22. * DefVarPackage | DefRefOf | DefShiftLeft | DefShitRight | DefSizeOf | DefStore |
  23. * DefSubtract | DefTimer | DefToBCD | DefToBuffer | DefToDecimalString |
  24. * DefToHexString | DefToInteger | DefToString | DefWait | DefXOr | MethodInvocation
  25. */
  26. comment_scope_verbose("Type2Opcode", choice!(def_l_equal(), def_store(), method_invocation()))
  27. }
  28. fn def_l_equal<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  29. where
  30. 'c: 'a,
  31. {
  32. /*
  33. * DefLEqual := 0x93 Operand Operand
  34. * Operand := TermArg => Integer
  35. */
  36. opcode(opcode::DEF_L_EQUAL_OP)
  37. .then(comment_scope_verbose(
  38. "DefLEqual",
  39. term_arg().then(term_arg()).map(|(left_arg, right_arg)| {
  40. Ok(AmlValue::Boolean(left_arg.as_integer()? == right_arg.as_integer()?))
  41. }),
  42. ))
  43. .map(|((), result)| Ok(result))
  44. }
  45. fn def_store<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  46. where
  47. 'c: 'a,
  48. {
  49. /*
  50. * DefStore := 0x70 TermArg SuperName
  51. *
  52. * Implicit conversion is only applied when the destination target is a `Name` - not when we
  53. * are storing into a method local or argument (these stores are semantically identical to
  54. * CopyObject). We must also make sure to return a copy of the data that is in the destination
  55. * after the store (as opposed to the data we think we put into it), because some stores can
  56. * alter the data during the store.
  57. */
  58. opcode(opcode::DEF_STORE_OP)
  59. .then(comment_scope("DefStore", term_arg().then(super_name())))
  60. .map_with_context(|((), (value, target)), context| {
  61. match target {
  62. Target::Name(ref path) => {
  63. let handle =
  64. try_with_context!(context, context.namespace.search(path, &context.current_scope));
  65. let desired_type = context.namespace.get(handle).unwrap().type_of();
  66. let converted_object = try_with_context!(context, value.as_type(desired_type));
  67. *try_with_context!(context, context.namespace.get_mut(handle)) =
  68. AmlValue::Name(box converted_object);
  69. (Ok(context.namespace.get(handle).unwrap().clone()), context)
  70. }
  71. Target::Debug => {
  72. // TODO
  73. unimplemented!()
  74. }
  75. Target::Arg(arg_num) => {
  76. // TODO
  77. unimplemented!()
  78. }
  79. Target::Local(local_num) => {
  80. // TODO
  81. unimplemented!()
  82. }
  83. }
  84. })
  85. }
  86. fn method_invocation<'a, 'c>() -> impl Parser<'a, 'c, AmlValue>
  87. where
  88. 'c: 'a,
  89. {
  90. /*
  91. * MethodInvocation := NameString TermArgList
  92. *
  93. * MethodInvocation is the worst of the AML structures, because you're meant to figure out how
  94. * much you're meant to parse using the name of the method (by knowing from its definition how
  95. * how many arguments it takes). However, the definition of a method can in theory appear after
  96. * an invocation of that method, and so parsing them properly can be very difficult.
  97. * NOTE: We don't support the case of the definition appearing after the invocation.
  98. *
  99. * It's also not clear whether things that aren't methods can be "invoked" using
  100. * MethodInvocation with 0 arguments. It seems that references to DefNames can be encoded using
  101. * MethodInvocation, at least, and should just be looked up.
  102. */
  103. comment_scope_verbose(
  104. "MethodInvocation",
  105. name_string()
  106. .map_with_context(move |name, context| {
  107. let handle =
  108. try_with_context!(context, context.namespace.search(&name, &context.current_scope))
  109. .clone();
  110. (Ok(handle), context)
  111. })
  112. .feed(|handle| {
  113. id().map_with_context(move |(), context| {
  114. let object = try_with_context!(context, context.namespace.get(handle));
  115. match object.clone() {
  116. AmlValue::Name(boxed_value) => (Ok(unbox(boxed_value)), context),
  117. AmlValue::Method { ref code, .. } => {
  118. // TODO: before we do this, we need to restructure the structures to allow us
  119. // to execute control methods from inside other control methods
  120. // TODO
  121. unimplemented!()
  122. }
  123. _ => (Err(AmlError::IncompatibleValueConversion), context),
  124. }
  125. })
  126. }),
  127. )
  128. }
  129. /// An unfortunate helper method to unbox an owned, boxed value. `*x` is special-cased for `Box`
  130. /// here, but the compiler needs the type signature of the method to figure it out.
  131. fn unbox<T>(x: Box<T>) -> T {
  132. *x
  133. }