Created
January 6, 2025 21:49
-
-
Save Eastwooder/100df7445b491fec09668d015c6ea0f1 to your computer and use it in GitHub Desktop.
Revisions
-
Eastwooder created this gist
Jan 6, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,9 @@ [package] name = "starlark-playground" version = "0.1.0" edition = "2021" [dependencies] allocative = "0.3.4" indoc = "2.0.5" starlark = "0.13.0" This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,89 @@ use allocative::Allocative; use indoc::indoc; use starlark::any::ProvidesStaticType; use starlark::environment::{GlobalsBuilder, Module}; use starlark::eval::Evaluator; use starlark::syntax::{AstModule, Dialect}; use starlark::values::none::NoneType; use starlark::values::{starlark_value, Heap, NoSerialize, StarlarkValue, Value}; use starlark::{starlark_module, starlark_simple_value}; use std::cell::RefCell; use std::fmt::{Display, Formatter}; fn main() -> starlark::Result<()> { let content = indoc! {" def my_loop(members): for item in members: emit(item) emit(fetch().name) my_loop(fetch().members) "}; let ast = AstModule::parse("complex.star", content.to_owned(), &Dialect::Standard)?; let globals = GlobalsBuilder::new().with(starlark_fetch).build(); let module = Module::new(); let store = Store::default(); { let mut eval = Evaluator::new(&module); eval.extra = Some(&store); let _ = eval.eval_module(ast, &globals)?; } for emitted in &*store.0.borrow() { println!("emitted: {emitted}"); } Ok(()) } // Define a store in which to accumulate JSON strings #[derive(Debug, ProvidesStaticType, Default)] struct Store(RefCell<Vec<String>>); impl Store { fn add(&self, x: String) { self.0.borrow_mut().push(x) } } #[starlark_module] fn starlark_fetch(builder: &mut GlobalsBuilder) { fn fetch(eval: &mut Evaluator) -> starlark::Result<Extr> { Ok(Extr { name: "test".to_string(), members: vec!["a".to_string(), "b".to_string()], }) } fn emit(x: Value, eval: &mut Evaluator) -> starlark::Result<NoneType> { // We modify extra (which we know is a Store) and add the JSON of the // value the user gave. eval.extra .unwrap() .downcast_ref::<Store>() .unwrap() .add(x.to_json()?); Ok(NoneType) } } #[derive(Debug, Clone, ProvidesStaticType, NoSerialize, Allocative)] pub struct Extr { pub name: String, pub members: Vec<String>, } starlark_simple_value!(Extr); impl Display for Extr { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "Extr[name={name}]", name = self.name) } } #[starlark_value(type = "Extr")] impl<'v> StarlarkValue<'v> for Extr { fn get_attr(&self, attribute: &str, heap: &'v Heap) -> Option<Value<'v>> { match attribute { "name" => Some(heap.alloc(self.name.clone())), "members" => Some(heap.alloc(self.members.clone())), _ => None, } } }