/* Copyright (C) 2003-2013 Runtime Revolution Ltd.
 
 This file is part of LiveCode.
 
 LiveCode is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License v3 as published by the Free
 Software Foundation.
 
 LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 along with LiveCode.  If not see <http://www.gnu.org/licenses/>.  */

/*  
This library consists of the operations on lists included in the standard library of LiveCode Builder.
*/

module com.livecode.list

use com.livecode.foreign

public foreign handler MCListEvalHeadOf(in Target as List, out Value as optional any) returns nothing binds to "<builtin>"
public foreign handler MCListEvalTailOf(in Target as List, out Value as optional any) returns nothing binds to "<builtin>"

public foreign handler MCListExecPushSingleElementOnto(in Value as optional any, in IsFront as CBool, inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListExecPopElement(in IsFront as CBool, inout Source as List) returns optional any binds to "<builtin>"

public foreign handler MCListEvalNumberOfElementsIn(in Target as List, out Count as LCUIndex) returns nothing binds to "<builtin>"

public foreign handler MCListEvalIsAmongTheElementsOf(in Needle as optional any, in Target as List, out Result as CBool) returns nothing binds to "<builtin>"
public foreign handler MCListEvalContainsElements(in Target as List, in Needle as List, out Result as CBool) returns nothing binds to "<builtin>"

public foreign handler MCListEvalBeginsWith(in Source as List, in Prefix as List, out Result as CBool) returns nothing binds to "<builtin>"
public foreign handler MCListEvalEndsWith(in Source as List, in Suffix as List, out Result as CBool) returns nothing binds to "<builtin>"

public foreign handler MCListEvalIsEqualTo(in Left as List, in Right as List, out Value as CBool) returns nothing binds to "<builtin>"
public foreign handler MCListEvalIsNotEqualTo(in Left as List, in Right as List, out Value as CBool) returns nothing binds to "<builtin>"

public foreign handler MCListFetchElementOf(in Index as LCIndex, in Target as List, out Value as any) returns nothing binds to "<builtin>"
public foreign handler MCListStoreElementOf(in Value as any, in Index as LCIndex, inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListFetchElementRangeOf(in Start as LCIndex, in Finish as LCIndex, in Target as List, out Value as List) returns nothing binds to "<builtin>"
public foreign handler MCListStoreElementRangeOf(in Value as optional any, in Start as LCIndex, in Finish as LCIndex, inout Target as List) returns nothing binds to "<builtin>"

public foreign handler MCListFetchIndexOf(in Target as List, in Index as LCIndex, out Value as optional any) returns nothing binds to "<builtin>"
public foreign handler MCListStoreIndexOf(in Value as optional any, inout Target as List, in Index as LCIndex) returns nothing binds to "<builtin>"

public foreign handler MCListStoreBeforeElementOf(in Value as optional any, in Index as LCIndex, inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListStoreAfterElementOf(in Value as optional any, in Index as LCIndex, inout Target as List) returns nothing binds to "<builtin>"

public foreign handler MCListSpliceIntoElementRangeOf(in Source as List, in Start as LCIndex, in Finish as LCIndex, inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListSpliceIntoElementOf(in Source as List, in Index as LCIndex, inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListSpliceBeforeElementOf(in Source as List, in Index as LCIndex, inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListSpliceAfterElementOf(in Source as List, in Index as LCIndex, inout Target as List) returns nothing binds to "<builtin>"

public foreign handler MCListSpliceBefore(in Source as List, inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListSpliceAfter(in Source as List, inout Target as List) returns nothing binds to "<builtin>"

public foreign handler MCListEvalEmpty(out Value as List) returns nothing binds to "<builtin>"

public foreign handler MCListRepeatForEachElement(inout Iterator as optional Pointer, out Iterand as optional any, in Container as List) returns CBool binds to "<builtin>"

public foreign handler MCListFetchFirstElementOf(in Target as List, out Value as optional any) returns nothing binds to "<builtin>"
public foreign handler MCListStoreFirstElementOf(in Value as optional any, inout Target as List) returns nothing binds to "<builtin>"

public foreign handler MCListFetchLastElementOf(in Target as List, out Value as optional any) returns nothing binds to "<builtin>"
public foreign handler MCListStoreLastElementOf(in Value as optional any, inout Target as List) returns nothing binds to "<builtin>"

public foreign handler MCListExecDeleteElementOf(in Index as LCIndex, inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListExecDeleteElementRangeOf(in Start as LCIndex, in Finish as LCIndex, inout Target as List) returns nothing binds to "<builtin>"

public foreign handler MCListExecDeleteFirstElementOf(inout Target as List) returns nothing binds to "<builtin>"
public foreign handler MCListExecDeleteLastElementOf(inout Target as List) returns nothing binds to "<builtin>"

public foreign handler MCListEvalIndexOfElement(in IsLast as CBool, in Needle as any, in Haystack as List, out Index as LCUIndex) returns nothing binds to "<builtin>"
public foreign handler MCListEvalIndexOfElementAfter(in IsLast as CBool, in Needle as any, in After as LCIndex, in Haystack as List, out Index as LCUIndex) returns nothing binds to "<builtin>"
public foreign handler MCListEvalIndexOfElementBefore(in IsFirst as CBool, in Needle as any, in Before as LCIndex, in Haystack as List, out Index as LCUIndex) returns nothing binds to "<builtin>"

public foreign handler MCListEvalOffsetOfList(in IsLast as CBool, in Needle as List, in Haystack as List, out Index as LCUIndex) returns nothing binds to "<builtin>"
public foreign handler MCListEvalOffsetOfListAfter(in IsLast as CBool, in Needle as List, in After as LCIndex, in Haystack as List, out Index as LCUIndex) returns nothing binds to "<builtin>"
public foreign handler MCListEvalOffsetOfListBefore(in IsFirst as CBool, in Needle as List, in Before as LCIndex, in Haystack as List, out Index as LCUIndex) returns nothing binds to "<builtin>"

--

/*
Summary:        Returns the first element of <Target>.
Target:         An expression which evaluates to a list.

Returns:			The first element of <Target>

Example:
	variable tVar as List
	put the empty list into tVar
	push "first element" onto tVar
	
	variable tResult as Boolean
	if the head of tVar is "first element" then
		put "success" into tResult
	end if
	
Description:
Returns the first element of the list <Target> without modifying <Target>.
```	the head of tVar```
is equivalent to using the <IndexedElementOfList> operator with index 1
```	tVar[1]```
	
References: IndexedElementOfList(operator)

Tags: Lists
*/

syntax HeadOfList is prefix operator with precedence 1
    "the" "head" "of" <Target: Expression>
begin
    MCListEvalHeadOf(Target, output)
end syntax

/* 
Summary:        Returns the last element of <Target>.
Target:         An expression which evaluates to a list.

Returns:			The last element of <Target>

Example:
	variable tVar as List
	put the empty list into tVar
	push "first element" onto tVar
	push "last element" onto tVar
	
	variable tResult as String
	if the tail of tVar is "last element" then
		put "success" into tResult
	end if
	
Description:
Returns the first element of the list <Target> without modifying <Target>.
```	the tail of tVar```
is equivalent to using the <IndexedElementOfList> operator with index -1
```	tVar[-1]```

References: IndexedElementOfList(operator)

Tags: Lists
*/

syntax TailOfList is prefix operator with precedence 1
    "the" "tail" "of" <Target: Expression>
begin
    MCListEvalTailOf(Target, output)
end syntax

--

/* 
Summary:        Pushes <Value> onto <Target>.
Value:          Any expression.
Target:         An expression which evaluates to a list.

Example:
	variable tVar as List
	put the empty list into tVar
	push "something" onto tVar
	push "something else" onto front of tVar
	
	variable tResult as String
	if tVar[1] is "something else" then
		put "success" into tResult
	end if

Description:
When <Value> is pushed onto <Target>, <Value> (by default) becomes the tail of the list, with an index one greater than the previous tail.
Use the 'front of' variant to push onto the front of a list instead.

Tags: Lists
*/

syntax PushOntoList is statement
    "push" <Value: Expression> "onto" ( "front" "of" <IsFront=true> | "back" "of" <IsFront=false> | <IsFront=false> ) <Target:Expression>
begin
    MCListExecPushSingleElementOnto(Value, IsFront, Target)
end syntax

/* 
Summary:        Pops the last element from <Source> into <Target>
Source:         An expression which evaluates to a list.
Target:         An expression which evaluates to a container.

Example:
	variable tVar as List
	put the empty list into tVar
	push "something" onto tVar
	push "something else" onto tVar
	
	variable tPopped as String
	pop tVar into tPopped -- tPopped contains "something else"
	
Example:
	variable tList as List
	put [1,2,3] into tList
	variable tNum as Number
	pop front of tList into tNum -- tNum is 1, tList is [2,3]

Description:
When <Source> is popped into <Target>, the last element of the list <Source> is removed and put into the container <Target>.
Use the 'front of' variant to pop from the front of a list instead.

Tags: Lists
*/

syntax PopList is statement
    "pop" ( "front" "of" <IsFront=true> | "back" "of" <IsFront=false> | <IsFront=false> ) <Source: Expression>
begin
    MCListExecPopElement(IsFront, Source)
end syntax

--

/*
Summary:        Returns the number of elements in <Target>
Target:         An expression which evaluates to a list.

Returns:			The number of elements in the list <Target>.

Example:
	variable tVar as List
	put [1,2,3,4,5] into tVar
	variable tNum as Number
	put the number of elements in tVar into tNum -- tNum is 5
	
Description:
Returns the number of elements in the list.

Tags: Lists
*/

syntax CountElementsOfList is prefix operator with precedence 1
    "the" "number" "of" "elements" "in" <Target: Expression>
begin
    MCListEvalNumberOfElementsIn(Target, output)
end syntax

--

/* 
Summary:        Determines if a given element is in <Target>
Needle:         Any expression.
Target:         An expression which evaluates to a list.

Returns: 	Returns true if <Needle> can be found among the elements of <Target>.

Example:
	variable tList as List
	put [ "a", "b", "c", "d" ] into tList
	
	variable tIsIn as Boolean
	put "a" is in tList into tIsIn -- tIsIn contains true

Description:
<Needle> must be an element of <Target> rather than a sublist, or contained within a list element of <Target>.

Tags: Lists
*/
                
syntax ElementIsInList is neutral binary operator with precedence 1
    <Needle: Expression> "is" "in" <Target: Expression>
begin
    MCListEvalIsAmongTheElementsOf(Needle, Target, output)
end syntax

/* 
Summary:        Determines if <Target> contains <Needle> as a subsequence.
Needle:         Any expression which evaluates to a list.
Target:         An expression which evaluates to a list.

Returns: 	Returns true if <Target> contains <Needle>.

Example:
	variable tList as List
	put [ "a", "b", "c", "d" ] into tList
	
	variable tContains as Boolean
	
	// put tList contains tList[1] into tContains -- error: tList[1] is not a list 
	
	put tList contains element 1 to 2 of tList into tContains -- tContains is true

Description:
<Target> contains <Needle> if and only if the elements of <Needle> occur as a subsequence of the elements of <Target>.

>*Note:* Since "" is a subsequence of elements of every list, every list contains the empty list.

Tags: Lists
*/
                
syntax ListContainsElements is neutral binary operator with precedence 1
    <Target: Expression> "contains" <Needle: Expression>
begin
    MCListEvalContainsElements(Target, Needle, output)
end syntax

--

/*
Summary:            Determines whether <Source> begins with <Prefix>
Prefix: 			An expression which evaluates to a list.
Source: 			An expression which evaluates to a list.

Returns: 	 Returns true if <Source> begins with <Prefix>.

Example:
	variable tVar as List
	put [1, 2, 3, 4, 5] into tVar
	
	variable tBegins as Boolean
	// put tList begins with tList[1] into tBegins -- error: tList[1] is not a list 
	
	put tList begins with [1, 2] into tBegins -- tBegins is true

Description:
<Source> begins with <Prefix> if and only if the elements of <Prefix> occur as an initial subsequence of the elements of <Source>.

>*Note:* Since the empty list is an initial subsequence of every list, every list begins with the empty list.

Tags: Lists
*/

syntax ListBeginsWithList is neutral binary operator with precedence 1
    <Source: Expression> "begins" "with" <Prefix: Expression>
begin
    MCListEvalBeginsWith(Source, Prefix, output)
end syntax

/*
Summary:            Determines whether <Source> ends with <Suffix>
Prefix: 			An expression which evaluates to a list.
Source: 			An expression which evaluates to a list.

Returns: 	Returns true if <Source> ends with <Suffix>.

Example:
	variable tVar as List
	put [1, 2, 3, 4, 5] into tVar
	
	variable tEnds as Boolean
	// put tList ends with tList[5] into tEnds -- error: tList[5] is not a list 
	
	put tList ends with element 1 to 5 of tList into tEnds -- tEnds is true

Description:
<Source> ends with <Suffix> if and only if the elements of <Suffix> occur as a final subsequence of the elements of <Source>.

>*Note:* Since the empty list is a final subsequence of every list, every list ends with the empty list.

Tags: Lists
*/

syntax ListEndsWithList is neutral binary operator with precedence 1
    <Source: Expression> "ends" "with" <Suffix: Expression>
begin
    MCListEvalEndsWith(Source, Suffix, output)
end syntax

--

/*
Summary:    Determines whether <Left> and <Right> are equal or not.

Left:       An expression which evaluates to a list.
Right:      An expression which evaluates to a list.


Returns: 	Returns true if <Left> is identical to <Right>.

Example:
	variable tList as List
	put ["a", "b", "c"] into tList
	variable tIs as Boolean
	
	put tList is ["A", "b", "c"] into tIs -- tIs is false
	put tList is element 1 to -1 of tList into tIs -- tIs is true
	
Description:
Two lists are equal if each corresponding element is of comparable type, and if the default equality of that type holds between the elements.
In particular, this means that comparison between string elements is case sensitive.

Tags: Lists
*/

syntax ListIsList is neutral binary operator with precedence 7
    <Left: Expression> "is" <Right: Expression>
begin
    MCListEvalIsEqualTo(Left, Right, output)
end syntax

/*
Summary:    Determines whether <Left> and <Right> are equal or not.

Left:       An expression which evaluates to a list.
Right:      An expression which evaluates to a list.


Returns: 	Returns true if <Left> is not identical to <Right>.

Example:
	variable tList as List
	put ["a", "b", "c"] into tList
	variable tIsNot as Boolean
	
	put tList is not ["A", "b", "c"] into tIsNot -- tIs is true
	
Description:
Two lists are not equal if any corresponding elements are of non-comparable types, or if the default equality of that type does not holds between the elements.
In particular, this means that comparison between string elements is case sensitive.

Tags: Lists
*/

syntax ListIsNotList is neutral binary operator with precedence 7
    <Left: Expression> "is not" <Right: Expression>
begin
    MCListEvalIsNotEqualTo(Left, Right, output)
end syntax

--

/*

Summary:            Designates the element at index <Index> in <Target>.
Index: 				An expression which evaluates to a valid integer index of <Target>.
Target:				An expression which evaluates to a list.

Example:
	variable tVar as List
	put [1,2,3] into tVar
	put "A" into element 1 of tVar -- tVar is ["A",2,3]
	
	variable tNum as Number
	put element 2 of tVar into tNum -- tNum is 2

Description:     
Either locates the element container at the given index for use as the target container of another operation, or evaluates the element at the given index as the source of another operation.
                                        
>*Note:* It is an error if <Index> is out of range.

Tags: Lists
*/

syntax SingletonElementOfList is prefix operator with precedence 1
	"element" <Index: Expression> "of" <Target: Expression>
begin
    MCListFetchElementOf(Index, Target, output)
    MCListStoreElementOf(input, Index, Target)
end syntax

/*

Summary:            Designates the element at index <Index> in <Target>.
Synonym:            SingletonElementOf
Index: 				An expression which evaluates to a valid integer index of <Target>.
Target:				An expression which evaluates to a list.

Example:
	variable tVar as List
	put [1,2,3] into tVar
	put "A" into tVar[1] -- tVar is ["A",2,3]
	
	variable tNum as Number
	put tVar[2] into tNum -- tNum is 2

Description:     
Either locates the element container at the given index for use as the target container of another operation, or evaluates the element at the given index as the source of another operation.
                                        
>*Note:* It is an error if <Index> is out of range.

Tags: Lists
*/

syntax IndexedElementOfList is postfix operator with precedence 1
    <Target: Expression> "[" <Index: Expression> "]"
begin
    MCListFetchIndexOf(Target, Index, output)
    MCListStoreIndexOf(input, Target, Index)
end syntax

/*

Summary:            Designates the elements between indices <Start> and <Finish> in <Target>.

Start:              An expression which evaluates to a valid integer index of <Target>.
Finish:             An expression which evaluates to a valid integer index of <Target>.
Target:             An expression which evaluates to a list.

Example:
	variable tList as List
	put [1,2,3] into tList
	
	put tList into element 1 to 2 of tList -- tList is [[1,2,3],3]
	
Description:     
Either locates the element containers between the given indices for use as a list container for the target of another operation, or evaluates the elements between the given indices as a list.
                                        
>*Note:* It is an error if either <Start> or <Finish> are out of range.

>*Note:* If a list is the source of ``put tList into element 1 to 3 of tOtherList```, then tList is *not* inserted element-wise. The entire list is inserted as an element, so that element 1 of tOtherList is tList.

Tags: Lists
*/

syntax RangeElementsOfList is prefix operator with precedence 1
	"element" <Start: Expression> "to" <Finish: Expression> "of" <Target: Expression>
begin
    MCListFetchElementRangeOf(Start, Finish, Target, output)
    MCListStoreElementRangeOf(input, Start, Finish, Target)
end syntax

/*

Summary:            Designates the first element in <Target>.
Target:				An expression which evaluates to a list.

Description:
Either locates the first element for use as the target container of another operation, or evaluates the first element as the source of another operation.

>*Note:* It is an error if <Target> is empty.

Tags: Lists
*/

syntax FirstElementOf is prefix operator with precedence 1
	"the" "first" "element" "of" <Target: Expression>
begin
	MCListFetchFirstElementOf(Target, output)
	MCListStoreFirstElementOf(input, Target)
end syntax

/*

Summary:            Designates the last element in <Target>.
Target:				An expression which evaluates to a list.

Description:
Either locates the first element for use as the target container of another operation, or evaluates the first element as the source of another operation.

>*Note:* It is an error if <Target> is empty.

Tags: Lists
*/

syntax LastElementOf is prefix operator with precedence 1
	"the" "last" "element" "of" <Target: Expression>
begin
	MCListFetchLastElementOf(Target, output)
	MCListStoreLastElementOf(input, Target)
end syntax

--

/*

Summary:            Deletes the element at index <Index> in <Target>.
Index: 				An expression which evaluates to a valid integer index of <Target>.
Target:				A list container.

Description:
Removes the element at the given index from the list.

>*Note:* It is an error if either <Index> is out of range.

Tags: Lists
*/

syntax DeleteSingletonElementOf is statement
	"delete" "element" <Index: Expression> "of" <Target: Expression>
begin
	MCListExecDeleteElementOf(Index, Target)
end syntax

/*

Summary:            Deletes the elements between indices <Start> and <Finish> in <Target>.

Start:              An expression which evaluates to a valid integer index of <Target>.
Finish:             An expression which evaluates to a valid integer index of <Target>.
Target:             A list container.

Description:
Removes the elements between the given indices from the list.

>*Note:* It is an error if either <Start> or <Finish> are out of range.

Tags: Lists
*/

syntax DeleteRangeElementOf is statement
	"delete" "element" <Start: Expression> "to" <Finish: Expression> "of" <Target: Expression>
begin
	MCListExecDeleteElementRangeOf(Start, Finish, Target)
end syntax

/*

Summary:            Deletes the first element of <Target>.
Target:				A list container.

Description:
Removes the first element of <Target>.

>*Note:* It is an error if <Target> is the empty list.

Tags: Lists
*/

syntax DeleteFirstElementOf is statement
	"delete" "the" "first" "element" "of" <Target: Expression>
begin
	MCListExecDeleteFirstElementOf(Target)
end syntax


/*

Summary:            Deletes the last element of <Target>.
Target:				A list container.

Description:
Removes the last element of <Target>.

>*Note:* It is an error if <Target> is the empty list.

Tags: Lists
*/

syntax DeleteLastElementOf is statement
	"delete" "the" "last" "element" "of" <Target: Expression>
begin
	MCListExecDeleteLastElementOf(Target)
end syntax

--

/*

Summary:            Removes the elements of <Target> from <Start > to <Finish> and inserts each of the elements of
                    <Source> into <Target> at <Start>.
Source:             An expression which evaluates to a list.
Start:              An expression which evaluates to a valid integer index of <Target>.
Finish:             An expression which evaluates to a valid integer index of <Target>.
Target:             An expression which evaluates to a list.

Example:
	variable tVar as List
	put the empty list into tVar
	
	variable tCount as Number
	put 1 into tCount
	repeat 3 times
		push tCount onto tVar
	end repeat
	
	variable tVar2 as List
	push "these" onto tVar2
	push "are" onto tVar2
	push "unwanted" onto tVar2
	push 4 onto tVar2
	
	splice tVar into element 1 to 3 of tVar2 -- tVar2 contains the list [1,2,3,4]
	

Description:
Use the splice syntax to insert the elements of one list into another list. 

>*Note:* ```put tList into element 1 to 3 of tList2``` results in the removal of elements 1 to 3 of tList2 and the insertion of tList **as an element**, i.e. tList2 becomes the list [tList,element 4 of tList2, element 5 of tList2 ...]

>*Note:* It is an error if either <Start> or <Finish> is out of range.

Tags: Lists
*/

syntax SpliceIntoRangeOfList is statement
    "splice" <Source: Expression> "into" "element" <Start: Expression> "to" <Finish: Expression> "of" <Target: Expression>
begin
    MCListSpliceIntoElementRangeOf(Source, Start, Finish, Target)
end syntax

/*

Summary:            Removes the element of <Target> at <Index> and inserts each of the elements of <Source> into
                    <Target> at <Index>.
Source:             An expression which evaluates to a list.
Index:              An expression which evaluates to a valid integer index of <Target>.
Target:             An expression which evaluates to a list.

Example:
	variable tVar as List
	put the empty list into tVar
	
	variable tCount as Number
	put 1 into tCount
	repeat 3 times
		push tCount onto tVar
	end repeat
	
	variable tVar2 as List
	push "this is unwanted" onto tVar2
	push 4 onto tVar2
	
	splice tVar into element 1 of tVar2 -- tVar2 contains the list [1,2,3,4]
	

Description:
Use the splice syntax to insert the elements of one list into another list. 

>*Note:* ```put tList into element 1 of tList2``` results in the removal of element 1 of tList2 and the insertion of tList **as an element**, i.e. tList2 becomes the list [tList,element 2 of tList2, element 3 of tList2 ...]

>*Note:* It is an error if <Index> is out of range.

Tags: Lists
*/

syntax SpliceIntoElementOfList is statement
    "splice" <Source: Expression> "into" "element" <Index: Expression> "of" <Target: Expression>
begin
    MCListSpliceIntoElementOf(Source, Index, Target)
end syntax

/*

Summary:            Inserts each of the elements of <Source> into <Target> before element at index <Index>.
Source:             An expression which evaluates to a list.
Index:              An expression which evaluates to a valid integer index of <Target>.
Target:             An expression which evaluates to a list.

Example:
	variable tVar as List
	put the empty list into tVar
	
	variable tCount as Number
	put 2 into tCount
	repeat 3 times
		push tCount onto tVar
	end repeat
	
	variable tVar2 as List
	push 1 onto tVar2
	push 5 onto tVar2
	
	splice tVar before element 2 of tVar2 -- tVar2 contains the list [1,2,3,4,5]
	

Description:
Use the splice syntax to insert the elements of one list into another list. 

>*Note:* ```put tList before element 2 of tList2``` results in the insertion of tList **as an element**, i.e. tList2 becomes the list [element 1 of tList2,tList,element 2 of tList2, element 3 of tList2 ...]

>*Note:* It is an error if <Index> is out of range.

Tags: Lists
*/

syntax SpliceBeforeElementOfList is statement
    "splice" <Source: Expression> "before" "element" <Index: Expression> "of" <Target: Expression>
begin	
	//MCListSpliceBefore(Source, Target)
    MCListSpliceBeforeElementOf(Source, Index, Target)
end syntax

/*

Summary:            Inserts each of the elements of <Source> into <Target> after element at index <Index>.
Source:             An expression which evaluates to a list.
Index:              An expression which evaluates to a valid integer index of <Target>.
Target:             An expression which evaluates to a list.

Example:
	variable tVar as List
	put the empty list into tVar
	
	variable tCount as Number
	put 2 into tCount
	repeat 3 times
		push tCount onto tVar
	end repeat
	
	variable tVar2 as List
	push 1 onto tVar2
	push 5 onto tVar2
	
	splice tVar after element 1 of tVar2 -- tVar2 contains the list [1,2,3,4,5]
	

Description:
Use the splice syntax to insert the elements of one list into another list. 

>*Note:* ```put tList after element 1 of tList2``` results in the insertion of tList **as an element**, i.e. tList2 becomes the list [element 1 of tList2,tList,element 2 of tList2, element 3 of tList2 ...]

>*Note:* It is an error if <Index> is out of range.

Tags: Lists
*/

syntax SpliceAfterElementOfList is statement
    "splice" <Source: Expression> "after" "element" <Index: Expression> "of" <Target: Expression>
begin
	//MCListSpliceAfter(Source, Target)
    MCListSpliceAfterElementOf(Source, Index, Target)
end syntax

--

/* 

Summary: 		Designates the list of length zero.

Example:
	variable tVar as List
	variable tCount as Number
	put the empty list into tVar
	put the number of elements in tVar into tCount -- tCount is 0
	
Description:
Use ```the empty list``` to initialise a list variable.

Tags: Lists

*/

syntax EmptyList is expression
	"the" "empty" "list"
begin
	MCListEvalEmpty(output)
end syntax

/*
Summary:        Repeat over the elements of a list
Iterand:        Any variable of appropriate type.

Example:
    variable tList as List
    put [1, 1, 2, 3, 5, 8, 13] into tList

    variable tRelist as List
    variable tElement as any
    put the empty list into tRelist

    repeat for each element tElement in tList
        push tElement onto tRelist
    end repeat

    // tRelist is the same as tList

Description:
Use repeat for each to perform an operation on each element of a list. On each iteration, the Iterand will contain the next element of the list being iterated over.
>*Note:* If <Iterand> is typed, then an error will be thrown if the list being iterated over contains any elements of a different type.

Tags: Lists, Control structures
*/

syntax RepeatForEachElementInList is iterator
    "element" <Iterand: Expression>
begin
    MCListRepeatForEachElement(iterator, Iterand, container)
end syntax

----------------------------------------------------------------

/*
Summary:	Find the first or last occurrence of <Needle> within <Haystack>

Needle:	An expression which evaluates to any value.
Target:	An expression which evaluates to a list.

Returns:	Returns the index from the start of <Haystack>.

Example:
	variable tVar as List
	variable tOffset as Number
	put ["a", "b", "c", "d", "b"]
	put the index of "b" in tVar into tOffset
	-- tOffset contains 2

	put the last index of "b" in tVar into tOffset
	-- tOffset contains 5

Description:
Use `the index of` to find where particular elements occur within a
list.  <Haystack> is scanned for an element that is equal to <Needle>,
and the position of the element found is returned.  If neither the
"first index" nor "last index" are specified, the index of the first
element found is returned.  If no element of <Haystack> is equal to
<Needle>, the return value is 0.

Tags: Lists
*/
syntax ListIndex is prefix operator with precedence 1
	"the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "index" "of" <Needle: Expression> "in" <Haystack: Expression>
begin
	MCListEvalIndexOfElement(IsLast, Needle, Haystack, output)
end syntax

/*
Summary:	Find the first or last occurrence of <Needle> within the tail of <Haystack>

Needle:	An expression which evaluates to any value.
After:		An expression which evaluates to a valid index in Target.
Target:	An expression which evaluates to a list.

Returns:	Returns the index in <Haystack> relative to <After>.

Example:
	variable tVar as List
	variable tOffset as Number
	put ["a", "b", "c", "d", "b"]
	put the index of "b" after 1 in tVar into tOffset
	--tOffset contains 2

	put the last index of "b" after 2 in tVar into tOffset
	--tOffset contains 5

Description:
Use `the index of… after` to find where particular elements occur
within a list.  Starting from but not including the position <After>,
<Haystack> is scanned for an element that is equal to <Needle>, and
the position of the element found is returned.  If no element of
<Haystack> is equal to <Needle>, the return value is 0.

Tags: Lists
*/
syntax ListIndexAfter is prefix operator with precedence 1
	"the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "index" "of" <Needle: Expression> "after" <After: Expression> "in" <Haystack: Expression>
begin
	MCListEvalIndexOfElementAfter(IsLast, Needle, After, Haystack, output)
end syntax

/*
Summary:	Find the first or last occurrence of <Needle> within the head of <Haystack>

Needle:	An expression which evaluates to any value.
Before:	An expression which evaluates to a valid index in Target.
Target:	An expression which evaluates to a list.

Returns:	Returns the index in <Haystack>.

Example:
	variable tVar as List
	variable tOffset as Number
	put ["a", "b", "c", "d", "b"]
	put the index of "b" before 2 in tVar into tOffset
	--tOffset contains 0

	put the first index of "b" before 5 in tVar into tOffset
	--tOffset contains 2

Description:
Use `the index of… before` to find where particular elements occur
within a list.  <Haystack> is scanned for an element that is equal to
<Needle>, stopping before the position <Before>, and the position of
the element found is returned.  If no element of <Haystack> is equal
to <Needle>, the return value is 0.  If neither "first" nor "last" is
specified, the last matching element is found.

Tags: Lists
*/
syntax ListIndexBefore is prefix operator with precedence 1
	"the" ( "first" <IsFirst=true> | "last" <IsFirst=false> | <IsFirst=false> ) "index" "of" <Needle: Expression> "before" <Before: Expression> "in" <Haystack: Expression>
begin
	MCListEvalIndexOfElementBefore(IsFirst, Needle, Before, Haystack, output)
end syntax

----------------------------------------------------------------

/*
Summary:	Find the first or last occurrence of <Needle> within <Haystack>

Needle:	An expression which evaluates to a list.
Target:	An expression which evaluates to a list.

Returns:	Returns the index from the start of <Haystack>.

Example:
	variable tVar as List
	variable tOffset as Number
	put ["a", "b", "c", "d", "b", "c"]
	put the offset of ["b","c"] in tVar into tOffset
	-- tOffset contains 2

	put the last offset of ["b", "c"] in tVar into tOffset
	-- tOffset contains 5

Description:
Use `the offset of` to find where a particular sub-list occurs within
a list.  <Haystack> is scanned for a sequence of elements that are
equal to the elements of <Needle>, and the position of the start of
the sequence found is returned.  If neither the "first offset" nor
"last offset" are specified, the index of the first matching sub-list
found is returned.  If no sub-list of <Haystack> is equal to <Needle>,
the return value is 0.

Tags: Lists
*/
syntax ListOffset is prefix operator with precedence 1
	"the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "offset" "of" <Needle: Expression> "in" <Haystack: Expression>
begin
	MCListEvalOffsetOfList(IsLast, Needle, Haystack, output)
end syntax

/*
Summary:	Find the first or last occurrence of <Needle> within the tail of <Haystack>

Needle:	An expression which evaluates to any list.
After:		An expression which evaluates to a valid index in Target.
Target:	An expression which evaluates to a list.

Returns:	Returns the index in <Haystack> relative to <After>.

Example:
	variable tVar as List
	variable tOffset as Number
	put ["a", "b", "c", "d", "b", "c"]
	put the offset of ["b","c"] after 1 in tVar into tOffset
	--tOffset contains 2

	put the last offset of ["b","c"] after 1 in tVar into tOffset
	--tOffset contains 5

Description:

Use `the offset of… after` to find where a particular sub-list occurs
within a list.  Starting from but not including the position <After>,
<Haystack> is scanned for an sequence of elements that are equal to
the elements of <Needle>, and the position of the start of the
sequence found is returned.  If neither the "first offset" nor "last
offset" are specified, the position of the first matching sub-list
found is returned.  If no sub-list of <Haystack> starting after the
position <After> is equal to <Needle>, the return value is 0.

Tags: Lists
*/
syntax ListOffsetAfter is prefix operator with precedence 1
	"the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "offset" "of" <Needle: Expression> "after" <After: Expression> "in" <Haystack: Expression>
begin
	MCListEvalOffsetOfListAfter(IsLast, Needle, After, Haystack, output)
end syntax

/*
Summary:	Find the first or last occurrence of <Needle> within the head of <Haystack>

Needle:	An expression which evaluates to List.
Before:	An expression which evaluates to a valid index in Target.
Target:	An expression which evaluates to a List.

Returns:	Returns the index in <Haystack>.

Example:
	variable tVar as List
	variable tOffset as Number
	put ["a", "b", "c", "d", "b","c"]
	put the offset of ["b","c"] before 5 in tVar into tOffset
	--tOffset contains 2

	put the first offset of ["b","c"] before 6 in tVar into tOffset
	--tOffset contains 2

Description:

Use `the offset of… before` to find where a particular sub-list occurs
within a list.  <Haystack> is scanned for a sequence of elements that
are equal to the elements of <Needle>, stopping before the position
<Before>, and the position of the start of the sequence found is
returned.  If no sub-list of <Haystack> before the position <Before>
is equal to <Needle>, the return value is 0.  If neither "first" nor
"last" is specified, the last matching subsequence is found.

Tags: Lists
*/
syntax ListOffsetBefore is prefix operator with precedence 1
	"the" ( "first" <IsFirst=true> | "last" <IsFirst=false> | <IsFirst=false> ) "offset" "of" <Needle: Expression> "before" <Before: Expression> "in" <Haystack: Expression>
begin
	MCListEvalOffsetOfListBefore(IsFirst, Needle, Before, Haystack, output)
end syntax

end module
