microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
c8adde746a7aaa0185fd4eac69af19d259ce1faa

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

compiler/qsc_eval/src/lib.rs

1574lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![warn(clippy::mod_module_files, clippy::pedantic, clippy::unwrap_used)]
5
6#[cfg(test)]
7mod tests;
8
9pub mod debug;
10mod intrinsic;
11pub mod output;
12pub mod val;
13
14use crate::val::{ConversionError, FunctorApp, Value};
15use debug::{CallStack, Frame};
16use intrinsic::invoke_intrinsic;
17use miette::Diagnostic;
18use num_bigint::BigInt;
19use output::Receiver;
20use qir_backend::{
21 __quantum__rt__initialize, __quantum__rt__qubit_allocate, __quantum__rt__qubit_release,
22 qubit_is_zero,
23};
24use qsc_data_structures::span::Span;
25use qsc_hir::hir::{
26 self, BinOp, Block, CallableBody, CallableDecl, Expr, ExprKind, Functor, Lit, Mutability,
27 NodeId, PackageId, Pat, PatKind, PrimField, QubitInit, QubitInitKind, Res, Spec, SpecBody,
28 SpecGen, Stmt, StmtKind, TernOp, UnOp,
29};
30use std::{
31 collections::{hash_map::Entry, HashMap},
32 mem::take,
33 ops::{
34 ControlFlow::{self, Break, Continue},
35 Neg,
36 },
37 ptr::null_mut,
38};
39use thiserror::Error;
40use val::{GlobalId, Qubit};
41
42#[derive(Clone, Debug, Diagnostic, Error)]
43pub enum Error {
44 #[error("array too large")]
45 ArrayTooLarge(#[label("this array has too many items")] Span),
46
47 #[error("invalid array length: {0}")]
48 Count(i64, #[label("cannot be used as a length")] Span),
49
50 #[error("division by zero")]
51 DivZero(#[label("cannot divide by zero")] Span),
52
53 #[error("empty range")]
54 EmptyRange(#[label("the range cannot be empty")] Span),
55
56 #[error("{0} type does not support equality comparison")]
57 Equality(&'static str, #[label("does not support comparison")] Span),
58
59 #[error("value cannot be used as an index: {0}")]
60 IndexVal(i64, #[label("invalid index")] Span),
61
62 #[error("integer too large for operation")]
63 IntTooLarge(i64, #[label("this value is too large")] Span),
64
65 #[error("missing specialization: {0}")]
66 MissingSpec(Spec, #[label("callable has no {0} specialization")] Span),
67
68 #[error("reassigning immutable variable")]
69 Mutability(#[label("variable declared as immutable")] Span),
70
71 #[error("iterable ranges cannot be open-ended")]
72 OpenEnded(#[label("open-ended range used as iterator")] Span),
73
74 #[error("index out of range: {0}")]
75 OutOfRange(i64, #[label("out of range")] Span),
76
77 #[error("negative integers cannot be used here: {0}")]
78 Negative(i64, #[label("invalid negative integer")] Span),
79
80 #[error("type {0} is not iterable")]
81 NotIterable(&'static str, #[label("not iterable")] Span),
82
83 #[error("output failure")]
84 Output(#[label("failed to generate output")] Span),
85
86 #[error("range with step size of zero")]
87 RangeStepZero(#[label("invalid range")] Span),
88
89 #[error("Qubit{0} released while not in |0⟩ state")]
90 ReleasedQubitNotZero(usize, #[label] Span),
91
92 #[error("mismatched types")]
93 Type(
94 &'static str,
95 &'static str,
96 #[label("expected {0}, found {1}")] Span,
97 ),
98
99 #[error("mismatched tuples")]
100 TupleArity(
101 usize,
102 usize,
103 #[label("expected {0}-tuple, found {1}-tuple")] Span,
104 ),
105
106 #[error("invalid left-hand side of assignment")]
107 #[diagnostic(help("the left-hand side must be a variable or tuple of variables"))]
108 Unassignable(#[label("not assignable")] Span),
109
110 #[error("symbol is not bound")]
111 Unbound(#[label] Span),
112
113 #[error("{0} support is not implemented")]
114 #[diagnostic(help("this language feature is not yet supported"))]
115 Unimplemented(&'static str, #[label("cannot evaluate this")] Span),
116
117 #[error("unknown intrinsic")]
118 UnknownIntrinsic(#[label("callable has no implementation")] Span),
119
120 #[error("program failed: {0}")]
121 UserFail(String, #[label("explicit fail")] Span),
122}
123
124#[derive(Debug)]
125enum Reason {
126 Error(Error),
127 Return(Value),
128}
129
130trait WithSpan {
131 type Output;
132
133 fn with_span(self, span: Span) -> Self::Output;
134}
135
136impl<T> WithSpan for Result<T, ConversionError> {
137 type Output = ControlFlow<Reason, T>;
138
139 fn with_span(self, span: Span) -> Self::Output {
140 match self {
141 Ok(c) => Continue(c),
142 Err(e) => Break(Reason::Error(Error::Type(e.expected, e.actual, span))),
143 }
144 }
145}
146
147trait AsIndex {
148 type Output;
149
150 fn as_index(&self, span: Span) -> Self::Output;
151}
152
153impl AsIndex for i64 {
154 type Output = ControlFlow<Reason, usize>;
155
156 fn as_index(&self, span: Span) -> ControlFlow<Reason, usize> {
157 match (*self).try_into() {
158 Ok(index) => Continue(index),
159 Err(_) => Break(Reason::Error(Error::IndexVal(*self, span))),
160 }
161 }
162}
163
164#[derive(Debug)]
165struct Variable {
166 value: Value,
167 mutability: Mutability,
168}
169
170impl Variable {
171 fn is_mutable(&self) -> bool {
172 self.mutability == Mutability::Mutable
173 }
174}
175
176struct Range {
177 step: i64,
178 end: i64,
179 curr: i64,
180}
181
182impl Iterator for Range {
183 type Item = i64;
184
185 fn next(&mut self) -> Option<Self::Item> {
186 let curr = self.curr;
187 self.curr += self.step;
188 if (self.step > 0 && curr <= self.end) || (self.step < 0 && curr >= self.end) {
189 Some(curr)
190 } else {
191 None
192 }
193 }
194}
195
196impl Range {
197 fn new(start: i64, step: i64, end: i64) -> Self {
198 Range {
199 step,
200 end,
201 curr: start,
202 }
203 }
204}
205
206pub trait GlobalLookup<'a> {
207 fn callable(&self, id: GlobalId) -> Option<&'a CallableDecl>;
208}
209
210impl<'a, F: Fn(GlobalId) -> Option<&'a CallableDecl>> GlobalLookup<'a> for F {
211 fn callable(&self, id: GlobalId) -> Option<&'a CallableDecl> {
212 self(id)
213 }
214}
215
216/// Evaluates the given statement with the given context.
217/// # Errors
218/// Returns the first error encountered during execution.
219pub fn eval_stmt<'a>(
220 stmt: &Stmt,
221 globals: &'a impl GlobalLookup<'a>,
222 package: PackageId,
223 env: &mut Env,
224 out: &'a mut dyn Receiver,
225) -> Result<Value, (Error, CallStack)> {
226 let mut eval = Evaluator {
227 globals,
228 package,
229 env: take(env),
230 call_stack: CallStack::default(),
231 out: Some(out),
232 };
233 let res = match eval.eval_stmt(stmt) {
234 Continue(res) | Break(Reason::Return(res)) => Ok(res),
235 Break(Reason::Error(error)) => Err((error, eval.call_stack.clone())),
236 };
237 *env = take(&mut eval.env);
238 res
239}
240
241/// Evaluates the given expression with the given context.
242/// # Errors
243/// Returns the first error encountered during execution.
244pub fn eval_expr<'a>(
245 expr: &Expr,
246 globals: &'a impl GlobalLookup<'a>,
247 package: PackageId,
248 env: &mut Env,
249 out: &'a mut dyn Receiver,
250) -> Result<Value, (Error, CallStack)> {
251 let mut eval = Evaluator {
252 globals,
253 package,
254 env: take(env),
255 call_stack: CallStack::default(),
256 out: Some(out),
257 };
258 let res = match eval.eval_expr(expr) {
259 Continue(res) | Break(Reason::Return(res)) => Ok(res),
260 Break(Reason::Error(error)) => Err((error, eval.call_stack.clone())),
261 };
262 *env = take(&mut eval.env);
263 res
264}
265
266pub fn init() {
267 __quantum__rt__initialize(null_mut());
268}
269
270#[derive(Default)]
271pub struct Env(Vec<Scope>);
272
273impl Env {
274 fn get(&self, id: NodeId) -> Option<&Variable> {
275 self.0
276 .iter()
277 .rev()
278 .find_map(|scope| scope.bindings.get(&id))
279 }
280
281 fn get_mut(&mut self, id: NodeId) -> Option<&mut Variable> {
282 self.0
283 .iter_mut()
284 .rev()
285 .find_map(|scope| scope.bindings.get_mut(&id))
286 }
287}
288
289#[derive(Default)]
290struct Scope {
291 bindings: HashMap<NodeId, Variable>,
292 qubits: Vec<(Qubit, Span)>,
293}
294
295impl Env {
296 #[must_use]
297 pub fn with_empty_scope() -> Self {
298 Self(vec![Scope::default()])
299 }
300}
301
302struct Evaluator<'a, G> {
303 globals: &'a G,
304 package: PackageId,
305 env: Env,
306 call_stack: CallStack,
307 out: Option<&'a mut dyn Receiver>,
308}
309
310impl<'a, G: GlobalLookup<'a>> Evaluator<'a, G> {
311 #[allow(clippy::too_many_lines)]
312 fn eval_expr(&mut self, expr: &Expr) -> ControlFlow<Reason, Value> {
313 match &expr.kind {
314 ExprKind::Array(arr) => {
315 let mut val_arr = vec![];
316 for expr in arr {
317 val_arr.push(self.eval_expr(expr)?);
318 }
319 Continue(Value::Array(val_arr.into()))
320 }
321 ExprKind::ArrayRepeat(item, size) => {
322 let item_val = self.eval_expr(item)?;
323 let size_val: i64 = self.eval_expr(size)?.try_into().with_span(size.span)?;
324 let s = match size_val.try_into() {
325 Ok(i) => Continue(i),
326 Err(_) => Break(Reason::Error(Error::Count(size_val, size.span))),
327 }?;
328 Continue(Value::Array(vec![item_val; s].into()))
329 }
330 ExprKind::Assign(lhs, rhs) => {
331 let val = self.eval_expr(rhs)?;
332 self.update_binding(lhs, val)
333 }
334 ExprKind::AssignOp(op, lhs, rhs) => {
335 let update = self.eval_binop(*op, lhs, rhs)?;
336 self.update_binding(lhs, update)
337 }
338 ExprKind::AssignUpdate(lhs, mid, rhs) => {
339 let update = self.eval_ternop_update(lhs, mid, rhs)?;
340 self.update_binding(lhs, update)
341 }
342 ExprKind::BinOp(op, lhs, rhs) => self.eval_binop(*op, lhs, rhs),
343 ExprKind::Block(block) => self.eval_block(block),
344 ExprKind::Call(call, args) => self.eval_call(call, args),
345 ExprKind::Fail(msg) => {
346 let msg = self.eval_expr(msg)?.try_into_string().with_span(msg.span)?;
347 Break(Reason::Error(Error::UserFail(msg.to_string(), expr.span)))
348 }
349 ExprKind::Field(record, field) => self.eval_field(expr.span, record, *field),
350 ExprKind::For(pat, expr, block) => self.eval_for_loop(pat, expr, block),
351 ExprKind::If(cond, then, els) => {
352 if self.eval_expr(cond)?.try_into().with_span(cond.span)? {
353 self.eval_block(then)
354 } else if let Some(els) = els {
355 self.eval_expr(els)
356 } else {
357 Continue(Value::unit())
358 }
359 }
360 ExprKind::Index(arr, index_expr) => {
361 let arr = self.eval_expr(arr)?.try_into_array().with_span(arr.span)?;
362 let index_val = self.eval_expr(index_expr)?;
363 match &index_val {
364 Value::Int(index) => index_array(&arr, *index, index_expr.span),
365 &Value::Range(start, step, end) => {
366 slice_array(&arr, start, step, end, index_expr.span)
367 }
368 _ => Break(Reason::Error(Error::Type(
369 "Int or Range",
370 index_val.type_name(),
371 index_expr.span,
372 ))),
373 }
374 }
375 ExprKind::Lit(lit) => Continue(lit_to_val(lit)),
376 ExprKind::Paren(expr) => self.eval_expr(expr),
377 ExprKind::Range(start, step, end) => self.eval_range(start, step, end),
378 ExprKind::Repeat(repeat, cond, fixup) => self.eval_repeat_loop(repeat, cond, fixup),
379 ExprKind::Return(expr) => Break(Reason::Return(self.eval_expr(expr)?)),
380 ExprKind::TernOp(ternop, lhs, mid, rhs) => match *ternop {
381 TernOp::Cond => self.eval_ternop_cond(lhs, mid, rhs),
382 TernOp::Update => self.eval_ternop_update(lhs, mid, rhs),
383 },
384 ExprKind::Tuple(tup) => {
385 let mut val_tup = vec![];
386 for expr in tup {
387 val_tup.push(self.eval_expr(expr)?);
388 }
389 Continue(Value::Tuple(val_tup.into()))
390 }
391 ExprKind::UnOp(op, rhs) => self.eval_unop(expr, *op, rhs),
392 &ExprKind::Var(res) => match self.resolve_binding(res, expr.span) {
393 Ok(val) => Continue(val),
394 Err(e) => Break(Reason::Error(e)),
395 },
396 ExprKind::While(cond, block) => {
397 while self.eval_expr(cond)?.try_into().with_span(cond.span)? {
398 self.eval_block(block)?;
399 }
400 Continue(Value::unit())
401 }
402 ExprKind::Conjugate(..) => {
403 Break(Reason::Error(Error::Unimplemented("conjugate", expr.span)))
404 }
405 ExprKind::Err => Break(Reason::Error(Error::Unimplemented("error", expr.span))),
406 ExprKind::Hole => Break(Reason::Error(Error::Unimplemented("hole", expr.span))),
407 ExprKind::Lambda(..) => Break(Reason::Error(Error::Unimplemented("lambda", expr.span))),
408 }
409 }
410
411 fn eval_range(
412 &mut self,
413 start: &Option<Box<Expr>>,
414 step: &Option<Box<Expr>>,
415 end: &Option<Box<Expr>>,
416 ) -> ControlFlow<Reason, Value> {
417 let mut to_opt_i64 = |e: &Option<Box<Expr>>| match e {
418 Some(expr) => Continue(Some(self.eval_expr(expr)?.try_into().with_span(expr.span)?)),
419 None => Continue(None),
420 };
421 Continue(Value::Range(
422 to_opt_i64(start)?,
423 to_opt_i64(step)?.unwrap_or(val::DEFAULT_RANGE_STEP),
424 to_opt_i64(end)?,
425 ))
426 }
427
428 fn eval_block(&mut self, block: &Block) -> ControlFlow<Reason, Value> {
429 self.enter_scope();
430 let result = if let Some((last, most)) = block.stmts.split_last() {
431 for stmt in most {
432 self.eval_stmt(stmt)?;
433 }
434 self.eval_stmt(last)
435 } else {
436 Continue(Value::unit())
437 };
438 self.leave_scope()?;
439 result
440 }
441
442 fn eval_stmt(&mut self, stmt: &Stmt) -> ControlFlow<Reason, Value> {
443 match &stmt.kind {
444 StmtKind::Item(_) => Continue(Value::unit()),
445 StmtKind::Expr(expr) => self.eval_expr(expr),
446 StmtKind::Local(mutability, pat, expr) => {
447 let val = self.eval_expr(expr)?;
448 self.bind_value(pat, val, expr.span, *mutability)?;
449 Continue(Value::unit())
450 }
451 StmtKind::Semi(expr) => {
452 self.eval_expr(expr)?;
453 Continue(Value::unit())
454 }
455 StmtKind::Qubit(_, pat, qubit_init, block) => {
456 let (qubit_val, qubits) = self.eval_qubit_init(qubit_init)?;
457 if let Some(block) = block {
458 self.enter_scope();
459 self.track_qubits(qubits);
460 self.bind_value(pat, qubit_val, stmt.span, Mutability::Immutable)?;
461 self.eval_block(block)?;
462 self.leave_scope()?;
463 } else {
464 self.track_qubits(qubits);
465 self.bind_value(pat, qubit_val, stmt.span, Mutability::Immutable)?;
466 }
467 Continue(Value::unit())
468 }
469 }
470 }
471
472 fn eval_for_loop(
473 &mut self,
474 pat: &Pat,
475 expr: &Expr,
476 block: &Block,
477 ) -> ControlFlow<Reason, Value> {
478 match self.eval_expr(expr)? {
479 Value::Array(arr) => self.iterate_for_loop(pat, arr.iter().cloned(), expr.span, block),
480 Value::Range(start, step, end) => {
481 let start =
482 start.map_or(Break(Reason::Error(Error::OpenEnded(expr.span))), Continue)?;
483 let end =
484 end.map_or(Break(Reason::Error(Error::OpenEnded(expr.span))), Continue)?;
485 let range = Range::new(start, step, end);
486 self.iterate_for_loop(pat, range.map(Value::Int), expr.span, block)
487 }
488 value => Break(Reason::Error(Error::NotIterable(
489 value.type_name(),
490 expr.span,
491 ))),
492 }
493 }
494
495 fn iterate_for_loop(
496 &mut self,
497 pat: &Pat,
498 values: impl Iterator<Item = Value>,
499 span: Span,
500 block: &Block,
501 ) -> ControlFlow<Reason, Value> {
502 for value in values {
503 self.enter_scope();
504 self.bind_value(pat, value, span, Mutability::Immutable);
505 self.eval_block(block)?;
506 self.leave_scope()?;
507 }
508
509 Continue(Value::unit())
510 }
511
512 fn eval_repeat_loop(
513 &mut self,
514 repeat: &Block,
515 cond: &Expr,
516 fixup: &Option<Block>,
517 ) -> ControlFlow<Reason, Value> {
518 self.enter_scope();
519
520 for stmt in &repeat.stmts {
521 self.eval_stmt(stmt)?;
522 }
523 while !self.eval_expr(cond)?.try_into().with_span(cond.span)? {
524 if let Some(block) = fixup.as_ref() {
525 self.eval_block(block)?;
526 }
527
528 self.leave_scope()?;
529 self.enter_scope();
530
531 for stmt in &repeat.stmts {
532 self.eval_stmt(stmt)?;
533 }
534 }
535
536 self.leave_scope()?;
537 Continue(Value::unit())
538 }
539
540 fn eval_qubit_init(
541 &mut self,
542 qubit_init: &QubitInit,
543 ) -> ControlFlow<Reason, (Value, Vec<(Qubit, Span)>)> {
544 match &qubit_init.kind {
545 QubitInitKind::Array(count) => {
546 let count_val: i64 = self.eval_expr(count)?.try_into().with_span(count.span)?;
547 let count: usize = match count_val.try_into() {
548 Ok(i) => Continue(i),
549 Err(_) => Break(Reason::Error(Error::Count(count_val, count.span))),
550 }?;
551 let mut arr = vec![];
552 arr.resize_with(count, || {
553 (Qubit(__quantum__rt__qubit_allocate()), qubit_init.span)
554 });
555
556 Continue((
557 Value::Array(arr.iter().copied().map(|q| Value::Qubit(q.0)).collect()),
558 arr,
559 ))
560 }
561 QubitInitKind::Paren(qubit_init) => self.eval_qubit_init(qubit_init),
562 QubitInitKind::Single => {
563 let qubit = Qubit(__quantum__rt__qubit_allocate());
564 Continue((Value::Qubit(qubit), vec![(qubit, qubit_init.span)]))
565 }
566 QubitInitKind::Tuple(tup) => {
567 let mut tup_vec = vec![];
568 let mut qubit_vec = vec![];
569 for init in tup {
570 let (t, mut v) = self.eval_qubit_init(init)?;
571 tup_vec.push(t);
572 qubit_vec.append(&mut v);
573 }
574 Continue((Value::Tuple(tup_vec.into()), qubit_vec))
575 }
576 }
577 }
578
579 fn eval_call(&mut self, call_expr: &Expr, args: &Expr) -> ControlFlow<Reason, Value> {
580 let call_val = self.eval_expr(call_expr)?;
581 let call_span = call_expr.span;
582 let (call, functor) = value_to_call_id(&call_val, call_expr.span)?;
583 let args_val = self.eval_expr(args)?;
584 let decl = match self.globals.callable(call) {
585 Some(decl) => Continue(decl),
586 None => Break(Reason::Error(Error::Unbound(call_expr.span))),
587 }?;
588 let spec = spec_from_functor_app(functor);
589
590 self.push_frame(Frame {
591 id: call,
592 span: Some(call_span),
593 caller: self.package,
594 functor,
595 });
596
597 let mut new_self = Self {
598 globals: self.globals,
599 package: call.package,
600 env: Env::default(),
601 out: self.out.take(),
602 call_stack: CallStack::default(),
603 };
604 let call_res = new_self.eval_call_spec(
605 decl,
606 spec,
607 args_val,
608 args.span,
609 call_span,
610 functor.controlled,
611 );
612 self.out = new_self.out.take();
613
614 match call_res {
615 Break(Reason::Return(val)) => {
616 self.pop_frame();
617 Continue(val)
618 }
619 Break(Reason::Error(_)) => {
620 for frame in new_self.call_stack.clone().into_frames() {
621 self.call_stack.push_frame(frame);
622 }
623
624 call_res
625 }
626 Continue(_) => {
627 self.pop_frame();
628 call_res
629 }
630 }
631 }
632
633 fn eval_call_spec(
634 &mut self,
635 decl: &CallableDecl,
636 spec: Spec,
637 args_val: Value,
638 args_span: Span,
639 call_span: Span,
640 ctl_count: u8,
641 ) -> ControlFlow<Reason, Value> {
642 self.enter_scope();
643 let res = match (&decl.body, spec) {
644 (CallableBody::Block(body_block), Spec::Body) => {
645 self.bind_value(&decl.input, args_val, args_span, Mutability::Immutable)?;
646 self.eval_block(body_block)
647 }
648 (CallableBody::Specs(spec_decls), spec) => {
649 let spec_decl = spec_decls
650 .iter()
651 .find(|spec_decl| spec_decl.spec == spec)
652 .map_or_else(
653 || Break(Reason::Error(Error::MissingSpec(spec, call_span))),
654 |spec_decl| Continue(&spec_decl.body),
655 )?;
656 match spec_decl {
657 SpecBody::Impl(pat, body_block) => {
658 self.bind_args_for_spec(&decl.input, pat, args_val, args_span, ctl_count)?;
659 self.eval_block(body_block)
660 }
661 SpecBody::Gen(SpecGen::Intrinsic) => invoke_intrinsic(
662 &decl.name.name,
663 call_span,
664 args_val,
665 args_span,
666 self.out
667 .as_deref_mut()
668 .expect("output receiver should be set"),
669 ),
670 SpecBody::Gen(_) => Break(Reason::Error(Error::MissingSpec(spec, call_span))),
671 }
672 }
673 _ => Break(Reason::Error(Error::MissingSpec(spec, call_span))),
674 };
675 self.leave_scope()?;
676 res
677 }
678
679 fn bind_args_for_spec(
680 &mut self,
681 decl_pat: &Pat,
682 spec_pat: &Pat,
683 args_val: Value,
684 args_span: Span,
685 ctl_count: u8,
686 ) -> ControlFlow<Reason, ()> {
687 match &spec_pat.kind {
688 PatKind::Bind(_) | PatKind::Discard => {
689 panic!("spec pattern should be elided or elided tuple, found bind/discard")
690 }
691 PatKind::Elided => {
692 self.bind_value(decl_pat, args_val, args_span, Mutability::Immutable)
693 }
694 PatKind::Paren(pat) => {
695 self.bind_args_for_spec(decl_pat, pat, args_val, args_span, ctl_count)
696 }
697 PatKind::Tuple(pats) => {
698 assert_eq!(pats.len(), 2, "spec pattern tuple should have 2 elements");
699 assert!(
700 ctl_count > 0,
701 "spec pattern tuple used without controlled functor"
702 );
703
704 let mut tup = args_val;
705 let mut ctls = vec![];
706 for _ in 0..ctl_count {
707 let tup_nesting = tup.try_into_tuple().with_span(args_span)?;
708 if tup_nesting.len() != 2 {
709 return Break(Reason::Error(Error::TupleArity(
710 2,
711 tup_nesting.len(),
712 args_span,
713 )));
714 }
715
716 let c = tup_nesting[0].clone();
717 let rest = tup_nesting[1].clone();
718 ctls.extend_from_slice(c.try_into_array().with_span(args_span)?.as_ref());
719 tup = rest;
720 }
721
722 self.bind_value(
723 &pats[0],
724 Value::Array(ctls.into()),
725 args_span,
726 Mutability::Immutable,
727 )?;
728 self.bind_value(decl_pat, tup, args_span, Mutability::Immutable)
729 }
730 }
731 }
732
733 fn eval_unop(&mut self, expr: &Expr, op: UnOp, rhs: &Expr) -> ControlFlow<Reason, Value> {
734 let val = self.eval_expr(rhs)?;
735 match op {
736 UnOp::Neg => match val {
737 Value::BigInt(v) => Continue(Value::BigInt(v.neg())),
738 Value::Double(v) => Continue(Value::Double(v.neg())),
739 Value::Int(v) => Continue(Value::Int(v.wrapping_neg())),
740 _ => Break(Reason::Error(Error::Type(
741 "Int, BigInt, or Double",
742 val.type_name(),
743 rhs.span,
744 ))),
745 },
746 UnOp::Pos => match val {
747 Value::BigInt(_) | Value::Int(_) | Value::Double(_) => Continue(val),
748 _ => Break(Reason::Error(Error::Type(
749 "Int, BigInt, or Double",
750 val.type_name(),
751 rhs.span,
752 ))),
753 },
754 UnOp::NotL => match val {
755 Value::Bool(b) => Continue(Value::Bool(!b)),
756 _ => Break(Reason::Error(Error::Type(
757 "Bool",
758 val.type_name(),
759 rhs.span,
760 ))),
761 },
762 UnOp::NotB => match val {
763 Value::Int(v) => Continue(Value::Int(!v)),
764 Value::BigInt(v) => Continue(Value::BigInt(!v)),
765 _ => Break(Reason::Error(Error::Type(
766 "Int or BigInt",
767 val.type_name(),
768 rhs.span,
769 ))),
770 },
771 UnOp::Functor(functor) => match val {
772 Value::Closure => Break(Reason::Error(Error::Unimplemented("closure", expr.span))),
773 Value::Global(id, app) => {
774 Continue(Value::Global(id, update_functor_app(functor, app)))
775 }
776 _ => Break(Reason::Error(Error::Type(
777 "Callable",
778 val.type_name(),
779 rhs.span,
780 ))),
781 },
782 UnOp::Unwrap => Break(Reason::Error(Error::Unimplemented("unwrap", expr.span))),
783 }
784 }
785
786 fn eval_binop(&mut self, op: BinOp, lhs: &Expr, rhs: &Expr) -> ControlFlow<Reason, Value> {
787 let lhs_val = self.eval_expr(lhs)?;
788 match op {
789 BinOp::Add => eval_binop_add(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
790 BinOp::AndB => eval_binop_andb(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
791 BinOp::AndL => self.eval_binop_andl(lhs_val.try_into().with_span(lhs.span)?, rhs),
792 BinOp::Div => eval_binop_div(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
793 BinOp::Eq => eval_binop_eq(&lhs_val, lhs.span, &self.eval_expr(rhs)?, rhs.span),
794 BinOp::Exp => eval_binop_exp(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
795 BinOp::Gt => eval_binop_gt(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
796 BinOp::Gte => eval_binop_gte(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
797 BinOp::Lt => eval_binop_lt(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
798 BinOp::Lte => eval_binop_lte(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
799 BinOp::Mod => eval_binop_mod(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
800 BinOp::Mul => eval_binop_mul(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
801 BinOp::Neq => eval_binop_neq(&lhs_val, lhs.span, &self.eval_expr(rhs)?, rhs.span),
802 BinOp::OrB => eval_binop_orb(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
803 BinOp::OrL => self.eval_binop_orl(lhs_val.try_into().with_span(lhs.span)?, rhs),
804 BinOp::Shl => eval_binop_shl(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
805 BinOp::Shr => eval_binop_shr(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
806 BinOp::Sub => eval_binop_sub(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
807 BinOp::XorB => eval_binop_xorb(lhs_val, lhs.span, self.eval_expr(rhs)?, rhs.span),
808 }
809 }
810
811 fn eval_binop_andl(&mut self, lhs: bool, rhs: &Expr) -> ControlFlow<Reason, Value> {
812 Continue(Value::Bool(
813 lhs && self.eval_expr(rhs)?.try_into().with_span(rhs.span)?,
814 ))
815 }
816
817 fn eval_binop_orl(&mut self, lhs: bool, rhs: &Expr) -> ControlFlow<Reason, Value> {
818 Continue(Value::Bool(
819 lhs || self.eval_expr(rhs)?.try_into().with_span(rhs.span)?,
820 ))
821 }
822
823 fn eval_ternop_cond(
824 &mut self,
825 lhs: &Expr,
826 mid: &Expr,
827 rhs: &Expr,
828 ) -> ControlFlow<Reason, Value> {
829 if self.eval_expr(lhs)?.try_into().with_span(lhs.span)? {
830 self.eval_expr(mid)
831 } else {
832 self.eval_expr(rhs)
833 }
834 }
835
836 fn eval_ternop_update(
837 &mut self,
838 lhs: &Expr,
839 mid: &Expr,
840 rhs: &Expr,
841 ) -> ControlFlow<Reason, Value> {
842 let values = self.eval_expr(lhs)?.try_into_array().with_span(lhs.span)?;
843 let index: i64 = self.eval_expr(mid)?.try_into().with_span(mid.span)?;
844 if index < 0 {
845 return Break(Reason::Error(Error::Negative(index, mid.span)));
846 }
847
848 let mut values: Vec<_> = values.iter().cloned().collect();
849 match values.get_mut(index.as_index(mid.span)?) {
850 Some(value) => {
851 *value = self.eval_expr(rhs)?;
852 Continue(Value::Array(values.into()))
853 }
854 None => Break(Reason::Error(Error::OutOfRange(index, mid.span))),
855 }
856 }
857
858 fn eval_field(
859 &mut self,
860 span: Span,
861 record: &Expr,
862 field: PrimField,
863 ) -> ControlFlow<Reason, Value> {
864 let record_span = record.span;
865 let record = self.eval_expr(record)?;
866 // For now we only support built-in fields for Arrays and Ranges.
867 match (record, field) {
868 (Value::Array(arr), PrimField::Length) => {
869 let len: i64 = match arr.len().try_into() {
870 Ok(len) => Continue(len),
871 Err(_) => Break(Reason::Error(Error::ArrayTooLarge(record_span))),
872 }?;
873 Continue(Value::Int(len))
874 }
875 (Value::Range(Some(start), _, _), PrimField::Start) => Continue(Value::Int(start)),
876 (Value::Range(_, step, _), PrimField::Step) => Continue(Value::Int(step)),
877 (Value::Range(_, _, Some(end)), PrimField::End) => Continue(Value::Int(end)),
878 _ => Break(Reason::Error(Error::Unimplemented("field access", span))),
879 }
880 }
881
882 fn enter_scope(&mut self) {
883 self.env.0.push(Scope::default());
884 }
885
886 fn track_qubits(&mut self, mut qubits: Vec<(Qubit, Span)>) {
887 self.env
888 .0
889 .last_mut()
890 .expect("scope should have been entered to track qubits")
891 .qubits
892 .append(&mut qubits);
893 }
894
895 fn leave_scope(&mut self) -> ControlFlow<Reason, ()> {
896 for (qubit, span) in self
897 .env
898 .0
899 .pop()
900 .expect("scope should be entered first before leaving")
901 .qubits
902 {
903 if !qubit_is_zero(qubit.0) {
904 return ControlFlow::Break(Reason::Error(Error::ReleasedQubitNotZero(
905 qubit.0 as usize,
906 span,
907 )));
908 }
909 __quantum__rt__qubit_release(qubit.0);
910 }
911 ControlFlow::Continue(())
912 }
913
914 fn bind_value(
915 &mut self,
916 pat: &Pat,
917 value: Value,
918 span: Span,
919 mutability: Mutability,
920 ) -> ControlFlow<Reason, ()> {
921 match &pat.kind {
922 PatKind::Bind(variable) => {
923 let scope = self.env.0.last_mut().expect("binding should have a scope");
924 match scope.bindings.entry(variable.id) {
925 Entry::Vacant(entry) => entry.insert(Variable { value, mutability }),
926 Entry::Occupied(_) => panic!("duplicate binding"),
927 };
928 Continue(())
929 }
930 PatKind::Discard => Continue(()),
931 PatKind::Elided => panic!("elision used in binding"),
932 PatKind::Paren(pat) => self.bind_value(pat, value, span, mutability),
933 PatKind::Tuple(tup) => {
934 let val_tup = value.try_into_tuple().with_span(span)?;
935 if val_tup.len() == tup.len() {
936 for (pat, val) in tup.iter().zip(val_tup.iter()) {
937 self.bind_value(pat, val.clone(), span, mutability)?;
938 }
939 Continue(())
940 } else {
941 Break(Reason::Error(Error::TupleArity(
942 tup.len(),
943 val_tup.len(),
944 pat.span,
945 )))
946 }
947 }
948 }
949 }
950
951 fn resolve_binding(&mut self, res: Res, span: Span) -> Result<Value, Error> {
952 Ok(match res {
953 Res::Err => panic!("resolution error"),
954 Res::Item(item) => Value::Global(
955 GlobalId {
956 package: item.package.unwrap_or(self.package),
957 item: item.item,
958 },
959 FunctorApp::default(),
960 ),
961 Res::Local(node) => self
962 .env
963 .get(node)
964 .ok_or(Error::Unbound(span))?
965 .value
966 .clone(),
967 })
968 }
969
970 #[allow(clippy::similar_names)]
971 fn update_binding(&mut self, lhs: &Expr, rhs: Value) -> ControlFlow<Reason, Value> {
972 match (&lhs.kind, rhs) {
973 (ExprKind::Hole, _) => Continue(Value::unit()),
974 (ExprKind::Paren(expr), rhs) => self.update_binding(expr, rhs),
975 (&ExprKind::Var(Res::Local(node)), rhs) => match self.env.get_mut(node) {
976 Some(var) if var.is_mutable() => {
977 var.value = rhs;
978 Continue(Value::unit())
979 }
980 Some(_) => Break(Reason::Error(Error::Mutability(lhs.span))),
981 None => Break(Reason::Error(Error::Unbound(lhs.span))),
982 },
983 (ExprKind::Tuple(var_tup), Value::Tuple(tup)) => {
984 if var_tup.len() == tup.len() {
985 for (expr, val) in var_tup.iter().zip(tup.iter()) {
986 self.update_binding(expr, val.clone())?;
987 }
988 Continue(Value::unit())
989 } else {
990 Break(Reason::Error(Error::TupleArity(
991 var_tup.len(),
992 tup.len(),
993 lhs.span,
994 )))
995 }
996 }
997 _ => Break(Reason::Error(Error::Unassignable(lhs.span))),
998 }
999 }
1000
1001 fn push_frame(&mut self, frame: Frame) {
1002 self.call_stack.push_frame(frame);
1003 }
1004
1005 fn pop_frame(&mut self) {
1006 self.call_stack.pop_frame();
1007 }
1008}
1009
1010fn spec_from_functor_app(functor: FunctorApp) -> Spec {
1011 match (functor.adjoint, functor.controlled) {
1012 (false, 0) => Spec::Body,
1013 (true, 0) => Spec::Adj,
1014 (false, _) => Spec::Ctl,
1015 (true, _) => Spec::CtlAdj,
1016 }
1017}
1018
1019fn value_to_call_id(val: &Value, span: Span) -> ControlFlow<Reason, (GlobalId, FunctorApp)> {
1020 match val {
1021 Value::Closure => Break(Reason::Error(Error::Unimplemented("closure", span))),
1022 Value::Global(global, functor) => Continue((*global, *functor)),
1023 _ => Break(Reason::Error(Error::Type(
1024 "Callable",
1025 val.type_name(),
1026 span,
1027 ))),
1028 }
1029}
1030
1031fn lit_to_val(lit: &Lit) -> Value {
1032 match lit {
1033 Lit::BigInt(v) => Value::BigInt(v.clone()),
1034 Lit::Bool(v) => Value::Bool(*v),
1035 Lit::Double(v) => Value::Double(*v),
1036 Lit::Int(v) => Value::Int(*v),
1037 Lit::Pauli(v) => Value::Pauli(*v),
1038 Lit::Result(hir::Result::Zero) => Value::Result(false),
1039 Lit::Result(hir::Result::One) => Value::Result(true),
1040 Lit::String(v) => Value::String(v.clone()),
1041 }
1042}
1043
1044fn index_array(arr: &[Value], index: i64, span: Span) -> ControlFlow<Reason, Value> {
1045 match arr.get(index.as_index(span)?) {
1046 Some(v) => Continue(v.clone()),
1047 None => Break(Reason::Error(Error::OutOfRange(index, span))),
1048 }
1049}
1050
1051fn slice_array(
1052 arr: &[Value],
1053 start: Option<i64>,
1054 step: i64,
1055 end: Option<i64>,
1056 span: Span,
1057) -> ControlFlow<Reason, Value> {
1058 if step == 0 {
1059 Break(Reason::Error(Error::RangeStepZero(span)))
1060 } else {
1061 let len: i64 = match arr.len().try_into() {
1062 Ok(len) => Continue(len),
1063 Err(_) => Break(Reason::Error(Error::ArrayTooLarge(span))),
1064 }?;
1065 let (start, end) = if step > 0 {
1066 (start.unwrap_or(0), end.unwrap_or(len - 1))
1067 } else {
1068 (start.unwrap_or(len - 1), end.unwrap_or(0))
1069 };
1070
1071 let range = Range::new(start, step, end);
1072 let mut slice = vec![];
1073 for i in range {
1074 slice.push(index_array(arr, i, span)?);
1075 }
1076
1077 Continue(Value::Array(slice.into()))
1078 }
1079}
1080
1081fn update_functor_app(functor: Functor, app: FunctorApp) -> FunctorApp {
1082 match functor {
1083 Functor::Adj => FunctorApp {
1084 adjoint: !app.adjoint,
1085 controlled: app.controlled,
1086 },
1087 Functor::Ctl => FunctorApp {
1088 adjoint: app.adjoint,
1089 controlled: app.controlled + 1,
1090 },
1091 }
1092}
1093
1094fn eval_binop_add(
1095 lhs_val: Value,
1096 lhs_span: Span,
1097 rhs_val: Value,
1098 rhs_span: Span,
1099) -> ControlFlow<Reason, Value> {
1100 match lhs_val {
1101 Value::Array(arr) => {
1102 let rhs_arr = rhs_val.try_into_array().with_span(rhs_span)?;
1103 let items: Vec<_> = arr.iter().cloned().chain(rhs_arr.iter().cloned()).collect();
1104 Continue(Value::Array(items.into()))
1105 }
1106 Value::BigInt(val) => {
1107 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1108 Continue(Value::BigInt(val + rhs))
1109 }
1110 Value::Double(val) => {
1111 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1112 Continue(Value::Double(val + rhs))
1113 }
1114 Value::Int(val) => {
1115 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1116 Continue(Value::Int(val + rhs))
1117 }
1118 Value::String(val) => {
1119 let rhs = rhs_val.try_into_string().with_span(rhs_span)?;
1120 Continue(Value::String((val.to_string() + &rhs).into()))
1121 }
1122 _ => Break(Reason::Error(Error::Type(
1123 "Array, BigInt, Double, Int, or String",
1124 lhs_val.type_name(),
1125 lhs_span,
1126 ))),
1127 }
1128}
1129
1130fn eval_binop_andb(
1131 lhs_val: Value,
1132 lhs_span: Span,
1133 rhs_val: Value,
1134 rhs_span: Span,
1135) -> ControlFlow<Reason, Value> {
1136 match lhs_val {
1137 Value::BigInt(val) => {
1138 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1139 Continue(Value::BigInt(val & rhs))
1140 }
1141 Value::Int(val) => {
1142 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1143 Continue(Value::Int(val & rhs))
1144 }
1145 _ => Break(Reason::Error(Error::Type(
1146 "BigInt or Int",
1147 lhs_val.type_name(),
1148 lhs_span,
1149 ))),
1150 }
1151}
1152
1153fn eval_binop_div(
1154 lhs_val: Value,
1155 lhs_span: Span,
1156 rhs_val: Value,
1157 rhs_span: Span,
1158) -> ControlFlow<Reason, Value> {
1159 match lhs_val {
1160 Value::BigInt(val) => {
1161 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1162 if rhs == BigInt::from(0) {
1163 Break(Reason::Error(Error::DivZero(rhs_span)))
1164 } else {
1165 Continue(Value::BigInt(val / rhs))
1166 }
1167 }
1168 Value::Int(val) => {
1169 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1170 if rhs == 0 {
1171 Break(Reason::Error(Error::DivZero(rhs_span)))
1172 } else {
1173 Continue(Value::Int(val / rhs))
1174 }
1175 }
1176 Value::Double(val) => {
1177 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1178 if rhs == 0.0 {
1179 Break(Reason::Error(Error::DivZero(rhs_span)))
1180 } else {
1181 Continue(Value::Double(val / rhs))
1182 }
1183 }
1184 _ => Break(Reason::Error(Error::Type(
1185 "BigInt, Double, or Int",
1186 lhs_val.type_name(),
1187 lhs_span,
1188 ))),
1189 }
1190}
1191
1192fn supports_eq(val: &Value, val_span: Span) -> ControlFlow<Reason, ()> {
1193 match val {
1194 Value::Closure | Value::Global(..) => {
1195 Break(Reason::Error(Error::Equality(val.type_name(), val_span)))
1196 }
1197 _ => Continue(()),
1198 }
1199}
1200
1201fn eval_binop_eq(
1202 lhs_val: &Value,
1203 lhs_span: Span,
1204 rhs_val: &Value,
1205 rhs_span: Span,
1206) -> ControlFlow<Reason, Value> {
1207 supports_eq(lhs_val, lhs_span)?;
1208 if lhs_val.type_name() == rhs_val.type_name() {
1209 Continue(Value::Bool(lhs_val == rhs_val))
1210 } else {
1211 Break(Reason::Error(Error::Type(
1212 lhs_val.type_name(),
1213 rhs_val.type_name(),
1214 rhs_span,
1215 )))
1216 }
1217}
1218
1219fn eval_binop_exp(
1220 lhs_val: Value,
1221 lhs_span: Span,
1222 rhs_val: Value,
1223 rhs_span: Span,
1224) -> ControlFlow<Reason, Value> {
1225 match lhs_val {
1226 Value::BigInt(val) => {
1227 let rhs_val: i64 = rhs_val.try_into().with_span(rhs_span)?;
1228 if rhs_val < 0 {
1229 Break(Reason::Error(Error::Negative(rhs_val, rhs_span)))
1230 } else {
1231 let rhs_val: u32 = match rhs_val.try_into() {
1232 Ok(v) => Continue(v),
1233 Err(_) => Break(Reason::Error(Error::IntTooLarge(rhs_val, rhs_span))),
1234 }?;
1235 Continue(Value::BigInt(val.pow(rhs_val)))
1236 }
1237 }
1238 Value::Double(val) => Continue(Value::Double(
1239 val.powf(rhs_val.try_into().with_span(rhs_span)?),
1240 )),
1241 Value::Int(val) => {
1242 let rhs_val: i64 = rhs_val.try_into().with_span(rhs_span)?;
1243 if rhs_val < 0 {
1244 Break(Reason::Error(Error::Negative(rhs_val, rhs_span)))
1245 } else {
1246 let rhs_val: u32 = match rhs_val.try_into() {
1247 Ok(v) => Continue(v),
1248 Err(_) => Break(Reason::Error(Error::IntTooLarge(rhs_val, rhs_span))),
1249 }?;
1250 Continue(Value::Int(val.pow(rhs_val)))
1251 }
1252 }
1253 _ => Break(Reason::Error(Error::Type(
1254 "BigInt, Double, or Int",
1255 lhs_val.type_name(),
1256 lhs_span,
1257 ))),
1258 }
1259}
1260
1261fn eval_binop_gt(
1262 lhs_val: Value,
1263 lhs_span: Span,
1264 rhs_val: Value,
1265 rhs_span: Span,
1266) -> ControlFlow<Reason, Value> {
1267 match lhs_val {
1268 Value::BigInt(val) => {
1269 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1270 Continue(Value::Bool(val > rhs))
1271 }
1272 Value::Int(val) => {
1273 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1274 Continue(Value::Bool(val > rhs))
1275 }
1276 Value::Double(val) => {
1277 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1278 Continue(Value::Bool(val > rhs))
1279 }
1280 _ => Break(Reason::Error(Error::Type(
1281 "BigInt, Double, or Int",
1282 lhs_val.type_name(),
1283 lhs_span,
1284 ))),
1285 }
1286}
1287
1288fn eval_binop_gte(
1289 lhs_val: Value,
1290 lhs_span: Span,
1291 rhs_val: Value,
1292 rhs_span: Span,
1293) -> ControlFlow<Reason, Value> {
1294 match lhs_val {
1295 Value::BigInt(val) => {
1296 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1297 Continue(Value::Bool(val >= rhs))
1298 }
1299 Value::Int(val) => {
1300 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1301 Continue(Value::Bool(val >= rhs))
1302 }
1303 Value::Double(val) => {
1304 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1305 Continue(Value::Bool(val >= rhs))
1306 }
1307 _ => Break(Reason::Error(Error::Type(
1308 "BigInt, Double, or Int",
1309 lhs_val.type_name(),
1310 lhs_span,
1311 ))),
1312 }
1313}
1314
1315fn eval_binop_lt(
1316 lhs_val: Value,
1317 lhs_span: Span,
1318 rhs_val: Value,
1319 rhs_span: Span,
1320) -> ControlFlow<Reason, Value> {
1321 match lhs_val {
1322 Value::BigInt(val) => {
1323 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1324 Continue(Value::Bool(val < rhs))
1325 }
1326 Value::Int(val) => {
1327 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1328 Continue(Value::Bool(val < rhs))
1329 }
1330 Value::Double(val) => {
1331 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1332 Continue(Value::Bool(val < rhs))
1333 }
1334 _ => Break(Reason::Error(Error::Type(
1335 "BigInt, Double, or Int",
1336 lhs_val.type_name(),
1337 lhs_span,
1338 ))),
1339 }
1340}
1341
1342fn eval_binop_lte(
1343 lhs_val: Value,
1344 lhs_span: Span,
1345 rhs_val: Value,
1346 rhs_span: Span,
1347) -> ControlFlow<Reason, Value> {
1348 match lhs_val {
1349 Value::BigInt(val) => {
1350 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1351 Continue(Value::Bool(val <= rhs))
1352 }
1353 Value::Int(val) => {
1354 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1355 Continue(Value::Bool(val <= rhs))
1356 }
1357 Value::Double(val) => {
1358 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1359 Continue(Value::Bool(val <= rhs))
1360 }
1361 _ => Break(Reason::Error(Error::Type(
1362 "BigInt, Double, or Int",
1363 lhs_val.type_name(),
1364 lhs_span,
1365 ))),
1366 }
1367}
1368
1369fn eval_binop_mod(
1370 lhs_val: Value,
1371 lhs_span: Span,
1372 rhs_val: Value,
1373 rhs_span: Span,
1374) -> ControlFlow<Reason, Value> {
1375 match lhs_val {
1376 Value::BigInt(val) => {
1377 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1378 Continue(Value::BigInt(val % rhs))
1379 }
1380 Value::Int(val) => {
1381 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1382 Continue(Value::Int(val % rhs))
1383 }
1384 Value::Double(val) => {
1385 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1386 Continue(Value::Double(val % rhs))
1387 }
1388 _ => Break(Reason::Error(Error::Type(
1389 "BigInt, Double, or Int",
1390 lhs_val.type_name(),
1391 lhs_span,
1392 ))),
1393 }
1394}
1395
1396fn eval_binop_mul(
1397 lhs_val: Value,
1398 lhs_span: Span,
1399 rhs_val: Value,
1400 rhs_span: Span,
1401) -> ControlFlow<Reason, Value> {
1402 match lhs_val {
1403 Value::BigInt(val) => {
1404 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1405 Continue(Value::BigInt(val * rhs))
1406 }
1407 Value::Int(val) => {
1408 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1409 Continue(Value::Int(val * rhs))
1410 }
1411 Value::Double(val) => {
1412 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1413 Continue(Value::Double(val * rhs))
1414 }
1415 _ => Break(Reason::Error(Error::Type(
1416 "BigInt, Double, or Int",
1417 lhs_val.type_name(),
1418 lhs_span,
1419 ))),
1420 }
1421}
1422
1423fn eval_binop_neq(
1424 lhs_val: &Value,
1425 lhs_span: Span,
1426 rhs_val: &Value,
1427 rhs_span: Span,
1428) -> ControlFlow<Reason, Value> {
1429 supports_eq(lhs_val, lhs_span)?;
1430 if lhs_val.type_name() == rhs_val.type_name() {
1431 Continue(Value::Bool(lhs_val != rhs_val))
1432 } else {
1433 Break(Reason::Error(Error::Type(
1434 lhs_val.type_name(),
1435 rhs_val.type_name(),
1436 rhs_span,
1437 )))
1438 }
1439}
1440
1441fn eval_binop_orb(
1442 lhs_val: Value,
1443 lhs_span: Span,
1444 rhs_val: Value,
1445 rhs_span: Span,
1446) -> ControlFlow<Reason, Value> {
1447 match lhs_val {
1448 Value::BigInt(val) => {
1449 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1450 Continue(Value::BigInt(val | rhs))
1451 }
1452 Value::Int(val) => {
1453 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1454 Continue(Value::Int(val | rhs))
1455 }
1456 _ => Break(Reason::Error(Error::Type(
1457 "BigInt or Int",
1458 lhs_val.type_name(),
1459 lhs_span,
1460 ))),
1461 }
1462}
1463
1464fn eval_binop_shl(
1465 lhs_val: Value,
1466 lhs_span: Span,
1467 rhs_val: Value,
1468 rhs_span: Span,
1469) -> ControlFlow<Reason, Value> {
1470 match lhs_val {
1471 Value::BigInt(val) => {
1472 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1473 if rhs > 0 {
1474 Continue(Value::BigInt(val << rhs))
1475 } else {
1476 Continue(Value::BigInt(val >> rhs.abs()))
1477 }
1478 }
1479 Value::Int(val) => {
1480 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1481 if rhs > 0 {
1482 Continue(Value::Int(val << rhs))
1483 } else {
1484 Continue(Value::Int(val >> rhs.abs()))
1485 }
1486 }
1487 _ => Break(Reason::Error(Error::Type(
1488 "BigInt or Int",
1489 lhs_val.type_name(),
1490 lhs_span,
1491 ))),
1492 }
1493}
1494
1495fn eval_binop_shr(
1496 lhs_val: Value,
1497 lhs_span: Span,
1498 rhs_val: Value,
1499 rhs_span: Span,
1500) -> ControlFlow<Reason, Value> {
1501 match lhs_val {
1502 Value::BigInt(val) => {
1503 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1504 if rhs > 0 {
1505 Continue(Value::BigInt(val >> rhs))
1506 } else {
1507 Continue(Value::BigInt(val << rhs.abs()))
1508 }
1509 }
1510 Value::Int(val) => {
1511 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1512 if rhs > 0 {
1513 Continue(Value::Int(val >> rhs))
1514 } else {
1515 Continue(Value::Int(val << rhs.abs()))
1516 }
1517 }
1518 _ => Break(Reason::Error(Error::Type(
1519 "BigInt or Int",
1520 lhs_val.type_name(),
1521 lhs_span,
1522 ))),
1523 }
1524}
1525
1526fn eval_binop_sub(
1527 lhs_val: Value,
1528 lhs_span: Span,
1529 rhs_val: Value,
1530 rhs_span: Span,
1531) -> ControlFlow<Reason, Value> {
1532 match lhs_val {
1533 Value::BigInt(val) => {
1534 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1535 Continue(Value::BigInt(val - rhs))
1536 }
1537 Value::Int(val) => {
1538 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1539 Continue(Value::Int(val - rhs))
1540 }
1541 Value::Double(val) => {
1542 let rhs: f64 = rhs_val.try_into().with_span(rhs_span)?;
1543 Continue(Value::Double(val - rhs))
1544 }
1545 _ => Break(Reason::Error(Error::Type(
1546 "BigInt, Double, or Int",
1547 lhs_val.type_name(),
1548 lhs_span,
1549 ))),
1550 }
1551}
1552
1553fn eval_binop_xorb(
1554 lhs_val: Value,
1555 lhs_span: Span,
1556 rhs_val: Value,
1557 rhs_span: Span,
1558) -> ControlFlow<Reason, Value> {
1559 match lhs_val {
1560 Value::BigInt(val) => {
1561 let rhs: BigInt = rhs_val.try_into().with_span(rhs_span)?;
1562 Continue(Value::BigInt(val ^ rhs))
1563 }
1564 Value::Int(val) => {
1565 let rhs: i64 = rhs_val.try_into().with_span(rhs_span)?;
1566 Continue(Value::Int(val ^ rhs))
1567 }
1568 _ => Break(Reason::Error(Error::Type(
1569 "BigInt or Int",
1570 lhs_val.type_name(),
1571 lhs_span,
1572 ))),
1573 }
1574}
1575