Task

Select certain elements from an Array into a new Array in a generic way.



To demonstrate, select all even numbers from an Array.

As an option, give a second solution which filters destructively,
by modifying the original Array rather than creating a new Array.




DEFINE PTR="CARD"
 
INT value ;used in predicate
 
PROC PrintArray(INT ARRAY a BYTE size)
  BYTE i
 
  Put('[)
  FOR i=0 TO size-1
  DO
    PrintI(a(i))
    IF i<size-1 THEN
      Put(' )
    FI
  OD
  Put(']) PutE()
RETURN
 
;jump addr is stored in X and A registers
BYTE FUNC Predicate=*(PTR jumpAddr)
  DEFINE STX="$8E"
  DEFINE STA="$8D"
  DEFINE JSR="$20"
  DEFINE RTS="$60"
 [STX Predicate+8
  STA Predicate+7
  JSR $00 $00
  RTS]
 
PROC DoFilter(PTR predicateFun
  INT ARRAY src BYTE srcSize
  INT ARRAY dst BYTE POINTER dstSize)
 
  INT i
 
  dstSize^=0
  FOR i=0 TO srcSize-1
  DO
    value=src(i)
    IF Predicate(predicateFun) THEN
      dst(dstSize^)=value
      dstSize^==+1
    FI
  OD
RETURN
 
PROC DoFilterInplace(PTR predicateFun
  INT ARRAY data BYTE POINTER size)
 
  INT i,j
 
  i=0
  WHILE i<size^
  DO
    value=data(i)
    IF Predicate(predicateFun)=0 THEN
      FOR j=i TO size^-2
      DO
        data(j)=data(j+1)
      OD
      size^==-1
    ELSE
      i==+1
    FI
  OD
RETURN
 
BYTE FUNC Even()
  IF (value&1)=0 THEN
    RETURN (1)
  FI
RETURN (0)
 
BYTE FUNC NonNegative()
  IF value>=0 THEN
    RETURN (1)
  FI
RETURN (0)
 
PROC Main()
  INT ARRAY src=[65532 3 5 2 65529 1 0 65300 4123],dst(9)
  BYTE srcSize=[9],dstSize
 
  PrintE("Non destructive operations:") PutE()
  PrintE("Original array:")
  PrintArray(src,srcSize)
 
  DoFilter(Even,src,srcSize,dst,@dstSize)
  PrintE("Select all even numbers:")
  PrintArray(dst,dstSize)
 
  DoFilter(NonNegative,src,srcSize,dst,@dstSize)
  PrintE("Select all non negative numbers:")
  PrintArray(dst,dstSize)
 
  PutE()
  PrintE("Destructive operations:") PutE()
  PrintE("Original array:")
  PrintArray(src,srcSize)
 
  DoFilterInplace(Even,src,@srcSize)
  PrintE("Select all even numbers:")
  PrintArray(src,srcSize)
 
  DoFilterInplace(NonNegative,src,@srcSize)
  PrintE("Select all non negative numbers:")
  PrintArray(src,srcSize)
RETURN