diff --git a/src/ast/types.rs b/src/ast/types.rs index 6f180a9..39dd092 100644 --- a/src/ast/types.rs +++ b/src/ast/types.rs @@ -204,7 +204,8 @@ impl Record { } } -pub const UNIT: Expr = Expr::Value(Value::Record(Record(BTreeMap::new()))); +pub const UNIT_VALUE: Value = Value::Record(Record(BTreeMap::new())); +pub const UNIT: Expr = Expr::Value(UNIT_VALUE); #[derive(PartialEq, Debug, thiserror::Error)] pub enum Error { diff --git a/src/interpret/interpret.rs b/src/interpret/interpret.rs index e98e323..b2ca6c5 100644 --- a/src/interpret/interpret.rs +++ b/src/interpret/interpret.rs @@ -5,29 +5,44 @@ use std::collections::BTreeMap; use crate::ast; -pub fn run( - program: ast::Program, +pub fn global_env_name() -> ast::EnvName { + ast::EnvName("global".to_string()) +} + +pub fn setup(program: ast::Program) -> Result { + let mut state = State::new(global_env_name().0.clone()); + + defs_to_env(program.0, &global_env_name(), &mut state)?; + Ok(state) +} + +pub fn interpret( + state: &mut State, func: ast::Name, args: Vec, ) -> Result { - let env_name = ast::EnvName("global".to_string()); - let mut state = State::new("global".into()); - - defs_to_env(program.0, &env_name, &mut state)?; - - let main = ast::Expr::Value(state.envs.get(&env_name)?.get(&func)?.clone()); + let main = ast::Expr::Value(state.envs.get(&global_env_name())?.get(&func)?.clone()); let expr = ast::Expr::FunCall { func: Box::new(main), args, }; - let env: Env = state.envs.get(&env_name)?.clone(); - let result = eval_expr(&env, &mut state, &expr)?; + let env: Env = state.envs.get(&global_env_name())?.clone(); + let result = eval_expr(&env, state, &expr)?; Ok(result) } +pub fn run( + program: ast::Program, + func: ast::Name, + args: Vec, +) -> Result { + let mut state = setup(program)?; + interpret(&mut state, func, args) +} + enum StatementResult { Result(ast::Value), Return(ast::Value), @@ -230,6 +245,33 @@ fn defs_to_env( Ok(()) } +pub fn value_to_stadnalone_expr(state: &State, value: ast::Value) -> Result { + match value { + ast::Value::Ref(reference) => { + let value = state.variables.get(&reference).clone(); + value_to_stadnalone_expr(state, value) + } + ast::Value::Vector(vector) => { + let mut vec = Vec::with_capacity(vector.0.len()); + for reference in vector.0 { + let expr = value_to_stadnalone_expr(state, ast::Value::Ref(reference))?; + vec.push(expr); + } + Ok(ast::Expr::Vector(vec)) + } + ast::Value::Record(record) => { + let mut map = BTreeMap::new(); + for (field, reference) in record.0 { + let expr = value_to_stadnalone_expr(state, ast::Value::Ref(reference))?; + map.insert(field.clone(), expr); + } + Ok(ast::Expr::Record(map)) + } + ast::Value::Closure { .. } => Err("Closure migration not supported".into()), + _ => Ok(ast::Expr::Value(value)), + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/interpret/mod.rs b/src/interpret/mod.rs index a84e1c0..1f1133c 100644 --- a/src/interpret/mod.rs +++ b/src/interpret/mod.rs @@ -4,3 +4,4 @@ pub mod interpret; pub mod types; pub use interpret::*; +pub use types::*; diff --git a/src/main.rs b/src/main.rs index 2f03ce0..57d636e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use ayin::ast; use ayin::runtime::*; use macroquad::prelude::*; @@ -16,7 +17,7 @@ async fn main() { env_logger::init(); info!("Hello, 👁️‍🗨️!"); - let mut state = setup().await; + let mut state = setup(ast::Program(vec![])).await; loop { let events = fetch_events(); diff --git a/src/runtime/runtime.rs b/src/runtime/runtime.rs index ff4915c..0b61657 100644 --- a/src/runtime/runtime.rs +++ b/src/runtime/runtime.rs @@ -1,13 +1,64 @@ use super::types::*; use crate::ast; +use crate::interpret; use macroquad::prelude::*; -pub async fn setup() -> State { +pub async fn setup(code: ast::Program) -> State { let font = load_ttf_font("./assets/fonts/monogram.ttf").await.unwrap(); + let mut state = match interpret::setup(code) { + Ok(state) => state, + Err(err) => { + println!("Error: {}", err); + interpret::State::new("game".into()) + } + }; + let game_state = match interpret::interpret(&mut state, "setup".into(), vec![]) { + Ok(result) => result, + Err(err) => { + println!("Error: {}", err); + ast::UNIT_VALUE + } + }; + State { assets: Assets { font }, - code: ast::Program(vec![]), + state, + game_state, + } +} + +pub async fn migrate(mut state: State, code: ast::Program) -> State { + match interpret::setup(code) { + Err(err) => { + println!("Error: {}", err); + state + } + Ok(mut new_program_state) => { + match interpret::value_to_stadnalone_expr(&state.state, state.game_state.clone()) { + Err(err) => { + println!("Error: {}", err); + state + } + Ok(expanded_game_state) => { + match interpret::interpret( + &mut new_program_state, + "migrate".into(), + vec![expanded_game_state], + ) { + Err(err) => { + println!("Error: {}", err); + state + } + Ok(result) => { + state.game_state = result; + state.state = new_program_state; + state + } + } + } + } + } } } diff --git a/src/runtime/types.rs b/src/runtime/types.rs index 7be8c8c..5706286 100644 --- a/src/runtime/types.rs +++ b/src/runtime/types.rs @@ -1,9 +1,11 @@ use crate::ast; +use crate::interpret; use macroquad::prelude::*; pub struct State { pub assets: Assets, - pub code: ast::Program, + pub state: interpret::types::State, + pub game_state: ast::Value, } pub struct Assets {