summaryrefslogtreecommitdiff
path: root/src/ltable.js
blob: 14139afd498785287b196f285aca9712dad077ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*jshint esversion: 6 */
"use strict";

const assert  = require('assert');

const lobject = require('./lobject.js');
const lua     = require('./lua.js');
const CT      = lua.constant_types;
const nil     = require('./ldo.js').nil;
const Table   = lobject.Table;


Table.prototype.ordered_intindexes = function() {
    return [...this.value.keys()]
        .filter(e => typeof e === 'number' && e % 1 === 0)  // Only integer indexes
        .sort();
};

Table.prototype.ordered_indexes = function() {
    return [...this.value.keys()]
        .sort(function(a, b) {
            if (typeof a !== "number") return 1;
            if (typeof b !== "number") return -1;
            return a > b ? 1 : -1
        })
};

/*
** Try to find a boundary in table 't'. A 'boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
Table.prototype.luaH_getn = function() {
    // TODO: is this costly ?
    let indexes = this.ordered_intindexes();
    let len = indexes.length;

    for (let i = 0; i < len; i++) {
        let key = indexes[i];

        if (!this.value.get(key).ttisnil() // t[i] is non-nil
            && (i === len - 1 || this.value.get(indexes[i + 1]).ttisinil())) { // t[i+1] is nil or is the last integer indexed element
            return indexes[i];
        }
    }

    return 0;
};

Table.prototype.luaH_next = function(L, keyI) {
    let keyO = L.stack[keyI];
    let key = Table.keyValue(keyO);
    let indexes = this.ordered_indexes();
    let i = indexes.indexOf(key);

    if (i >= 0 && i < indexes.length - 1) {
        let nidx = indexes[i+1];
        let tnidx = typeof nidx;

        if (tnidx === 'number' && nidx % 1 === 0)
            L.stack[keyI] = new TValue(CT.LUA_TNUMINT, indexes[i + 1]);
        else if (tnidx === 'string')
            L.stack[keyI] = new TValue(CT.LUA_TLNGSTR, indexes[i + 1]);
        else
            L.stack[keyI] = indexes[i + 1];

        L.stack[keyI + 1] = this.map.get(indexes[i]);
        return 1;
    }

    return 0;
};