| 79 | | // newFunction(t, &flatten, "flatten"); fielda(t, -2, "flatten"); |
|---|
| 80 | | // newFunction(t, &makeHeap, "makeHeap"); fielda(t, -2, "makeHeap"); |
|---|
| 81 | | // newFunction(t, &pushHeap, "pushHeap"); fielda(t, -2, "pushHeap"); |
|---|
| 82 | | // newFunction(t, &popHeap, "popHeap"); fielda(t, -2, "popHeap"); |
|---|
| 83 | | // newFunction(t, &sortHeap, "sortHeap"); fielda(t, -2, "sortHeap"); |
|---|
| 84 | | // newFunction(t, &count, "count"); fielda(t, -2, "count"); |
|---|
| 85 | | // newFunction(t, &countIf, "countIf"); fielda(t, -2, "countIf"); |
|---|
| | 78 | |
|---|
| | 79 | newTable(t); |
|---|
| | 80 | newFunction(t, &flatten, "flatten", 1); fielda(t, -2, "flatten"); |
|---|
| | 81 | |
|---|
| | 82 | newFunction(t, &makeHeap, "makeHeap"); fielda(t, -2, "makeHeap"); |
|---|
| | 83 | newFunction(t, &pushHeap, "pushHeap"); fielda(t, -2, "pushHeap"); |
|---|
| | 84 | newFunction(t, &popHeap, "popHeap"); fielda(t, -2, "popHeap"); |
|---|
| | 85 | newFunction(t, &sortHeap, "sortHeap"); fielda(t, -2, "sortHeap"); |
|---|
| | 86 | newFunction(t, &count, "count"); fielda(t, -2, "count"); |
|---|
| | 87 | newFunction(t, &countIf, "countIf"); fielda(t, -2, "countIf"); |
|---|
| 801 | | bool[MDArray] flattening; |
|---|
| 802 | | auto ret = new MDArray(0); |
|---|
| 803 | | |
|---|
| 804 | | void flatten(MDArray a) |
|---|
| 805 | | { |
|---|
| 806 | | if(a in flattening) |
|---|
| 807 | | s.throwRuntimeException("Attempting to flatten a self-referencing array"); |
|---|
| 808 | | |
|---|
| 809 | | flattening[a] = true; |
|---|
| 810 | | |
|---|
| 811 | | foreach(ref val; a) |
|---|
| 812 | | { |
|---|
| 813 | | if(val.isArray) |
|---|
| 814 | | flatten(val.as!(MDArray)); |
|---|
| | 810 | checkParam(t, 0, MDValue.Type.Array); |
|---|
| | 811 | auto flattening = getUpval(t, 0); |
|---|
| | 812 | |
|---|
| | 813 | auto ret = newArray(t, 0); |
|---|
| | 814 | |
|---|
| | 815 | void flatten(word arr) |
|---|
| | 816 | { |
|---|
| | 817 | auto a = absIndex(t, arr); |
|---|
| | 818 | |
|---|
| | 819 | if(opin(t, a, flattening)) |
|---|
| | 820 | throwException(t, "Attempting to flatten a self-referencing array"); |
|---|
| | 821 | |
|---|
| | 822 | dup(t, a); |
|---|
| | 823 | pushBool(t, true); |
|---|
| | 824 | idxa(t, flattening); |
|---|
| | 825 | |
|---|
| | 826 | scope(exit) |
|---|
| | 827 | { |
|---|
| | 828 | dup(t, a); |
|---|
| | 829 | pushNull(t); |
|---|
| | 830 | idxa(t, flattening); |
|---|
| | 831 | } |
|---|
| | 832 | |
|---|
| | 833 | foreach(ref val; getArray(t, a).slice) |
|---|
| | 834 | { |
|---|
| | 835 | if(val.type == MDValue.Type.Array) |
|---|
| | 836 | flatten(pushArray(t, val.mArray)); |
|---|
| 816 | | ret ~= val; |
|---|
| 817 | | } |
|---|
| 818 | | |
|---|
| 819 | | flattening.remove(a); |
|---|
| 820 | | } |
|---|
| 821 | | |
|---|
| 822 | | flatten(s.getContext!(MDArray)()); |
|---|
| 823 | | s.push(ret); |
|---|
| 824 | | return 1; |
|---|
| 825 | | } |
|---|
| | 838 | { |
|---|
| | 839 | dup(t, ret); |
|---|
| | 840 | push(t, val); |
|---|
| | 841 | cateq(t, 1); |
|---|
| | 842 | pop(t); |
|---|
| | 843 | } |
|---|
| | 844 | } |
|---|
| | 845 | } |
|---|
| | 846 | |
|---|
| | 847 | flatten(0); |
|---|
| | 848 | dup(t, ret); |
|---|
| | 849 | return 1; |
|---|
| | 850 | } |
|---|
| | 851 | |
|---|
| | 852 | uword makeHeap(MDThread* t, uword numParams) |
|---|
| | 853 | { |
|---|
| | 854 | checkParam(t, 0, MDValue.Type.Array); |
|---|
| | 855 | auto a = getArray(t, 0); |
|---|
| | 856 | |
|---|
| | 857 | .makeHeap(a.slice, (ref MDValue a, ref MDValue b) |
|---|
| | 858 | { |
|---|
| | 859 | push(t, a); |
|---|
| | 860 | push(t, b); |
|---|
| | 861 | auto ret = cmp(t, -2, -1) < 0; |
|---|
| | 862 | pop(t, 2); |
|---|
| | 863 | return ret; |
|---|
| | 864 | }); |
|---|
| | 865 | |
|---|
| | 866 | dup(t, 0); |
|---|
| | 867 | return 1; |
|---|
| | 868 | } |
|---|
| | 869 | |
|---|
| | 870 | uword pushHeap(MDThread* t, uword numParams) |
|---|
| | 871 | { |
|---|
| | 872 | checkParam(t, 0, MDValue.Type.Array); |
|---|
| | 873 | checkAnyParam(t, 1); |
|---|
| | 874 | auto a = getArray(t, 0); |
|---|
| | 875 | |
|---|
| | 876 | .pushHeap(a.slice, *getValue(t, 1), (ref MDValue a, ref MDValue b) |
|---|
| | 877 | { |
|---|
| | 878 | push(t, a); |
|---|
| | 879 | push(t, b); |
|---|
| | 880 | auto ret = cmp(t, -2, -1) < 0; |
|---|
| | 881 | pop(t, 2); |
|---|
| | 882 | return ret; |
|---|
| | 883 | }); |
|---|
| | 884 | |
|---|
| | 885 | dup(t, 0); |
|---|
| | 886 | return 1; |
|---|
| | 887 | } |
|---|
| | 888 | |
|---|
| | 889 | uword popHeap(MDThread* t, uword numParams) |
|---|
| | 890 | { |
|---|
| | 891 | checkParam(t, 0, MDValue.Type.Array); |
|---|
| | 892 | |
|---|
| | 893 | if(len(t, 0) == 0) |
|---|
| | 894 | throwException(t, "Array is empty"); |
|---|
| | 895 | |
|---|
| | 896 | idxi(t, 0, 0, true); |
|---|
| | 897 | |
|---|
| | 898 | .popHeap(getArray(t, 0).slice, (ref MDValue a, ref MDValue b) |
|---|
| | 899 | { |
|---|
| | 900 | push(t, a); |
|---|
| | 901 | push(t, b); |
|---|
| | 902 | auto ret = cmp(t, -2, -1) < 0; |
|---|
| | 903 | pop(t, 2); |
|---|
| | 904 | return ret; |
|---|
| | 905 | }); |
|---|
| | 906 | |
|---|
| | 907 | return 1; |
|---|
| | 908 | } |
|---|
| | 909 | |
|---|
| | 910 | uword sortHeap(MDThread* t, uword numParams) |
|---|
| | 911 | { |
|---|
| | 912 | checkParam(t, 0, MDValue.Type.Array); |
|---|
| | 913 | |
|---|
| | 914 | .sortHeap(getArray(t, 0).slice, (ref MDValue a, ref MDValue b) |
|---|
| | 915 | { |
|---|
| | 916 | push(t, a); |
|---|
| | 917 | push(t, b); |
|---|
| | 918 | auto ret = cmp(t, -2, -1) < 0; |
|---|
| | 919 | pop(t, 2); |
|---|
| | 920 | return ret; |
|---|
| | 921 | }); |
|---|
| | 922 | |
|---|
| | 923 | dup(t, 0); |
|---|
| | 924 | return 1; |
|---|
| | 925 | } |
|---|
| | 926 | |
|---|
| | 927 | uword count(MDThread* t, uword numParams) |
|---|
| | 928 | { |
|---|
| | 929 | checkParam(t, 0, MDValue.Type.Array); |
|---|
| | 930 | checkAnyParam(t, 1); |
|---|
| | 931 | |
|---|
| | 932 | bool delegate(MDValue, MDValue) pred; |
|---|
| | 933 | |
|---|
| | 934 | if(numParams > 1) |
|---|
| | 935 | { |
|---|
| | 936 | checkParam(t, 2, MDValue.Type.Function); |
|---|
| | 937 | |
|---|
| | 938 | pred = (MDValue a, MDValue b) |
|---|
| | 939 | { |
|---|
| | 940 | auto reg = dup(t, 2); |
|---|
| | 941 | pushNull(t); |
|---|
| | 942 | push(t, a); |
|---|
| | 943 | push(t, b); |
|---|
| | 944 | rawCall(t, reg, 1); |
|---|
| | 945 | |
|---|
| | 946 | if(!isBool(t, -1)) |
|---|
| | 947 | { |
|---|
| | 948 | pushTypeString(t, -1); |
|---|
| | 949 | throwException(t, "count predicate expected to return 'bool', not '{}'", getString(t, -1)); |
|---|
| | 950 | } |
|---|
| | 951 | |
|---|
| | 952 | auto ret = getBool(t, -1); |
|---|
| | 953 | pop(t); |
|---|
| | 954 | return ret; |
|---|
| | 955 | }; |
|---|
| | 956 | } |
|---|
| | 957 | else |
|---|
| | 958 | { |
|---|
| | 959 | pred = (MDValue a, MDValue b) |
|---|
| | 960 | { |
|---|
| | 961 | push(t, a); |
|---|
| | 962 | push(t, b); |
|---|
| | 963 | auto ret = cmp(t, -2, -1) == 0; |
|---|
| | 964 | pop(t, 2); |
|---|
| | 965 | return ret; |
|---|
| | 966 | }; |
|---|
| | 967 | } |
|---|
| | 968 | |
|---|
| | 969 | pushInt(t, .count(getArray(t, 0).slice, *getValue(t, 1), pred)); |
|---|
| | 970 | return 1; |
|---|
| | 971 | } |
|---|
| | 972 | |
|---|
| | 973 | uword countIf(MDThread* t, uword numParams) |
|---|
| | 974 | { |
|---|
| | 975 | checkParam(t, 0, MDValue.Type.Array); |
|---|
| | 976 | checkParam(t, 1, MDValue.Type.Function); |
|---|
| | 977 | |
|---|
| | 978 | pushInt(t, .countIf(getArray(t, 0).slice, (MDValue a) |
|---|
| | 979 | { |
|---|
| | 980 | auto reg = dup(t, 1); |
|---|
| | 981 | pushNull(t); |
|---|
| | 982 | push(t, a); |
|---|
| | 983 | rawCall(t, reg, 1); |
|---|
| | 984 | |
|---|
| | 985 | if(!isBool(t, -1)) |
|---|
| | 986 | { |
|---|
| | 987 | pushTypeString(t, -1); |
|---|
| | 988 | throwException(t, "count predicate expected to return 'bool', not '{}'", getString(t, -1)); |
|---|
| | 989 | } |
|---|
| 827 | | uword makeHeap(MDThread* t, uword numParams) |
|---|
| 828 | | { |
|---|
| 829 | | auto self = s.getContext!(MDArray)(); |
|---|
| 830 | | .makeHeap(self.mData, (ref MDValue a, ref MDValue b) { return s.cmp(a, b) < 0; }); |
|---|
| 831 | | s.push(self); |
|---|
| 832 | | return 1; |
|---|
| 833 | | } |
|---|
| 834 | | |
|---|
| 835 | | uword pushHeap(MDThread* t, uword numParams) |
|---|
| 836 | | { |
|---|
| 837 | | auto self = s.getContext!(MDArray)(); |
|---|
| 838 | | auto val = s.getParam(0u); |
|---|
| 839 | | .pushHeap(self.mData, val, (ref MDValue a, ref MDValue b) { return s.cmp(a, b) < 0; }); |
|---|
| 840 | | s.push(self); |
|---|
| 841 | | return 1; |
|---|
| 842 | | } |
|---|
| 843 | | |
|---|
| 844 | | uword popHeap(MDThread* t, uword numParams) |
|---|
| 845 | | { |
|---|
| 846 | | auto self = s.getContext!(MDArray)(); |
|---|
| 847 | | |
|---|
| 848 | | if(self.length == 0) |
|---|
| 849 | | s.throwRuntimeException("Array is empty"); |
|---|
| 850 | | |
|---|
| 851 | | s.push(self[0]); |
|---|
| 852 | | .popHeap(self.mData, (ref MDValue a, ref MDValue b) { return s.cmp(a, b) < 0; }); |
|---|
| 853 | | return 1; |
|---|
| 854 | | } |
|---|
| 855 | | |
|---|
| 856 | | uword sortHeap(MDThread* t, uword numParams) |
|---|
| 857 | | { |
|---|
| 858 | | auto self = s.getContext!(MDArray)(); |
|---|
| 859 | | .sortHeap(self.mData, (ref MDValue a, ref MDValue b) { return s.cmp(a, b) < 0; }); |
|---|
| 860 | | s.push(self); |
|---|
| 861 | | return 1; |
|---|
| 862 | | } |
|---|
| 863 | | |
|---|
| 864 | | uword count(MDThread* t, uword numParams) |
|---|
| 865 | | { |
|---|
| 866 | | auto self = s.getContext!(MDArray)(); |
|---|
| 867 | | auto val = s.getParam(0u); |
|---|
| 868 | | |
|---|
| 869 | | bool delegate(MDValue, MDValue) pred; |
|---|
| 870 | | |
|---|
| 871 | | if(numParams > 1) |
|---|
| 872 | | { |
|---|
| 873 | | auto cl = s.getParam!(MDClosure)(1); |
|---|
| 874 | | pred = (MDValue a, MDValue b) |
|---|
| 875 | | { |
|---|
| 876 | | s.call(cl, 1, a, b); |
|---|
| 877 | | return s.pop!(bool)(); |
|---|
| 878 | | }; |
|---|
| 879 | | } |
|---|
| 880 | | else |
|---|
| 881 | | pred = (MDValue a, MDValue b) { return s.cmp(a, b) == 0; }; |
|---|
| 882 | | |
|---|
| 883 | | s.push(.count(self.mData, val, pred)); |
|---|
| 884 | | return 1; |
|---|
| 885 | | } |
|---|
| 886 | | |
|---|
| 887 | | uword countIf(MDThread* t, uword numParams) |
|---|
| 888 | | { |
|---|
| 889 | | auto self = s.getContext!(MDArray)(); |
|---|
| 890 | | auto cl = s.getParam!(MDClosure)(0); |
|---|
| 891 | | |
|---|
| 892 | | s.push(.countIf(self.mData, (MDValue a) |
|---|
| 893 | | { |
|---|
| 894 | | s.call(cl, 1, a); |
|---|
| 895 | | return s.pop!(bool)(); |
|---|
| | 991 | auto ret = getBool(t, -1); |
|---|
| | 992 | pop(t); |
|---|
| | 993 | return ret; |
|---|