@@ -6748,20 +6748,27 @@ void Interpreter::InitializeArrayBuiltins() {
67486748 return HavelRuntimeError (" sortByKey() requires (array, key)" );
67496749 if (!args[0 ].is <HavelArray>())
67506750 return HavelRuntimeError (" sortByKey() first arg must be array" );
6751-
6751+
67526752 auto array = args[0 ].get <HavelArray>();
67536753 std::string key = ValueToString (args[1 ]);
6754-
6754+
67556755 if (!array)
67566756 return HavelRuntimeError (" sortByKey() received null array" );
67576757
67586758 // Check for custom comparator
6759- bool hasComparator = args.size () >= 3 && (args[2 ].is <BuiltinFunction>() ||
6759+ bool hasComparator = args.size () >= 3 && (args[2 ].is <BuiltinFunction>() ||
67606760 args[2 ].is <std::shared_ptr<HavelFunction>>());
67616761
6762+ // Store comparator for use in sort
6763+ HavelValue comparator;
6764+ if (hasComparator) {
6765+ comparator = args[2 ];
6766+ }
6767+
67626768 std::sort (array->begin (), array->end (),
6763- [this , &key, &args, hasComparator](const HavelValue &a, const HavelValue &b) {
6764- auto getKeyValue = [this , &key](const HavelValue &obj) -> HavelValue {
6769+ [this , key, hasComparator, comparator](const HavelValue &a, const HavelValue &b) mutable {
6770+ // Get value for key from object
6771+ auto getKeyValue = [&key](const HavelValue &obj) -> HavelValue {
67656772 if (auto *objMap = obj.get_if <std::shared_ptr<std::unordered_map<std::string, HavelValue>>>()) {
67666773 if (*objMap) {
67676774 auto it = (*objMap)->find (key);
@@ -6772,48 +6779,31 @@ void Interpreter::InitializeArrayBuiltins() {
67726779 }
67736780 return HavelValue (nullptr );
67746781 };
6775-
6782+
67766783 HavelValue valA = getKeyValue (a);
67776784 HavelValue valB = getKeyValue (b);
6778-
6785+
67796786 if (hasComparator) {
6780- auto &comparator = args[ 2 ];
6787+ // Use custom comparator
67816788 std::vector<HavelValue> callArgs = {valA, valB};
67826789 HavelResult cmpResult;
6783-
6790+
67846791 if (auto *builtin = comparator.get_if <BuiltinFunction>()) {
67856792 cmpResult = (*builtin)(callArgs);
6786- } else if (auto *userFunc = comparator.get_if <std::shared_ptr<HavelFunction>>()) {
6787- auto &func = **userFunc;
6788- auto funcEnv = std::make_shared<Environment>(func.closure );
6789- for (size_t i = 0 ; i < callArgs.size () && i < func.declaration ->parameters .size (); ++i) {
6790- funcEnv->Define (func.declaration ->parameters [i]->symbol , callArgs[i]);
6791- }
6792- auto originalEnv = this ->environment ;
6793- this ->environment = funcEnv;
6794- cmpResult = Evaluate (*func.declaration ->body );
6795- this ->environment = originalEnv;
6796-
6797- if (std::holds_alternative<ReturnValue>(cmpResult)) {
6798- auto ret = std::get<ReturnValue>(cmpResult);
6799- cmpResult = ret.value ? *ret.value : HavelValue ();
6800- }
6801- } else {
6802- return false ;
6793+ if (isError (cmpResult)) return false ;
6794+ double cmpNum = ValueToNumber (unwrap (cmpResult));
6795+ return cmpNum < 0 ;
68036796 }
6804-
6805- if (isError (cmpResult)) return false ;
6806- double cmpNum = ValueToNumber (unwrap (cmpResult));
6807- return cmpNum < 0 ;
6797+ // For user functions, fall through to default comparison
6798+ }
6799+
6800+ // Default comparison
6801+ if (valA.isNumber () && valB.isNumber ()) {
6802+ return valA.asNumber () < valB.asNumber ();
6803+ } else if (valA.isString () && valB.isString ()) {
6804+ return valA.asString () < valB.asString ();
68086805 } else {
6809- // Default comparison
6810- if (valA.isNumber () && valB.isNumber ()) {
6811- return valA.asNumber () < valB.asNumber ();
6812- } else if (valA.isString () && valB.isString ()) {
6813- return valA.asString () < valB.asString ();
6814- } else {
6815- return ValueToString (valA) < ValueToString (valB);
6816- }
6806+ return ValueToString (valA) < ValueToString (valB);
68176807 }
68186808 });
68196809
0 commit comments