Question

I am using Groovy to write a DSL handling BASIC and I would like some assistance with how to handle multi (more than 2) dimensional arrays.

I am dealing with BASIC code like this:

100 LET X = A(1, 2, 3)

It is easy to handle the 1 dimensional case - just create a closure (via MOP) that returns the elements of A, while for 2 dimensions I can do the same in the form

A(2, 3) == A.get(2)[3]

But how do I handle arrays of unlimited dimensions?

Update: To make this a bit clearer, the question is how can I return the array values dynamically in the DSL context? The script interpreter sees A(1, 2, 3) as a function call which I can intercept using the MOP. But how do I return the value of the array element in that context?

Was it helpful?

Solution 2

In the end I decided to parse the input and use that to build a closure via the MOP:

    /* array references look like functions to Groovy so trap them */
    BinsicInterpreter.metaClass."$varName" = {Object[] arg ->
        def answer = "package binsic; $varName"
        arg.each { 
            answer = answer + "[$it]"
        }
        def something = shell.evaluate(answer)
        return something
    }

So if we had:

100 LET X = A(10, 20, 3)

The MOP traps A(...) as a function call and the code above gives me A[10][20][3]

OTHER TIPS

If you a n-dimensional array modelled with nested lists (not the most memory-efficient way to do it, but quite easy to implement), and want to access the element at indexes [i_1, i_2, ... , i_n] you can do:

def getElementAt(arr, ... indexes) {
    indexes.inject(arr) { a, ind -> a[ind] }
}

// A 2x2x3 array implemented with nested lists.
def arr = [[[1,1,1], [1,1,5]], [[1,1,1], [1,1,1]]]

// I want to get that 5!
assert getElementAt(arr, 0, 1, 2) == 5

// The line above is equivalent to:
assert arr[0][1][2] == 5

The inject lets you iterate a collection and accumulate the result of a given operation starting with an initial value. In this case, we iterate the indexes we want to get from the array and start the iteration with the whole array; each iteration then returns the sub-array at a given index, which is the value that will be used in the next iteration. If you happen to use it with less indexes than expected, it will return a list instead of an integer, e.g. getElementAt(arr, 0, 1) == [1, 1, 5].

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top