1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
mod bitwise;
mod list;
mod math;
mod num_utils;
mod number;
mod panics;
mod partial_print;
mod print;
mod testing;
mod vector;

use arret_syntax::span::Span;

use crate::mir::builder::Builder;
use crate::mir::error::Result;
use crate::mir::eval_hir::EvalHirCtx;
use crate::mir::Value;

macro_rules! define_eval_intrinsics {
    ( $($name:expr => $handler:path),* ) => {
        pub fn try_eval(
            ehx: &mut EvalHirCtx,
            b: &mut Option<Builder>,
            span: Span,
            intrinsic_name: &'static str,
            arg_list_value: &Value,
        ) -> Result<Option<Value>> {
            match intrinsic_name {
                $(
                    $name => {
                        $handler(ehx, b, span, arg_list_value)
                    }
                ),*
                _ => Ok(None),
            }
        }
    };
}

pub enum BuildOutcome {
    None,
    ReturnValue(Value),
    SimplifiedArgs(Value),
}

macro_rules! define_build_intrinsics {
    ( $($name:expr => $handler:path),* ) => {
        pub fn try_build(
            ehx: &mut EvalHirCtx,
            b: &mut Builder,
            span: Span,
            intrinsic_name: &'static str,
            arg_list_value: &Value,
        ) -> Result<BuildOutcome> {
            match intrinsic_name {
                $(
                    $name => {
                        $handler(ehx, b, span, arg_list_value)
                    }
                ),*
                _ => Ok(BuildOutcome::None),
            }
        }
    };
}

define_eval_intrinsics! {
    "length" => list::length,
    "cons" => list::cons,
    "repeat" => list::repeat,
    "fn-op-categories" => testing::fn_op_categories
}

define_build_intrinsics! {
    "+" => math::add,
    "*" => math::mul,
    "-" => math::sub,
    "/" => math::div,
    "quot" => math::quot,
    "rem" => math::rem,
    "sqrt" => math::sqrt,

    "int" => number::int,
    "float" => number::float,
    "<" => number::num_lt,
    "<=" => number::num_le,
    "==" => number::num_eq,
    ">" => number::num_gt,
    ">=" => number::num_ge,

    // Purity doesn't matter at the MIR level; these are both treated as impure so they're not
    // optimised away.
    "panic" => panics::panics,
    "panic!" => panics::panics,

    "print!" => print::print,
    "println!" => print::print,
    "print-str" => print::print_str,

    "vector-length" => vector::vector_length,
    "vector-ref" => vector::vector_ref,

    "bit-and" => bitwise::bit_and,
    "bit-or" => bitwise::bit_or,
    "bit-xor" => bitwise::bit_xor,
    "bit-not" => bitwise::bit_not,
    "bit-shift-left" => bitwise::bit_shift_left,
    "bit-shift-right" => bitwise::bit_shift_right,
    "unsigned-bit-shift-right" => bitwise::unsigned_bit_shift_right
}