-
Notifications
You must be signed in to change notification settings - Fork 155
Array #173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Array #173
Conversation
…s, e.g. "typeof(a())")
…variadic parameter may contain commas, so it may expand to more than one parameter, this also allows for a macro to receive less arguments than specified in the macro´s definition, if there is a variadic parameter.
…ty variadic paramter, the else clause was missing
…efining an already defined key word, the existing definition is not lost, but temporarily superseded by the new definition. The original definition becomes valid again as soon as a scope block is left, or by using #UNDEF, in global scope #UNDEF is mandatory.
…at is, it returns the argument count of a (variadic) parameter. An empty parameter counts as one parameter. This can be extremly useful for processing variadic macro parameters.
… as "#" operator) but as uppercase. This is useful for case independent parsing of macro arguments.
|
The first section (mostly for the preprocessor to allow for more flexible macros) is ready now. TYPEOF : Macro parameter check modification: BUGFIX: #REDEF : "###" : "#&#" : JK |
…rayCalcPos, fb_ArrayCalcIdxPos, fb_ArrayCalcIdxPtr, fb_ArrayShift, fb_ArraySort, fb_ArrayAttach, fb_ArrayReset, fb_ArrayScan)
|
Section two is ready. This adds all new RTL function definitions needed for the new array features It might still be necessary to apply minor changes to these definitions in rtl-array.bas later on. JK |
…ry definitions and code.
|
As a third step "array.bi" has been added. This file contains the necessary definitions and code. It will be updated along with the following commits for the RTL in order to activate the provided features. JK |
…ompile time errors (#ERROR ...) inside macros is one line off sometimes, #LINE __PREVLINE__ can fix this.
… overlay and for resetting such an array to default state again.
…nter, linear (one based) index and (multidimensional) array indices
…rom an existing array. This doesn´t change (REDIM) the element count of an array
…t, ...) and array(scan, ...) to be complete
…ions for each standard variable type, as well as support for custom sort functions
… literal or expression, custom search functions are suported too.
|
The last section covers additions to the RTL and corresponding changes to the compiler and "array.bi" All new features work with all kinds of arrays regardless of the data type. Passed z/wstring arrays don´t work because of an existing bug. Applying #158 to this PR fixes this problem. Arrays: This seems pretty obvious so far, it starts to become a bit more complicated with multidimensional arrays. That is, you must specify more than one index value for accessing an element. The memory layout is the same, but the overlaying logic is different. Nevertheless any multidimensional may be seen as a one dimensional array too. In fact "DIM a(1 to 8) AS BYTE" allocates the same amount of memory as "DIM b(1 to 2, 1 to 2, 1 to 2) AS BYTE". In case of a() the first element in memory is a(1), the second a(2) and so on, in case of b(), the first element is b(1,1,1), the second element in memory is b(1,1,2), the third is b(1,2,1). If we look at b() as if it was a one dimensional array with a starting index of 1, we would have a "linear index" of 1 for (1,1,1), of 2 for (1,1,2), 3 for (1,2,1) and so on. All array features work for multidimensional arrays too. You may specify a certain element by it´s "regular index" (x,y,z,...) or by it´s "linear index". It is important to understand, that array scan always returns the linear index, which is identical to the one dimensional index with a starting index of 1. Example: for "DIM a(1 to 8) AS BYTE" a linear index of 4 denominates element 4 for "DIM a(10 to 18) AS BYTE" a linear index of 4 denominates element 13 (!) Syntax: array(sort, ... no return value sort an array of arbitrary type, for arrays of UDT´s you must define and use a callback function for sorting, for all standard variable types there is a readymade sorting function in the RTL or you may use a user defined callback, if you like. In general using a callback function is slower, because of the overhead of multiple calls. The default sorting direction is ascending ("up"), if not specified otherwise. For sorting in descending order you must specify "down". By default all elements of an array are sorted. You may specify a starting index and a count of elements to sort. If no count is given, all elements up to the end of the array are sorted. The starting index may be given as index (index value(s) in parenthesis) as usual "(x,y,...)", or a linear index. In case of a linear index, the key word "pos" is required (pos(). You may specify a second array of arbitrary type to be sorted in the same order as the first Arrays of strings (zstring/wstring/string and ustring) may be sorted case insensitive. Default is case sensitive. For a case insensitive sorting you must specify the "nocase" key word in parenthesis with the string array to sort (see example #3 and #4). array(sort, array) array(insert, ... no return value Inserts an element into an existing array by shifting the already present elements up by one. Currently the last element is shifted out and thus deleted. For elements with a destructor, the destructor "Value" must be of the same variable type as the array itself and is assigned to the given position. You may only insert one element at a time. Position may be a regular index or a linear index. By default all elements up to the end of the array are shifted. Count restricts this shift operation to the specified number of elements. array(insert, array, value [, (i1 [, i2 [, ...]]) | pos(i), [, count]]) array(delete, ... no return value Deletes an element into an existing array by shifting the already present elements down by one. The last is initialized to the data type´s default value. For elements with a constructor, the You may only delete one element at a time. Position may be a regular index or a linear index. By default all elements up to the end of the array are shifted. Count restricts this shift operation to the specified number of elements. The last element covered by "count", is initialized to it´s default in this case. array(delete, array [, (i1 [, i2 [, ...]]) | pos(i), [, count]]) array(scan, ... returns linear index Searches an array for a specified value (for(). "Searchterm" must be a compatible type. That is, you may mix all numeric types (except floating point types) and all string types. Obviously not all allowed combination make sense under all circumstances. It´s up to the user to interpret results in correct manner. A value of zero is returned, if searchterm is nor present in the array, otherwise the linear position (!) of the first occurrence is returned. Position may be a regular index or a linear index. By default all elements up to the end of the array are searched. Count restricts this search operation to the specified number of elements. Arrays of strings (zstring/wstring/string and ustring) may be searched case insensitive. The default is case sensitive. For a case insensitive sorting you must specify the "nocase" key word in the for() clause (see example #2). For arrays of UDT´s you must define and use a callback function for searching, for all standard variable types there is a ready-made search function in the RTL. You may use a user defined callback for special searches, if you like. In general using a callback function is slower, because of the overhead of multiple calls. A return value of 0 may indicate either "not found" or "an error occurred", you must check ERR in this case. i = array(scan, array, for()[, (i1 [, i2 [, ...]]) | pos(i), [, count]]) for(searchterm [,nocase [,from]) array(, ... Return the requested value from the array´s descriptor. Some values are already available i = array(specifier, array), returns any ptr (1), integer (2,3,4,5) or boolean (6,7,8) array(, ... Calculate the linear index form a regular index and vice versa, do the same for a given memory pointer. This is necessary for retrieving the regular index from the linear index returned by "array(scan, ...", and it is necessary when dealing with multidimensional arrays. i = array(pos, array, (i1 [, i2 [,...]])) returns linear (one based) position from index array(attach, ... Redim an array at a specific memory location. You must specify the index (or indices) as usual "REDIM()". No memeory is allocated or deallocated afterwards, instead existing memory is made accessible by an overlay structure in form of an array. This can be useful for all kinds of direct data manipulation. Array reset erases the array descriptor again without erasing the memory. This feature requires an empty (not yet dimmed or erased) dynamic array and doesn´t work with array(attach, array, redim(1 to 5[, 1 to 6 [1, ...]]), memory ptr) |
|
I didn´t know that Travis fails on warnings ... This PR is ready now for review. I coded and ran tests, which will have to be ported to the test suite as soon as this PR is in a state, that it will be accepted. JK |
|
There is but one thing that bothers me currently, with respect to INDEXING. |
|
Well, i have three reasons for starting at 1 for the "linear index" 1.) It´s important to understand that a "linear index" is a different thing than a regular index. 2.) With array(scan, ...) i need a return value for "not found". Zero seems to be the most logical 3.) lbound and ubound are defined as "INTEGER", which means an array´s index can cover the whole So in case your array is not one dimensional or it´s lbound is not 1, you must use "Array_index" is defined in array.bi as type array_index 'return type for array(index, ...) li as integer 'linear index (one based), 0 = invalid JK |
…ew pp operator (#&# and #?)
…t open bracket, adapt array.bi. this allows for arrays to be specified with and without brackets (a - a() both are valid)
|
I changed the allowed syntax to accept array parameters with and without brackets. The prefererred syntax should be "array()" (with brackets) for clarity. |
This pull request is ready now for review.
It has four sections (each one split into several commits):
There are comments after each section for further information
JK