use crate::symbol::Symbol; /// Low-level operations that get translated directly into e.g. LLVM instructions. /// These are always wrapped when exposed to end users, and can only make it /// into an Expr when added directly by can::builtins #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum LowLevel { StrConcat, StrJoinWith, StrIsEmpty, StrStartsWith, StrStartsWithCodePt, StrEndsWith, StrSplit, StrCountGraphemes, StrFromInt, StrFromUtf8, StrFromUtf8Range, StrToUtf8, StrRepeat, StrFromFloat, StrTrim, StrTrimLeft, StrTrimRight, ListLen, ListGetUnsafe, ListSet, ListSingle, ListRepeat, ListReverse, ListConcat, ListContains, ListAppend, ListPrepend, ListJoin, ListRange, ListMap, ListMap2, ListMap3, ListMap4, ListMapWithIndex, ListKeepIf, ListWalk, ListWalkUntil, ListWalkBackwards, ListKeepOks, ListKeepErrs, ListSortWith, ListSublist, ListDropAt, ListSwap, ListAny, ListFindUnsafe, DictSize, DictEmpty, DictInsert, DictRemove, DictContains, DictGetUnsafe, DictKeys, DictValues, DictUnion, DictIntersection, DictDifference, DictWalk, SetFromList, NumAdd, NumAddWrap, NumAddChecked, NumSub, NumSubWrap, NumSubChecked, NumMul, NumMulWrap, NumMulChecked, NumGt, NumGte, NumLt, NumLte, NumCompare, NumDivUnchecked, NumDivCeilUnchecked, NumRemUnchecked, NumIsMultipleOf, NumAbs, NumNeg, NumSin, NumCos, NumSqrtUnchecked, NumLogUnchecked, NumRound, NumToFloat, NumPow, NumCeiling, NumPowInt, NumFloor, NumIsFinite, NumAtan, NumAcos, NumAsin, NumBytesToU16, NumBytesToU32, NumBitwiseAnd, NumBitwiseXor, NumBitwiseOr, NumShiftLeftBy, NumShiftRightBy, NumShiftRightZfBy, NumIntCast, Eq, NotEq, And, Or, Not, Hash, ExpectTrue, } macro_rules! higher_order { () => { ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk | ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith | ListAny | ListFindUnsafe | DictWalk }; } impl LowLevel { /// is one of the arguments always a function? /// An example is List.map. pub fn is_higher_order(&self) -> bool { use LowLevel::*; matches!(self, higher_order!()) } pub fn function_argument_position(&self) -> usize { use LowLevel::*; match self { ListMap => 1, ListMap2 => 2, ListMap3 => 3, ListMap4 => 4, ListMapWithIndex => 1, ListKeepIf => 1, ListWalk => 2, ListWalkUntil => 2, ListWalkBackwards => 2, ListKeepOks => 1, ListKeepErrs => 1, ListSortWith => 1, ListAny => 1, ListFindUnsafe => 1, DictWalk => 2, _ => unreachable!(), } } /// Used in dev backends to inline some lowlevel wrapper functions /// For wrappers that contain logic, we return None to prevent inlining /// (Mention each explicitly rather than using `_`, to show they have not been forgotten) pub fn from_inlined_wrapper(symbol: Symbol) -> Option { use LowLevel::*; match symbol { Symbol::STR_CONCAT => Some(StrConcat), Symbol::STR_JOIN_WITH => Some(StrJoinWith), Symbol::STR_IS_EMPTY => Some(StrIsEmpty), Symbol::STR_STARTS_WITH => Some(StrStartsWith), Symbol::STR_STARTS_WITH_CODE_PT => Some(StrStartsWithCodePt), Symbol::STR_ENDS_WITH => Some(StrEndsWith), Symbol::STR_SPLIT => Some(StrSplit), Symbol::STR_COUNT_GRAPHEMES => Some(StrCountGraphemes), Symbol::STR_FROM_INT => Some(StrFromInt), Symbol::STR_FROM_UTF8 => None, Symbol::STR_FROM_UTF8_RANGE => None, Symbol::STR_TO_UTF8 => Some(StrToUtf8), Symbol::STR_REPEAT => Some(StrRepeat), Symbol::STR_FROM_FLOAT => Some(StrFromFloat), Symbol::STR_TRIM => Some(StrTrim), Symbol::STR_TRIM_LEFT => Some(StrTrimLeft), Symbol::STR_TRIM_RIGHT => Some(StrTrimRight), Symbol::LIST_LEN => Some(ListLen), Symbol::LIST_GET => None, Symbol::LIST_SET => None, Symbol::LIST_SINGLE => Some(ListSingle), Symbol::LIST_REPEAT => Some(ListRepeat), Symbol::LIST_REVERSE => Some(ListReverse), Symbol::LIST_CONCAT => Some(ListConcat), Symbol::LIST_CONTAINS => Some(ListContains), Symbol::LIST_APPEND => Some(ListAppend), Symbol::LIST_PREPEND => Some(ListPrepend), Symbol::LIST_JOIN => Some(ListJoin), Symbol::LIST_RANGE => Some(ListRange), Symbol::LIST_MAP => Some(ListMap), Symbol::LIST_MAP2 => Some(ListMap2), Symbol::LIST_MAP3 => Some(ListMap3), Symbol::LIST_MAP4 => Some(ListMap4), Symbol::LIST_MAP_WITH_INDEX => Some(ListMapWithIndex), Symbol::LIST_KEEP_IF => Some(ListKeepIf), Symbol::LIST_WALK => Some(ListWalk), Symbol::LIST_WALK_UNTIL => Some(ListWalkUntil), Symbol::LIST_WALK_BACKWARDS => Some(ListWalkBackwards), Symbol::LIST_KEEP_OKS => Some(ListKeepOks), Symbol::LIST_KEEP_ERRS => Some(ListKeepErrs), Symbol::LIST_SORT_WITH => Some(ListSortWith), Symbol::LIST_SUBLIST => Some(ListSublist), Symbol::LIST_DROP => Some(ListDrop), Symbol::LIST_DROP_AT => Some(ListDropAt), Symbol::LIST_SWAP => Some(ListSwap), Symbol::LIST_ANY => Some(ListAny), Symbol::LIST_FIND => None, Symbol::DICT_LEN => Some(DictSize), Symbol::DICT_EMPTY => Some(DictEmpty), Symbol::DICT_INSERT => Some(DictInsert), Symbol::DICT_REMOVE => Some(DictRemove), Symbol::DICT_CONTAINS => Some(DictContains), Symbol::DICT_GET => None, Symbol::DICT_KEYS => Some(DictKeys), Symbol::DICT_VALUES => Some(DictValues), Symbol::DICT_UNION => Some(DictUnion), Symbol::DICT_INTERSECTION => Some(DictIntersection), Symbol::DICT_DIFFERENCE => Some(DictDifference), Symbol::DICT_WALK => Some(DictWalk), Symbol::SET_FROM_LIST => Some(SetFromList), Symbol::NUM_ADD => Some(NumAdd), Symbol::NUM_ADD_WRAP => Some(NumAddWrap), Symbol::NUM_ADD_CHECKED => None, Symbol::NUM_SUB => Some(NumSub), Symbol::NUM_SUB_WRAP => Some(NumSubWrap), Symbol::NUM_SUB_CHECKED => None, Symbol::NUM_MUL => Some(NumMul), Symbol::NUM_MUL_WRAP => Some(NumMulWrap), Symbol::NUM_MUL_CHECKED => None, Symbol::NUM_GT => Some(NumGt), Symbol::NUM_GTE => Some(NumGte), Symbol::NUM_LT => Some(NumLt), Symbol::NUM_LTE => Some(NumLte), Symbol::NUM_COMPARE => Some(NumCompare), Symbol::NUM_DIV_FLOAT => None, Symbol::NUM_DIV_CEIL => None, Symbol::NUM_REM => None, Symbol::NUM_IS_MULTIPLE_OF => Some(NumIsMultipleOf), Symbol::NUM_ABS => Some(NumAbs), Symbol::NUM_NEG => Some(NumNeg), Symbol::NUM_SIN => Some(NumSin), Symbol::NUM_COS => Some(NumCos), Symbol::NUM_SQRT => None, Symbol::NUM_LOG => None, Symbol::NUM_ROUND => Some(NumRound), Symbol::NUM_TO_FLOAT => Some(NumToFloat), Symbol::NUM_POW => Some(NumPow), Symbol::NUM_CEILING => Some(NumCeiling), Symbol::NUM_POW_INT => Some(NumPowInt), Symbol::NUM_FLOOR => Some(NumFloor), // => Some(NumIsFinite), Symbol::NUM_ATAN => Some(NumAtan), Symbol::NUM_ACOS => Some(NumAcos), Symbol::NUM_ASIN => Some(NumAsin), Symbol::NUM_BYTES_TO_U16 => None, Symbol::NUM_BYTES_TO_U32 => None, Symbol::NUM_BITWISE_AND => Some(NumBitwiseAnd), Symbol::NUM_BITWISE_XOR => Some(NumBitwiseXor), Symbol::NUM_BITWISE_OR => Some(NumBitwiseOr), Symbol::NUM_SHIFT_LEFT => Some(NumShiftLeftBy), Symbol::NUM_SHIFT_RIGHT => Some(NumShiftRightBy), Symbol::NUM_SHIFT_RIGHT_ZERO_FILL => Some(NumShiftRightZfBy), Symbol::NUM_INT_CAST => Some(NumIntCast), Symbol::BOOL_EQ => Some(Eq), Symbol::BOOL_NEQ => Some(NotEq), Symbol::BOOL_AND => Some(And), Symbol::BOOL_OR => Some(Or), Symbol::BOOL_NOT => Some(Not), // => Some(Hash), // => Some(ExpectTrue), _ => None, } } }