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