mutable state

This commit is contained in:
me 2025-12-19 00:12:50 +02:00
parent 9618575f7a
commit a9e4875f1e
9 changed files with 181 additions and 231 deletions

View file

@ -12,16 +12,12 @@ pub fn var(str: &str) -> Expr {
Expr::Var(name(str)) Expr::Var(name(str))
} }
pub fn record(rec: Vec<(&str, Expr)>) -> Value { pub fn record(rec: Vec<(&str, Expr)>) -> Expr {
Value::Record(Record({ Expr::Record(
rec.into_iter() rec.into_iter()
.map(|(lbl, val)| (Label(lbl.into()), val)) .map(|(lbl, val)| (Label(lbl.into()), val))
.collect() .collect(),
})) )
}
pub fn record_expr(rec: Vec<(&str, Expr)>) -> Expr {
Expr::Value(record(rec))
} }
pub fn assign(name: &str, expr: Expr) -> Statement { pub fn assign(name: &str, expr: Expr) -> Statement {

View file

@ -1,7 +1,6 @@
//! Ast definition for Ayin. //! Ast definition for Ayin.
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::rc;
/// An expression. /// An expression.
#[derive(PartialEq, PartialOrd, Debug, Clone)] #[derive(PartialEq, PartialOrd, Debug, Clone)]
@ -135,19 +134,13 @@ impl From<&str> for Expr {
} }
} }
impl From<Vec<(&str, Expr)>> for Value {
fn from(rec: Vec<(&str, Expr)>) -> Value {
Value::Record(Record({
rec.into_iter()
.map(|(lbl, expr)| (Label(lbl.into()), expr))
.collect()
}))
}
}
impl From<Vec<(&str, Expr)>> for Expr { impl From<Vec<(&str, Expr)>> for Expr {
fn from(rec: Vec<(&str, Expr)>) -> Expr { fn from(rec: Vec<(&str, Expr)>) -> Expr {
Expr::Value(rec.into()) Expr::Record(
rec.into_iter()
.map(|(lbl, expr)| (Label(lbl.into()), expr))
.collect(),
)
} }
} }
@ -203,7 +196,7 @@ impl From<Vec<Statement>> for Expr {
} }
impl Record { impl Record {
pub fn get(&self, label: &Label) -> Result<&Expr, Error> { pub fn get(&self, label: &Label) -> Result<&Ref, Error> {
match self.0.get(label) { match self.0.get(label) {
Some(v) => Ok(v), Some(v) => Ok(v),
None => Err(Error::LabelNotFound(label.clone())), None => Err(Error::LabelNotFound(label.clone())),

View file

@ -1,6 +1,7 @@
//! Interpreter for Ayin. //! Interpreter for Ayin.
use super::types::*; use super::types::*;
use std::collections::BTreeMap;
use crate::ast; use crate::ast;
@ -46,7 +47,7 @@ fn eval_statement(
}) => { }) => {
let mut result = eval_expr(expr_env, state, expr)?; let mut result = eval_expr(expr_env, state, expr)?;
if *mutable { if *mutable {
let reference = state.insert_variable(result); let reference = state.variables.insert(result);
result = ast::Value::Ref(reference); result = ast::Value::Ref(reference);
} }
expr_env.insert(name.clone(), result.clone()); expr_env.insert(name.clone(), result.clone());
@ -91,7 +92,7 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
Ok::<Option<ast::Value>, Error>(Some(result)) Ok::<Option<ast::Value>, Error>(Some(result))
} }
StatementResult::Return(result) => { StatementResult::Return(result) => {
return Ok::<Option<ast::Value>, Error>(Some(result)); Ok::<Option<ast::Value>, Error>(Some(result))
} }
} }
})? { })? {
@ -101,11 +102,7 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
} }
} }
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? { ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
ast::Value::Record(record) => eval_expr( ast::Value::Record(record) => Ok(state.variables.get(record.get(&field)?).clone()),
expr_env,
state,
&record.get(field).map_err(Error::from)?.clone(),
),
v => Err(Error::NotARecord(v)), v => Err(Error::NotARecord(v)),
}, },
ast::Expr::Var(var) => { ast::Expr::Var(var) => {
@ -140,67 +137,61 @@ fn eval_expr(expr_env: &Env, state: &mut State, expr: &ast::Expr) -> Result<ast:
_ => Ok(v.clone()), _ => Ok(v.clone()),
}, },
ast::Expr::Op { lhs, rhs, op } => match op { ast::Expr::Op { lhs, rhs, op } => match op {
ast::Op::Assign => match &**lhs { ast::Op::Assign => match eval_expr_shallow(expr_env, state, lhs)? {
ast::Expr::Var(name) => { ast::Value::Ref(reference) => {
let rhs = eval_expr(expr_env, state, rhs)?; let rhs = eval_expr(expr_env, state, rhs)?;
state state.variables.set(reference, rhs.clone());
.envs Ok(rhs)
.get_mut(&expr_env.name)
.unwrap()
.insert(name.clone(), rhs);
eval_expr(expr_env, state, &ast::UNIT)
}
// access via labels
ast::Expr::Access { expr, field } => {
let lhs = eval_expr(expr_env, state, lhs)?;
let rhs = eval_expr(expr_env, state, rhs)?;
if let Some(mut nested_field) =
access_nested_field(expr_env, state, expr, field)?
{
todo!()
} else {
todo!() // error nested field unreachable
}
} }
_ => todo!(), _ => todo!(),
}, },
/*
_ => { _ => {
let _lhs = eval_expr(expr_env, state, lhs)?; let _lhs = eval_expr(expr_env, state, lhs)?;
let _rhs = eval_expr(expr_env, state, rhs)?; let _rhs = eval_expr(expr_env, state, rhs)?;
todo!() todo!()
} }
*/
}, },
ast::Expr::Record(record) => {
let mut map = BTreeMap::new();
for (field, expr) in record {
let value = eval_expr(expr_env, state, expr)?;
let reference = state.variables.insert(value);
map.insert(field.clone(), reference);
}
Ok(ast::Value::Record(ast::Record(map)))
}
ast::Expr::Vector(vector) => {
let mut vec = Vec::with_capacity(vector.len());
for expr in vector {
let value = eval_expr(expr_env, state, expr)?;
let reference = state.variables.insert(value);
vec.push(reference);
}
Ok(ast::Value::Vector(ast::Vector(vec)))
} }
} }
fn access_nested_field( }
fn eval_expr_shallow(
expr_env: &Env, expr_env: &Env,
state: &State, state: &mut State,
expr: &ast::Expr, expr: &ast::Expr,
labels: &[ast::Label], ) -> Result<ast::Value, Error> {
) -> Result<ast::Ref, Error> { match expr {
let lhs = eval_expr(&expr_env, state, expr)?; ast::Expr::Var(var) => {
match lhs { let result = expr_env.get(&var)?;
ast::Value::Ref(reference) => { match result {
let mut current_ref = reference.clone(); ast::Value::Ref(_) => Ok(result.clone()),
let mut current: ast::Value = state.get_variable(&reference); v => Err(Error::NotAReference(v.clone())),
for label in labels {
match current {
ast::Value::Record(record) => {
if let Some(next) = record.0.get(label) {
current_ref = next;
current = state.get_variable(&current_ref);
} else {
todo!()
} }
} }
// vector, closure ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
_ => todo!(), // unexpected ast::Value::Record(record) => Ok(ast::Value::Ref(record.get(&field)?.clone())),
} v => Err(Error::NotARecord(v)),
} },
Ok(current_ref) _ => eval_expr(expr_env, state, expr),
}
_ => todo!(),
} }
} }
@ -227,7 +218,7 @@ fn defs_to_env(
), ),
}; };
if mutable { if mutable {
let reference = state.insert_variable(closure); let reference = state.variables.insert(closure);
env.insert_nodup(&name, ast::Value::Ref(reference))?; env.insert_nodup(&name, ast::Value::Ref(reference))?;
} else { } else {
env.insert_nodup(&name, closure)?; env.insert_nodup(&name, closure)?;

View file

@ -23,6 +23,8 @@ pub enum Error {
NotAFunction(ast::Expr), NotAFunction(ast::Expr),
#[error("Not a record {0:?}")] #[error("Not a record {0:?}")]
NotARecord(ast::Value), NotARecord(ast::Value),
#[error("Not a reference {0:?}")]
NotAReference(ast::Value),
#[error("Not a boolean {0:?}")] #[error("Not a boolean {0:?}")]
NotABoolean(ast::Value), NotABoolean(ast::Value),
#[error("Arguments mismatch")] #[error("Arguments mismatch")]
@ -55,20 +57,40 @@ pub struct State {
pub name: String, pub name: String,
env_namer: Namer, env_namer: Namer,
pub envs: Envs, pub envs: Envs,
variable_namer: Namer,
pub variables: Variables, pub variables: Variables,
} }
pub struct Variables(pub HashMap<ast::Ref, ast::Value>); pub struct Variables {
pub vars: HashMap<ast::Ref, ast::Value>,
namer: Namer,
}
impl Variables {
pub fn new() -> Self {
Variables {
vars: HashMap::new(),
namer: Namer::new(),
}
}
pub fn insert(&mut self, value: ast::Value) -> ast::Ref {
let name = ast::Ref(self.namer.next());
self.vars.insert(name.clone(), value);
name
}
pub fn get<'a>(&'a self, reference: &ast::Ref) -> &'a ast::Value {
self.vars.get(reference).unwrap()
}
pub fn set(&mut self, reference: ast::Ref, new_value: ast::Value) {
self.vars.insert(reference, new_value);
}
}
impl State { impl State {
pub fn new(name: String) -> State { pub fn new(name: String) -> State {
State { State {
name, name,
env_namer: Namer::new(), env_namer: Namer::new(),
envs: Envs(BTreeMap::new()), envs: Envs(BTreeMap::new()),
variable_namer: Namer::new(), variables: Variables::new(),
variables: Variables(HashMap::new()),
} }
} }
pub fn generate_env(&mut self, env: Env) -> Result<ast::EnvName, Error> { pub fn generate_env(&mut self, env: Env) -> Result<ast::EnvName, Error> {
@ -76,18 +98,6 @@ impl State {
self.envs.insert(&env_name, env)?; self.envs.insert(&env_name, env)?;
Ok(env_name) Ok(env_name)
} }
pub fn insert_variable(&mut self, value: ast::Value) -> ast::Ref {
let name = ast::Ref(self.variable_namer.next());
self.variables.0.insert(name.clone(), Rc::new(value));
name
}
pub fn get_variable<'a>(&'a self, reference: &ast::Ref) -> &'a ast::Value {
self.variables.0.get(reference).unwrap()
}
pub fn set_variable(&mut self, reference: ast::Ref, new_value: ast::Value) {
self.variables.0.insert(reference, new_value)
}
} }
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Clone)]

