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))
}
pub fn record(rec: Vec<(&str, Expr)>) -> Value {
Value::Record(Record({
pub fn record(rec: Vec<(&str, Expr)>) -> Expr {
Expr::Record(
rec.into_iter()
.map(|(lbl, val)| (Label(lbl.into()), val))
.collect()
}))
}
pub fn record_expr(rec: Vec<(&str, Expr)>) -> Expr {
Expr::Value(record(rec))
.collect(),
)
}
pub fn assign(name: &str, expr: Expr) -> Statement {

View file

@ -1,7 +1,6 @@
//! Ast definition for Ayin.
use std::collections::BTreeMap;
use std::rc;
/// An expression.
#[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 {
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 {
pub fn get(&self, label: &Label) -> Result<&Expr, Error> {
pub fn get(&self, label: &Label) -> Result<&Ref, Error> {
match self.0.get(label) {
Some(v) => Ok(v),
None => Err(Error::LabelNotFound(label.clone())),

View file

@ -1,6 +1,7 @@
//! Interpreter for Ayin.
use super::types::*;
use std::collections::BTreeMap;
use crate::ast;
@ -46,7 +47,7 @@ fn eval_statement(
}) => {
let mut result = eval_expr(expr_env, state, expr)?;
if *mutable {
let reference = state.insert_variable(result);
let reference = state.variables.insert(result);
result = ast::Value::Ref(reference);
}
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))
}
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::Value::Record(record) => eval_expr(
expr_env,
state,
&record.get(field).map_err(Error::from)?.clone(),
),
ast::Value::Record(record) => Ok(state.variables.get(record.get(&field)?).clone()),
v => Err(Error::NotARecord(v)),
},
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()),
},
ast::Expr::Op { lhs, rhs, op } => match op {
ast::Op::Assign => match &**lhs {
ast::Expr::Var(name) => {
ast::Op::Assign => match eval_expr_shallow(expr_env, state, lhs)? {
ast::Value::Ref(reference) => {
let rhs = eval_expr(expr_env, state, rhs)?;
state
.envs
.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
}
state.variables.set(reference, rhs.clone());
Ok(rhs)
}
_ => todo!(),
},
/*
_ => {
let _lhs = eval_expr(expr_env, state, lhs)?;
let _rhs = eval_expr(expr_env, state, rhs)?;
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,
state: &State,
state: &mut State,
expr: &ast::Expr,
labels: &[ast::Label],
) -> Result<ast::Ref, Error> {
let lhs = eval_expr(&expr_env, state, expr)?;
match lhs {
ast::Value::Ref(reference) => {
let mut current_ref = reference.clone();
let mut current: ast::Value = state.get_variable(&reference);
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!()
) -> Result<ast::Value, Error> {
match expr {
ast::Expr::Var(var) => {
let result = expr_env.get(&var)?;
match result {
ast::Value::Ref(_) => Ok(result.clone()),
v => Err(Error::NotAReference(v.clone())),
}
}
// vector, closure
_ => todo!(), // unexpected
}
}
Ok(current_ref)
}
_ => todo!(),
ast::Expr::Access { expr, field } => match eval_expr(expr_env, state, expr)? {
ast::Value::Record(record) => Ok(ast::Value::Ref(record.get(&field)?.clone())),
v => Err(Error::NotARecord(v)),
},
_ => eval_expr(expr_env, state, expr),
}
}
@ -227,7 +218,7 @@ fn defs_to_env(
),
};
if mutable {
let reference = state.insert_variable(closure);
let reference = state.variables.insert(closure);
env.insert_nodup(&name, ast::Value::Ref(reference))?;
} else {
env.insert_nodup(&name, closure)?;

View file

@ -23,6 +23,8 @@ pub enum Error {
NotAFunction(ast::Expr),
#[error("Not a record {0:?}")]
NotARecord(ast::Value),
#[error("Not a reference {0:?}")]
NotAReference(ast::Value),
#[error("Not a boolean {0:?}")]
NotABoolean(ast::Value),
#[error("Arguments mismatch")]
@ -55,20 +57,40 @@ pub struct State {
pub name: String,
env_namer: Namer,
pub envs: Envs,
variable_namer: Namer,
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 {
pub fn new(name: String) -> State {
State {
name,
env_namer: Namer::new(),
envs: Envs(BTreeMap::new()),
variable_namer: Namer::new(),
variables: Variables(HashMap::new()),
variables: Variables::new(),
}
}
pub fn generate_env(&mut self, env: Env) -> Result<ast::EnvName, Error> {
@ -76,18 +98,6 @@ impl State {
self.envs.insert(&env_name, env)?;
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)]

View file

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

View file

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

View file

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

View file

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

View file

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