cpclib_asm/implementation/
expression.rs1use std::fmt::Display;
2
3use cpclib_common::itertools::Itertools;
4use cpclib_tokens::symbols::*;
5use cpclib_tokens::tokens::*;
6
7use crate::assembler::Env;
8use crate::error::{ExpressionError, *};
9use crate::implementation::tokens::TokenExt;
10use crate::{SymbolFor, UnaryFunction};
11
12pub fn ensure_orgams_type(e: ExprResult, env: &Env) -> Result<ExprResult, AssemblerError> {
14 let e = if env.options().parse_options().is_orgams() {
15 match &e {
16 ExprResult::Float(_)
17 | ExprResult::Value(_)
18 | ExprResult::Char(_)
19 | ExprResult::Bool(_) => ExprResult::Value(e.int()?),
20 ExprResult::String(s) => e,
21 _ => {
22 return Err(AssemblerError::AlreadyRenderedError(format!(
23 "Incompatible type with orgams {:?}",
24 e
25 )));
26 }
27 }
28 }
29 else {
30 e
31 };
32
33 Ok(e)
34}
35
36pub trait ExprEvaluationExt: Display {
42 fn eval(&self) -> Result<ExprResult, AssemblerError> {
44 let mut env = Env::default();
45 self.resolve(&mut env)
46 }
47
48 fn resolve(&self, env: &mut Env) -> Result<ExprResult, AssemblerError>;
50
51 fn symbols_used(&self) -> Vec<&str>;
53}
54
55#[macro_export]
56macro_rules! resolve_impl {
57
58 ($self: ident, $env: ident) => { {
59 use std::ops::Neg;
60 use cpclib_tokens::symbols::SymbolsTableTrait;
61
62
63struct UnaryFunctionWrapper<'a, E:ExprEvaluationExt> {
65 func: UnaryFunction,
66 arg: &'a E
67}
68
69
70impl<'a, E:ExprEvaluationExt> std::fmt::Display for UnaryFunctionWrapper<'a,E> {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
72 write!(f, "{}({})", self.func, self.arg)
73 }
74}
75
76impl<'a, E:ExprEvaluationExt> UnaryFunctionWrapper<'a, E> {
77 fn new(func: UnaryFunction, arg: &'a E) -> UnaryFunctionWrapper<'a,E> {
78 UnaryFunctionWrapper { func, arg }
79 }
80}
81
82impl<'a, E:ExprEvaluationExt> ExprEvaluationExt for UnaryFunctionWrapper<'a,E> {
83
84
85 fn symbols_used(&self) -> Vec<&str> {
86 self.arg.symbols_used()
87 }
88
89 fn resolve(&self, env: &mut Env) -> Result<ExprResult, AssemblerError> {
91 let arg = self.arg.resolve(env)?;
92
93 let res = match self.func {
94 UnaryFunction::High => {
95 ((arg >> 8.into())? & 0xFF.into())
96 .map_err(|e| AssemblerError::ExpressionTypeError(e))
97 }
98 UnaryFunction::Low => {
99 (arg & 0xFF.into()).map_err(|e| AssemblerError::ExpressionTypeError(e))
100 }
101 UnaryFunction::Memory => {
102 if arg < 0.into() || arg > 0xFFFF.into() {
103 return Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
104 Box::new(AssemblerError::AssemblingError {
105 msg: format!("Impossible to read memory address 0x{:X}", arg)
106 })
107 )));
108 }
109 else {
110 Ok(env
111 .peek(&env.logical_to_physical_address(arg.int()? as _))
112 .into())
113 }
114 }
115 UnaryFunction::Floor => {
116 (arg.floor()).map_err(|e| AssemblerError::ExpressionTypeError(e))
117 }
118 UnaryFunction::Ceil => (arg.ceil()).map_err(|e| AssemblerError::ExpressionTypeError(e)),
119 UnaryFunction::Frac => (arg.frac()).map_err(|e| AssemblerError::ExpressionTypeError(e)),
120 UnaryFunction::Int => {
121 (arg.int())
122 .map(|i| i.into())
123 .map_err(|e| AssemblerError::ExpressionTypeError(e))
124 }
125 UnaryFunction::Char => {
126 (arg.char())
127 .map(|i| i.into())
128 .map_err(|e| AssemblerError::ExpressionTypeError(e))
129 }
130 UnaryFunction::Sin => {
131 if env.options().parse_options().is_orgams() {
132 dbg!("We need to check things here");
133 dbg!(Ok((512.0*(arg.float()? * 3.1415926545 / (256.0/2.0)).sin()).into()))
134 } else {
135 arg.sin()
136 }.map_err(|e| AssemblerError::ExpressionTypeError(e))
137 },
138 UnaryFunction::Cos => (arg.cos()).map_err(|e| AssemblerError::ExpressionTypeError(e)),
139 UnaryFunction::ASin => (arg.asin()).map_err(|e| AssemblerError::ExpressionTypeError(e)),
140 UnaryFunction::ACos => (arg.acos()).map_err(|e| AssemblerError::ExpressionTypeError(e)),
141 UnaryFunction::Abs => (arg.abs()).map_err(|e| AssemblerError::ExpressionTypeError(e)),
142 UnaryFunction::Ln => (arg.ln()).map_err(|e| AssemblerError::ExpressionTypeError(e)),
143 UnaryFunction::Log10 => {
144 (arg.log10()).map_err(|e| AssemblerError::ExpressionTypeError(e))
145 }
146 UnaryFunction::Exp => (arg.exp()).map_err(|e| AssemblerError::ExpressionTypeError(e)),
147 UnaryFunction::Sqrt => (arg.sqrt()).map_err(|e| AssemblerError::ExpressionTypeError(e))
148 }?;
149
150
151 ensure_orgams_type(res, env)
152
153
154 }
155}
156
157
158struct BinaryFunctionWrapper<'a, E:ExprEvaluationExt> {
160 func: BinaryFunction,
161 arg1: &'a E,
162 arg2: &'a E
163}
164
165
166impl<'a, E:ExprEvaluationExt> std::fmt::Display for BinaryFunctionWrapper<'a,E> {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
168 write!(f, "{}({},{})", self.func, self.arg1, self.arg2)
169 }
170}
171
172
173
174impl<'a, E:ExprEvaluationExt> BinaryFunctionWrapper<'a, E> {
175 fn new(func: BinaryFunction, arg1: &'a E, arg2: &'a E) -> Self {
176 BinaryFunctionWrapper { func, arg1, arg2 }
177 }
178}
179
180impl<'a, E:ExprEvaluationExt> ExprEvaluationExt for BinaryFunctionWrapper<'a, E> {
181 fn symbols_used(&self) -> Vec<&str> {
182 self.arg1
183 .symbols_used()
184 .into_iter()
185 .chain(self.arg2.symbols_used().into_iter())
186 .collect_vec()
187 }
188
189 fn resolve(&self, env: &mut Env) -> Result<ExprResult, AssemblerError> {
190 let arg1 = self.arg1.resolve(env)?;
191 let arg2 = self.arg2.resolve(env)?;
192
193 let res = match self.func {
194 BinaryFunction::Min => Ok(arg1.min(arg2)),
195 BinaryFunction::Max => Ok(arg1.max(arg2)),
196 BinaryFunction::Pow => {
197 let power = arg2.int()?;
198 match arg1 {
199 ExprResult::Float(f) => Ok(f.into_inner().powf(power as f64).into()),
200 ExprResult::Value(v) => Ok(v.pow(power as _).into()),
201
202 ExprResult::List(_) => {
203 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
204 Box::new(AssemblerError::AssemblingError {
205 msg: format!("pow cannot be applied to a list")
206 })
207 )))
208 },
209
210 _ => {
211 Err(AssemblerError::ExpressionError(ExpressionError::OwnError(
212 Box::new(AssemblerError::AssemblingError {
213 msg: format!("pow cannot be applied to a string")
214 })
215 )))
216 }
217 }
218 }
219 }?;
220
221 let res = ensure_orgams_type(res, env);
222 res
223
224 }
225}
226
227
228
229
230
231 let mut binary_operation = |left: &Self, right: &Self, oper: cpclib_tokens::BinaryOperation| -> Result<ExprResult, AssemblerError> {
232 let res_left = left.resolve($env);
233 let res_right = right.resolve($env);
234
235 match (res_left, res_right) {
236 (Ok(a), Ok(b)) => {
237 match oper {
238 cpclib_tokens::BinaryOperation::Add => (a + b).map_err(|e| AssemblerError::ExpressionTypeError(e)),
239 cpclib_tokens::BinaryOperation::Sub => (a - b).map_err(|e| AssemblerError::ExpressionTypeError(e)),
240 cpclib_tokens::BinaryOperation::Div => (a / b).map_err(|e| AssemblerError::ExpressionTypeError(e)),
241 cpclib_tokens::BinaryOperation::Mod => (a % b).map_err(|e| AssemblerError::ExpressionTypeError(e)),
242 cpclib_tokens::BinaryOperation::Mul => (a * b).map_err(|e| AssemblerError::ExpressionTypeError(e)),
243 cpclib_tokens::BinaryOperation::RightShift => {
244 (a >> b).map_err(|e| AssemblerError::ExpressionTypeError(e))
245 }
246 cpclib_tokens::BinaryOperation::LeftShift => {
247 (a << b).map_err(|e| AssemblerError::ExpressionTypeError(e))
248 }
249
250 cpclib_tokens::BinaryOperation::BinaryAnd => {
251 (a & b).map_err(|e| AssemblerError::ExpressionTypeError(e))
252 }
253 cpclib_tokens::BinaryOperation::BinaryOr => {
254 (a | b).map_err(|e| AssemblerError::ExpressionTypeError(e))
255 }
256 cpclib_tokens::BinaryOperation::BinaryXor => {
257 (a ^ b).map_err(|e| AssemblerError::ExpressionTypeError(e))
258 }
259
260 cpclib_tokens::BinaryOperation::BooleanAnd => Ok(ExprResult::from(a.bool()? && (b.bool()?))),
261 cpclib_tokens::BinaryOperation::BooleanOr => Ok(ExprResult::from(a.bool()? || (b.bool()?))),
262
263 cpclib_tokens::BinaryOperation::Equal => Ok((a == b).into()),
264 cpclib_tokens::BinaryOperation::Different => Ok((a != b).into()),
265
266 cpclib_tokens::BinaryOperation::LowerOrEqual => Ok((a <= b).into()),
267 cpclib_tokens::BinaryOperation::StrictlyLower => Ok((a < b).into()),
268 cpclib_tokens::BinaryOperation::GreaterOrEqual => Ok((a >= b).into()),
269 cpclib_tokens::BinaryOperation::StrictlyGreater => Ok((a > b).into())
270 }
271 }
272 (Err(a), Ok(_b)) => {
273 Err(AssemblerError::ExpressionError(ExpressionError::LeftError(
274 oper, Box::new(a)
275 )))
276 }
277
278 (Ok(_a), Err(b)) => {
279 Err(AssemblerError::ExpressionError(
280 ExpressionError::RightError(oper, Box::new(b))
281 ))
282 }
283 (Err(a), Err(b)) => {
284 Err(AssemblerError::ExpressionError(
285 ExpressionError::LeftAndRightError(oper, Box::new(a), Box::new(b))
286 ))
287 }
288 }
289 };
290
291 if $self.is_binary_operation() {
292 binary_operation($self.arg1(), $self.arg2(), $self.binary_operation())
293 }
294 else if $self.is_paren() {
295 let e = $self.arg1();
296 e.resolve($env)
297 }
298 else if $self.is_relative() {
299 (Expr::Label("$".into()).resolve($env)? + ExprResult::from($self.relative_delta()))
300 .map_err(|e| AssemblerError::ExpressionTypeError(e))
301 }
302 else if $self.is_value(){
303 Ok($self.value().into())
304 }
305 else if $self.is_char() {
306 Ok($self.char().into())
307 }
308 else if $self.is_bool() {
309 Ok($self.bool().into())
310 } else if $self.is_string() {
311 Ok(ExprResult::String($self.string().into()))
312 }
313 else if $self.is_float() {
314 Ok($self.float().into_inner().into())
315 }
316 else if $self.is_list() {
317 Ok(ExprResult::List(
318 $self.list().iter()
319 .map(|e| e.resolve($env))
320 .collect::<Result<Vec<_>, _>>()?
321 )
322 )
323 }
324 else if $self.is_label() {
325 let label = $self.label();
326 match $env.symbols().any_value(label)?.map(|vl| vl.value()) {
327 Some(cpclib_tokens::symbols::Value::Expr( val)) => Ok(val.clone().into()),
328 Some(cpclib_tokens::symbols::Value::Address( val)) => Ok(val.address().into()),
329 Some(cpclib_tokens::symbols::Value::Struct(s)) => Ok(s.len($env.symbols()).into()),
330 Some(cpclib_tokens::symbols::Value::String( val)) => Ok(val.into()),
331 Some(e) => { Err(AssemblerError::WrongSymbolType {
332 symbol: label.into(),
333 isnot: "a value".into(),
334 })},
335 None => Err(if $env.pass().is_first_pass() {
336 AssemblerError::UnknownSymbol {
338 symbol: label.into(),
339 closest: None,
340 }
341 } else {
342 AssemblerError::UnknownSymbol {
344 symbol: label.into(),
345 closest: $env.symbols().closest_symbol(label, SymbolFor::Number)?,
346 }
347 })
348 }
349
350 }
351 else if $self.is_prefix_label() {
352 let label = $self.label();
353 let prefix = $self.prefix();
354
355 let val = $env.symbols()
356 .prefixed_value(prefix, label)?;
357 match val {
358 Some(val) => Ok(val.into()),
359 None => Err(AssemblerError::AssemblingError {
360 msg: format!("Unable to use prefix {} for {}", prefix, label)
361 })
362 }
363 }
364
365 else if $self.is_token_operation() {
366 let token = $self.token();
367 match $self.token_operation() {
368 cpclib_tokens::UnaryTokenOperation::Duration => {
369 let duration = token.estimated_duration()?;
370 let duration = duration as i32;
371 Ok(duration.into())
372 },
373
374 cpclib_tokens::UnaryTokenOperation::Opcode => {
375 let bytes = token.to_bytes()?;
376 match bytes.len() {
377 0 => Err(
378 AssemblerError::ExpressionError(
379 ExpressionError::OwnError(
380 Box::new(AssemblerError::AssemblingError{msg:format!("{} is assembled with 0 bytes", token)})
381 )
382 )
383 ),
384 1 => Ok(i32::from(bytes[0]).into()),
385 2 => Ok((i32::from(bytes[0]) * 256 + i32::from(bytes[1])).into()),
386 val => Err(
387 AssemblerError::ExpressionError(
388 ExpressionError::OwnError(
389 Box::new(AssemblerError::AssemblingError{msg:format!("{} is assembled with {} bytes", token, val)})
390 )
391 )
392 )
393 }
394 }
395 }
396 }
397 else if $self.is_unary_operation() {
398 let e = $self.arg1();
399
400 match $self.unary_operation() {
401 cpclib_tokens::UnaryOperation::BinaryNot => {
402 e.resolve($env)?
403 .binary_not()
404 .map_err(|e| AssemblerError::ExpressionTypeError(e))
405 },
406 cpclib_tokens::UnaryOperation::Not => {
407 e.resolve($env)?
408 .not()
409 .map_err(|e| AssemblerError::ExpressionTypeError(e))
410 },
411 cpclib_tokens::UnaryOperation::Neg => {
412 (e.resolve($env)?)
413 .neg()
414 .map_err(|e| AssemblerError::ExpressionTypeError(e))
415 }
416 }
417 }
418 else if $self.is_unary_function() {
419 let func = $self.unary_function();
420 let arg = $self.arg1();
421 UnaryFunctionWrapper::new(func, arg).resolve($env)
422 }
423 else if $self.is_binary_function() {
424 let func = $self.binary_function();
425 let arg1 = $self.arg1();
426 let arg2 = $self.arg2();
427 BinaryFunctionWrapper::new(func, arg1, arg2).resolve($env)
428 }
429
430 else if $self.is_rnd() {
431 unimplemented!("Env need to maintain a counter of call with its value to ensure a consistant generation among the passes")
432 }
433 else if $self.is_any_function(){
434 let d = $self.function_name();
435 let expr = $self.function_args();
436
437
438 let mut params = Vec::with_capacity(expr.len());
439 for p in expr.iter() {
440 let v = $env.resolve_expr_may_fail_in_first_pass(p) ?;
441 params.push(v);
442 }
443
444 let f = $env.any_function(d)?;
445 f.eval($env, ¶ms)
446
447
448 } else {
449 unreachable!()
450 }
451 }
452 };
453}
454
455impl ExprEvaluationExt for Expr {
456 fn symbols_used(&self) -> Vec<&str> {
458 match self {
459 Expr::RelativeDelta(_)
460 | Expr::Value(_)
461 | Expr::Float(_)
462 | Expr::Char(_)
463 | Expr::Bool(_)
464 | Expr::String(_)
465 | Expr::Rnd => Vec::new(),
466
467 Expr::Label(label) | Expr::PrefixedLabel(_, label) => vec![label.as_str()],
468
469 Expr::BinaryFunction(_, box a, box b) | Expr::BinaryOperation(_, box a, box b) => {
470 a.symbols_used()
471 .into_iter()
472 .chain(b.symbols_used())
473 .collect_vec()
474 },
475
476 Expr::Paren(a) | Expr::UnaryFunction(_, a) | Expr::UnaryOperation(_, a) => {
477 a.symbols_used()
478 },
479
480 Expr::AnyFunction(_, l) | Expr::List(l) => {
481 l.iter().flat_map(|e| e.symbols_used()).collect_vec()
482 },
483
484 Expr::UnaryTokenOperation(_, box _t) => {
485 unimplemented!("Need to retreive the symbols from the operation")
486 }
487 }
488 }
489
490 fn resolve(&self, env: &mut Env) -> Result<ExprResult, AssemblerError> {
491 resolve_impl!(self, env)
492 }
493}