Repository: ergoplatform/sigma-rust (language: rust)

Issue:
[100 SigmaUSD] `Context.selfBoxIndex` method
- Add `SMethod` to `ergotree-ir::types::scontext`(method id is 8); 
- Add `EvalFn` in `ertotree-interpreter::eval::scontext` and include it in `ergotree-interpreter::eval::smethod_eval_fn`. Implementation details: return index of `Context::self_box` in `Context::inputs`.

See existing method implementations in `scoll` and `sbox` for examples;


Discussion / hints:
Howdy 👋 

I'm going to have a shot at this one

Fix patch:
diff --git a/ergotree-interpreter/src/eval.rs b/ergotree-interpreter/src/eval.rs
index cb872e5ef..0d4db7c1a 100644
--- a/ergotree-interpreter/src/eval.rs
+++ b/ergotree-interpreter/src/eval.rs
@@ -194,9 +194,16 @@ type EvalFn = fn(env: &Env, ctx: &mut EvalContext, Value, Vec<Value>) -> Result<
 fn smethod_eval_fn(method: &SMethod) -> Result<EvalFn, EvalError> {
     use ergotree_ir::types::*;
     Ok(match method.obj_type.type_code() {
-        scontext::TYPE_CODE if method.method_id() == scontext::DATA_INPUTS_PROPERTY_METHOD_ID => {
-            self::scontext::DATA_INPUTS_EVAL_FN
-        }
+        scontext::TYPE_CODE => match method.method_id() {
+            scontext::DATA_INPUTS_PROPERTY_METHOD_ID => self::scontext::DATA_INPUTS_EVAL_FN,
+            scontext::SELF_BOX_INDEX_PROPERTY_METHOD_ID => self::scontext::SELF_BOX_INDEX_EVAL_FN,
+            method_id => {
+                return Err(EvalError::NotFound(format!(
+                    "Eval fn: unknown method id in SContext: {:?}",
+                    method_id
+                )))
+            }
+        },
         sbox::TYPE_CODE => match method.method_id() {
             sbox::VALUE_METHOD_ID => self::sbox::VALUE_EVAL_FN,
             sbox::GET_REG_METHOD_ID => self::sbox::GET_REG_EVAL_FN,
diff --git a/ergotree-interpreter/src/eval/scontext.rs b/ergotree-interpreter/src/eval/scontext.rs
index 85ce8246e..43a3ac005 100644
--- a/ergotree-interpreter/src/eval/scontext.rs
+++ b/ergotree-interpreter/src/eval/scontext.rs
@@ -23,3 +23,58 @@ pub(crate) static DATA_INPUTS_EVAL_FN: EvalFn = |_env, ctx, obj, _args| {
         elem_tpe: SType::SBox,
     }))
 };
+
+pub(crate) static SELF_BOX_INDEX_EVAL_FN: EvalFn = |_env, ctx, obj, _args| {
+    if obj != Value::Context {
+        return Err(EvalError::UnexpectedValue(format!(
+            "Context.selfBoxIndex: expected object of Value::Context, got {:?}",
+            obj
+        )));
+    }
+    let box_index = ctx
+        .ctx
+        .inputs
+        .clone()
+        .into_iter()
+        .position(|it| it == ctx.ctx.self_box)
+        .ok_or_else(|| EvalError::NotFound("Context.selfBoxIndex: box not found".to_string()))?;
+    Ok(Value::Int(box_index as i32))
+};
+
+#[cfg(test)]
+#[cfg(feature = "arbitrary")]
+mod tests {
+    use crate::eval::context::ir_ergo_box_dummy::IrErgoBoxDummy;
+    use crate::eval::context::Context;
+    use crate::eval::tests::eval_out;
+    use ergotree_ir::mir::expr::Expr;
+    use ergotree_ir::mir::property_call::PropertyCall;
+    use ergotree_ir::types::scontext;
+    use sigma_test_util::force_any_val;
+    use std::rc::Rc;
+
+    fn make_ctx_inputs_includes_self_box() -> Context {
+        let ctx = force_any_val::<Context>();
+        let self_box = force_any_val::<IrErgoBoxDummy>();
+        let inputs = vec![
+            force_any_val::<IrErgoBoxDummy>().id.clone(),
+            self_box.id.clone(),
+        ];
+        Context {
+            height: 0u32,
+            self_box: self_box.id.clone(),
+            inputs,
+            ..ctx
+        }
+    }
+
+    #[test]
+    fn eval_self_box_index() {
+        let expr: Expr =
+            PropertyCall::new(Expr::Context, scontext::SELF_BOX_INDEX_PROPERTY.clone())
+                .unwrap()
+                .into();
+        let rc = Rc::new(make_ctx_inputs_includes_self_box());
+        assert_eq!(eval_out::<i32>(&expr, rc.clone()), 1);
+    }
+}
diff --git a/ergotree-ir/src/types/scontext.rs b/ergotree-ir/src/types/scontext.rs
index dae082006..5ca9fdace 100644
--- a/ergotree-ir/src/types/scontext.rs
+++ b/ergotree-ir/src/types/scontext.rs
@@ -120,7 +120,7 @@ lazy_static! {
         property("selfBoxIndex", SInt, SELF_BOX_INDEX_PROPERTY_METHOD_ID);
 }
 lazy_static! {
-    static ref SELF_BOX_INDEX_PROPERTY: SMethod = SMethod::new(
+    pub static ref SELF_BOX_INDEX_PROPERTY: SMethod = SMethod::new(
         STypeCompanion::Context,
         SELF_BOX_INDEX_PROPERTY_METHOD_DESC.clone()
     );


Test patch: