@@ -395,71 +395,119 @@ int list_count(struct YASL_State *S) {
395395 return 1 ;
396396}
397397
398- static const int SORT_TYPE_EMPTY = 0 ;
399- static const int SORT_TYPE_STR = -1 ;
400- static const int SORT_TYPE_NUM = 1 ;
401- void sort (struct YASL_Object * list , const size_t len ) {
402- // Base cases
403- struct YASL_Object tmpObj ;
404- if (len < 2 ) return ;
405- if (len == 2 ) {
406- if (yasl_object_cmp (list [0 ], list [1 ]) > 0 ) {
407- tmpObj = list [0 ];
408- list [0 ] = list [1 ];
409- list [1 ] = tmpObj ;
410- }
411- return ;
398+ enum SortType {
399+ SORT_TYPE_STR = -1 ,
400+ SORT_TYPE_EMPTY = 0 ,
401+ SORT_TYPE_NUM = 1
402+ };
403+
404+
405+ int custom_comp (struct YASL_State * S , struct YASL_Object a , struct YASL_Object b ) {
406+ YASL_duptop (S );
407+ vm_push ((struct VM * )S , a );
408+ vm_push ((struct VM * )S , b );
409+ YASL_functioncall (S , 2 );
410+ if (!YASL_isbool (S )) {
411+ YASL_print_err (S , "TypeError: Expected a function returning bool, got %s." , YASL_peektypename (S ));
412+ YASL_throw_err (S , YASL_TYPE_ERROR );
412413 }
413-
414- // YASL_Set sorting bounds
415- size_t left = 0 ;
416- size_t right = len - 1 ;
417-
418- // Determine random midpoint to use (good average case)
419- const size_t randIndex = rand () % len ;
420- const struct YASL_Object mid = list [randIndex ];
421-
422- // Determine exact number of items less than mid (mid's index)
423- // Furthermore, ensure list is not homogenous to avoid infinite loops
424- size_t ltCount = 0 ;
425- int seenDifferent = 0 ;
426- for (size_t i = 0 ; i < len ; i ++ ) {
427- if (yasl_object_cmp (list [i ], mid ) < 0 ) ltCount ++ ;
428- if (seenDifferent == 0 && yasl_object_cmp (list [0 ], list [i ]) != 0 ) seenDifferent = 1 ;
414+ bool a_lt_b = YASL_popbool (S );
415+
416+ YASL_duptop (S );
417+ vm_push ((struct VM * )S , b );
418+ vm_push ((struct VM * )S , a );
419+ YASL_functioncall (S , 2 );
420+ if (!YASL_isbool (S )) {
421+ YASL_print_err (S , "TypeError: Expected a function returning bool, got %s." , YASL_peektypename (S ));
422+ YASL_throw_err (S , YASL_TYPE_ERROR );
429423 }
430- if (seenDifferent == 0 ) return ;
431424
432- // Ensure all items are on the correct side of mid
433- while (left < right ) {
434- while (yasl_object_cmp (list [left ], mid ) < 0 ) left ++ ;
435- while (yasl_object_cmp (list [right ], mid ) >= 0 ) {
436- if (right == 0 ) break ;
437- right -- ;
438- }
425+ bool a_gt_b = YASL_popbool (S );
439426
440- int cmp = yasl_object_cmp (list [left ], list [right ]);
441- if (cmp > 0 && left < right ) {
442- tmpObj = list [right ];
443- list [right ] = list [left ];
444- list [left ++ ] = tmpObj ;
445- if (right == 0 ) break ;
446- right -- ;
447- } else if (cmp == 0 ) {
448- left ++ ;
449- if (right == 0 ) break ;
450- right -- ;
451- }
452- }
427+ if (a_lt_b == a_gt_b ) return 0 ;
428+ return a_lt_b ? -1 : a_gt_b ? 1 : 0 ;
429+ }
453430
454- // Let sort() finish that for us...
455- sort (list , ltCount );
456- sort (& list [ltCount ], len - ltCount );
431+ #define CUSTOM_COMP (a , b ) custom_comp(S, a, b)
432+
433+ #define DEF_SORT (name , COMP ) \
434+ static void name##sort(struct YASL_State *S, struct YASL_Object *list, const size_t len) {\
435+ /* Base cases*/ \
436+ struct YASL_Object tmpObj ;\
437+ if (len < 2 ) return ;\
438+ if (len == 2 ) {\
439+ if (COMP (list [0 ], list [1 ]) > 0 ) {\
440+ tmpObj = list [0 ];\
441+ list [0 ] = list [1 ];\
442+ list [1 ] = tmpObj ;\
443+ }\
444+ return ;\
445+ }\
446+ \
447+ /* YASL_Set sorting bounds */ \
448+ size_t left = 0 ;\
449+ size_t right = len - 1 ;\
450+ \
451+ /* Determine random midpoint to use (good average case) */ \
452+ const size_t randIndex = rand () % len ;\
453+ const struct YASL_Object mid = list [randIndex ];\
454+ \
455+ /* Determine exact number of items less than mid (mid's index)\
456+ Furthermore, ensure list is not homogeneous to avoid infinite loops */ \
457+ size_t ltCount = 0 ;\
458+ bool seenDifferent = false;\
459+ for (size_t i = 0 ; i < len ; i ++ ) {\
460+ if (COMP (list [i ], mid ) < 0 ) ltCount ++ ;\
461+ if (seenDifferent == 0 && COMP (list [0 ], list [i ]) != 0 ) seenDifferent = true;\
462+ }\
463+ if (!seenDifferent ) return ;\
464+ \
465+ /* Ensure all items are on the correct side of mid */ \
466+ while (left < right ) {\
467+ while (COMP (list [left ], mid ) < 0 ) left ++ ;\
468+ while (COMP (list [right ], mid ) >= 0 ) {\
469+ if (right == 0 ) break ;\
470+ right -- ;\
471+ }\
472+ \
473+ int cmp = COMP (list [left ], list [right ]);\
474+ if (cmp > 0 && left < right ) {\
475+ tmpObj = list [right ];\
476+ list [right ] = list [left ];\
477+ list [left ++ ] = tmpObj ;\
478+ if (right == 0 ) break ;\
479+ right -- ;\
480+ } else if (cmp == 0 ) {\
481+ left ++ ;\
482+ if (right == 0 ) break ;\
483+ right -- ;\
484+ }\
485+ }\
486+ \
487+ /* Let sort() finish that for us...*/ \
488+ name ##sort (S, list, ltCount);\
489+ name##sort(S, &list[ltCount], len - ltCount);\
457490}
458491
492+ DEF_SORT (default , yasl_object_cmp )
493+ // DEF_SORT(fn, CUSTOM_COMP)
494+
459495// TODO: clean this up
460496int list_sort (struct YASL_State * S ) {
461497 struct YASL_List * list = YASLX_checknlist (S , "list.sort" , 0 );
462- int type = SORT_TYPE_EMPTY ;
498+
499+ /*
500+ if (!YASL_isundef(S)) {
501+ fnsort(S, list->items, list->count);
502+ return 0;
503+ }
504+ */
505+
506+ if (YASL_List_length (list ) <= 1 ) {
507+ return 0 ;
508+ }
509+
510+ enum SortType type = SORT_TYPE_EMPTY ;
463511
464512 int err = 0 ;
465513 for (size_t i = 0 ; i < list -> count ; i ++ ) {
@@ -489,7 +537,7 @@ int list_sort(struct YASL_State *S) {
489537 }
490538
491539 if (type != SORT_TYPE_EMPTY ) {
492- sort ( list -> items , list -> count );
540+ defaultsort ( S , list -> items , list -> count );
493541 }
494542
495543 return 0 ;
0 commit comments