sim_kernel/eval/
runtime.rs1use crate::{
2 env::Cx,
3 error::{Error, Result},
4 eval::{Demand, Phase},
5 expr::Expr,
6 id::ClassId,
7 value::Value,
8};
9
10fn class_id_of(cx: &mut Cx, value: &Value) -> Result<Option<ClassId>> {
11 let class = value.object().class(cx)?;
12 Ok(class.object().as_class().map(|class| class.id()))
13}
14
15pub fn force_default(cx: &mut Cx, value: Value, demand: Demand) -> Result<Value> {
22 match demand {
23 Demand::Never => Ok(value),
24 Demand::Expr => {
25 let expr = value.object().as_expr(cx)?;
26 cx.factory().expr(expr)
27 }
28 Demand::Value => {
29 if let Some(thunk) = value.object().as_thunk() {
30 thunk.force(cx, demand)
31 } else {
32 Ok(value)
33 }
34 }
35 Demand::Bool => {
36 let forced = if let Some(thunk) = value.object().as_thunk() {
37 thunk.force(cx, demand)?
38 } else {
39 value
40 };
41 let truth = forced.object().truth(cx)?;
42 cx.factory().bool(truth)
43 }
44 Demand::Class(expected) => {
45 let forced = if let Some(thunk) = value.object().as_thunk() {
46 thunk.force(cx, demand)?
47 } else {
48 value
49 };
50 let found = class_id_of(cx, &forced)?.ok_or(Error::TypeMismatch {
51 expected: "class-backed value",
52 found: "non-class-backed value",
53 })?;
54 if found == expected {
55 Ok(forced)
56 } else {
57 Err(Error::WrongClass { expected, found })
58 }
59 }
60 Demand::Shape(_) => {
61 if let Some(thunk) = value.object().as_thunk() {
62 thunk.force(cx, demand)
63 } else {
64 Ok(value)
65 }
66 }
67 }
68}
69
70pub fn eval_expr_default(cx: &mut Cx, expr: Expr) -> Result<Value> {
78 let expr = cx.expand_macros(Phase::Eval, expr)?;
79 match expr {
80 Expr::Nil => cx.factory().nil(),
81 Expr::Bool(value) => cx.factory().bool(value),
82 Expr::Number(number) => cx.factory().number_literal(number.domain, number.canonical),
83 Expr::Symbol(symbol) => {
84 if let Some(value) = cx.env().get(&symbol) {
85 Ok(value.clone())
86 } else if let Ok(function) = cx.resolve_function(&symbol) {
87 Ok(function)
88 } else if let Ok(class) = cx.resolve_class(&symbol) {
89 Ok(class)
90 } else if let Ok(shape) = cx.resolve_shape(&symbol) {
91 Ok(shape)
92 } else if let Ok(value) = cx.resolve_value(&symbol) {
93 Ok(value)
94 } else {
95 cx.resolve_unbound_symbol(symbol)
96 }
97 }
98 Expr::Local(symbol) => cx.factory().expr(Expr::Local(symbol)),
99 Expr::String(value) => cx.factory().string(value),
100 Expr::Bytes(value) => cx.factory().bytes(value),
101 Expr::List(items) => {
102 let values = items
103 .into_iter()
104 .map(|item| eval_expr_default(cx, item))
105 .collect::<Result<Vec<_>>>()?;
106 cx.factory().list(values)
107 }
108 Expr::Vector(items) => {
109 let values = items
110 .into_iter()
111 .map(|item| eval_expr_default(cx, item))
112 .collect::<Result<Vec<_>>>()?;
113 cx.factory().list(values)
114 }
115 Expr::Map(entries) => {
116 let entries = entries
117 .into_iter()
118 .map(|(key, value)| {
119 let key_expr = eval_expr_default(cx, key)?.object().as_expr(cx)?;
120 let Expr::Symbol(key_symbol) = key_expr else {
121 return Err(Error::TypeMismatch {
122 expected: "symbol key",
123 found: "non-symbol key",
124 });
125 };
126 Ok((key_symbol, eval_expr_default(cx, value)?))
127 })
128 .collect::<Result<Vec<_>>>()?;
129 cx.factory().table(entries)
130 }
131 Expr::Set(items) => {
132 let values = items
133 .into_iter()
134 .map(|item| eval_expr_default(cx, item))
135 .collect::<Result<Vec<_>>>()?;
136 cx.factory().list(values)
137 }
138 Expr::Call { operator, args } => {
139 if let Expr::Symbol(name) = operator.as_ref()
140 && !cx.symbol_is_bound(name)
141 {
142 cx.resolve_unbound_call(name.clone(), args)
143 } else {
144 let callable = cx.eval_expr(*operator)?;
145 cx.call_exprs(callable, args)
146 }
147 }
148 Expr::Block(items) => {
149 let mut last = cx.factory().nil()?;
150 for item in items {
151 last = eval_expr_default(cx, item)?;
152 }
153 Ok(last)
154 }
155 Expr::Quote { expr, .. } => cx.factory().expr(*expr),
156 Expr::Annotated { expr, .. } => eval_expr_default(cx, *expr),
157 Expr::Extension { .. }
158 | Expr::Infix { .. }
159 | Expr::Prefix { .. }
160 | Expr::Postfix { .. } => cx.factory().expr(expr),
161 }
162}