Skip to content

Commit

Permalink
Merge pull request #18 from fakelag/array-find-slice
Browse files Browse the repository at this point in the history
Add slice + find array functions
  • Loading branch information
fakelag committed May 21, 2020
2 parents 43ea76b + 35ae250 commit b3288b0
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 0 deletions.
82 changes: 82 additions & 0 deletions Library/STL/Array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,94 @@ namespace ArrayModule
return args[ 0 ];
}

QScript::Value ArrayFind( void* frame, const QScript::Value* args, int argCount )
{
auto arr = args[ 0 ];

if ( !IS_ARRAY( arr ) )
{
throw RuntimeException( "rt_native_expected",
"Expected array object, got \"" + arr.ToString() + "\"", 0, 0, "" );
}

if ( argCount != 2 )
{
throw RuntimeException( "rt_native_argcount",
"Expected 1 arguments, got " + std::to_string( argCount - 1 ), 0, 0, "" );
}

auto findFn = args[ 1 ];
auto& arrayRef = AS_ARRAY( arr )->GetArray();

auto element = std::find_if( arrayRef.begin(), arrayRef.end(), [ &findFn, frame ]( QScript::Value value ) {
QVM::VirtualMachine->Push( findFn );
QVM::VirtualMachine->Push( value );

QVM::VirtualMachine->Call( ( Frame_t* ) frame, 1, findFn, true );
QVM::Run( *QVM::VirtualMachine, false );

return !QVM::VirtualMachine->Pop().IsTruthy();
} );

if ( element == arrayRef.end() )
return MAKE_NULL;

return *element;
}

QScript::Value ArraySlice( void* frame, const QScript::Value* args, int argCount )
{
auto arr = args[ 0 ];

if ( !IS_ARRAY( arr ) )
{
throw RuntimeException( "rt_native_expected",
"Expected array object, got \"" + arr.ToString() + "\"", 0, 0, "" );
}

if ( argCount < 2 )
{
throw RuntimeException( "rt_native_argcount",
"Expected >= 1 arguments, got " + std::to_string( argCount - 1 ), 0, 0, "" );
}

if ( !IS_NUMBER( args[ 1 ] ) || ( argCount > 2 && !IS_NUMBER( args[ 2 ] ) ) )
{
throw RuntimeException( "rt_native_expected",
"Both arguments of slice must be numbers, got \""
+ args[ 1 ].ToString() + ( argCount > 2 ? "\", \"" + args[ 2 ].ToString() + "\"" : "\"" ), 0, 0, "" );
}

auto newArray = MAKE_ARRAY( "" );
auto& arrayRef = AS_ARRAY( arr )->GetArray();

int startSlice = std::max( 0, ( int ) AS_NUMBER( args[ 1 ] ) );

if ( startSlice >= ( int ) arrayRef.size() )
return newArray;

int endSlice = ( int ) arrayRef.size();

if ( argCount > 2 )
{
endSlice = std::min( ( int ) arrayRef.size(), std::max( 0, ( int ) AS_NUMBER( args[ 2 ] ) ) );

if ( endSlice < startSlice )
return newArray;
}

AS_ARRAY( newArray )->GetArray() = std::vector< QScript::Value >( arrayRef.begin() + startSlice, arrayRef.begin() + endSlice );
return newArray;
}

void LoadMethods( VM_t* vm )
{
vm->CreateArrayMethod( "push", ArrayPush );
vm->CreateArrayMethod( "concat", ArrayConcat );
vm->CreateArrayMethod( "length", ArrayLength );
vm->CreateArrayMethod( "pop", ArrayPop );
vm->CreateArrayMethod( "filter", ArrayFilter );
vm->CreateArrayMethod( "find", ArrayFind );
vm->CreateArrayMethod( "slice", ArraySlice );
}
}
63 changes: 63 additions & 0 deletions Tests/TestInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,69 @@ bool Tests::TestInterpreter()
UTEST_CASE_CLOSED();
}( );

UTEST_CASE( "Arrays (STL Slice)" )
{
QScript::Value exitCode;
UTEST_ASSERT( TestUtils::RunVM( "var g0; \
{ \
Array a ={ 1, 2, 3, 4, 5, 6, 7 }; \
g0 =[ [ a.slice 0 ].concat \
[ a.slice 2, 4 ], \
[ a.slice 5 ], \
[ a.slice 6, 123123 ], \
[ a.slice 6, 0 ], \
[ a.slice 1231 ] \
]; \
} \
return g0;", &exitCode ) );

UTEST_ASSERT( IS_ARRAY( exitCode ) );

auto arr = AS_ARRAY( exitCode )->GetArray();
UTEST_ASSERT( arr.size() == 12 );
UTEST_ASSERT( IS_NUMBER( arr[ 0 ] ) && AS_NUMBER( arr[ 0 ] ) == 1.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 1 ] ) && AS_NUMBER( arr[ 1 ] ) == 2.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 2 ] ) && AS_NUMBER( arr[ 2 ] ) == 3.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 3 ] ) && AS_NUMBER( arr[ 3 ] ) == 4.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 4 ] ) && AS_NUMBER( arr[ 4 ] ) == 5.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 5 ] ) && AS_NUMBER( arr[ 5 ] ) == 6.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 6 ] ) && AS_NUMBER( arr[ 6 ] ) == 7.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 7 ] ) && AS_NUMBER( arr[ 7 ] ) == 3.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 8 ] ) && AS_NUMBER( arr[ 8 ] ) == 4.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 9 ] ) && AS_NUMBER( arr[ 9 ] ) == 6.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 10 ] ) && AS_NUMBER( arr[ 10 ] ) == 7.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 11 ] ) && AS_NUMBER( arr[ 11 ] ) == 7.00 );

TestUtils::FreeExitCode( exitCode );
UTEST_CASE_CLOSED();
}( );

UTEST_CASE( "Arrays (STL Find)" )
{
QScript::Value exitCode;
UTEST_ASSERT( TestUtils::RunVM( "var g0; \
{ \
Array a ={ 1, 2, 3, 4, 5, 6, 7 }; \
const filterFn = ( item ) -> { \
return item >= 4; \
}; \
g0 =[ a.filter filterFn ]; \
} \
return g0; ", &exitCode ) );

UTEST_ASSERT( IS_ARRAY( exitCode ) );

auto arr = AS_ARRAY( exitCode )->GetArray();
UTEST_ASSERT( arr.size() == 4 );
UTEST_ASSERT( IS_NUMBER( arr[ 0 ] ) && AS_NUMBER( arr[ 0 ] ) == 4.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 1 ] ) && AS_NUMBER( arr[ 1 ] ) == 5.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 2 ] ) && AS_NUMBER( arr[ 2 ] ) == 6.00 );
UTEST_ASSERT( IS_NUMBER( arr[ 3 ] ) && AS_NUMBER( arr[ 3 ] ) == 7.00 );

TestUtils::FreeExitCode( exitCode );
UTEST_CASE_CLOSED();
}( );

UTEST_CASE( "Mixing arrays and tables (1)" )
{
QScript::Value exitCode;
Expand Down

0 comments on commit b3288b0

Please sign in to comment.