View file

@ -10,17 +10,13 @@ Ok(
), ),
), ),
op: Assign, op: Assign,
rhs: Value( rhs: Vector(
Vector(
Vector(
[ [
Value( Value(
Int( Int(
2, 2,
), ),
), ),
Value(
Record(
Record( Record(
{ {
Label( Label(
@ -32,11 +28,7 @@ Ok(
), ),
}, },
), ),
),
),
], ],
), ),
),
),
}, },
) )

View file

@ -16,21 +16,15 @@ Ok(
[ [
Return( Return(
Some( Some(
Value(
Record(
Record( Record(
{ {
Label( Label(
"player", "player",
): Value( ): Record(
Record(
Record(
{ {
Label( Label(
"position", "position",
): Value( ): Record(
Record(
Record(
{ {
Label( Label(
"x", "x",
@ -48,18 +42,12 @@ Ok(
), ),
}, },
), ),
),
),
}, },
), ),
),
),
}, },
), ),
), ),
), ),
),
),
], ],
), ),
}, },
@ -175,15 +163,11 @@ Ok(
[ [
Return( Return(
Some( Some(
Value(
Record(
Record( Record(
{ {
Label( Label(
"player", "player",
): Value( ): Record(
Record(
Record(
{ {
Label( Label(
"pos", "pos",
@ -204,14 +188,10 @@ Ok(
}, },
}, },
), ),
),
),
}, },
), ),
), ),
), ),
),
),
], ],
), ),
}, },

View file

@ -3,8 +3,6 @@ source: src/parser/parser.rs
expression: result expression: result
--- ---
Ok( Ok(
Value(
Record(
Record( Record(
{ {
Label( Label(
@ -23,6 +21,4 @@ Ok(
), ),
}, },
), ),
),
),
) )

View file

@ -3,8 +3,6 @@ source: src/parser/parser.rs
expression: result expression: result
--- ---
Ok( Ok(
Value(
Vector(
Vector( Vector(
[ [
Var( Var(
@ -29,6 +27,4 @@ Ok(
), ),
], ],
), ),
),
),
) )

View file

@ -3,11 +3,7 @@ source: src/parser/parser.rs
expression: result expression: result
--- ---
Ok( Ok(
Value(
Vector(
Vector( Vector(
[], [],
), ),
),
),
) )