Added is_uniform
predicate to analyse_structure.lua
.
This commit is contained in:
parent
5c7354e40f
commit
1bfd4abb96
|
@ -158,6 +158,26 @@ local function is_tabular (t)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return children_keys
|
||||||
|
end
|
||||||
|
|
||||||
|
local function has_uniform_structure (t)
|
||||||
|
-- TODO: This can probably be more relaxed. Maybe combine string, number and boolean?
|
||||||
|
|
||||||
|
assert(type(t) == 'table')
|
||||||
|
|
||||||
|
-- Find the key and value types.
|
||||||
|
local first_key = next(t)
|
||||||
|
if first_key == nil then return true end
|
||||||
|
local key_type, value_type = type(first_key), type(t[first_key])
|
||||||
|
|
||||||
|
-- Ensure every other key value pair is the same.
|
||||||
|
for key, value in pairs(t) do
|
||||||
|
if type(key) ~= key_type or type(value) ~= value_type then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -175,6 +195,7 @@ local function get_table_info (t)
|
||||||
info.has_map = info.map_elems > 0
|
info.has_map = info.map_elems > 0
|
||||||
info.is_set = is_set(t) and info.nr_elems >= MINIMUM_NUMBER_OF_SET_ELEMENTS
|
info.is_set = is_set(t) and info.nr_elems >= MINIMUM_NUMBER_OF_SET_ELEMENTS
|
||||||
info.is_tabular = is_tabular(t)
|
info.is_tabular = is_tabular(t)
|
||||||
|
info.is_uniform = has_uniform_structure(t)
|
||||||
|
|
||||||
-- Determine type of table
|
-- Determine type of table
|
||||||
if not info.has_seq and not info.has_map then info.type = TABLE_TYPE.EMPTY
|
if not info.has_seq and not info.has_map then info.type = TABLE_TYPE.EMPTY
|
||||||
|
|
|
@ -12,117 +12,117 @@ SUITE:addTest('Empty Table', function ()
|
||||||
local input = {} -- Empty!
|
local input = {} -- Empty!
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.EMPTY, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.EMPTY, 'Returned bad type: '..table_info.type)
|
||||||
assert(table_info.has_seq == false)
|
assert_equal(table_info.has_seq, false)
|
||||||
assert(table_info.has_map == false)
|
assert_equal(table_info.has_map, false)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Sequence', function ()
|
SUITE:addTest('Sequence', function ()
|
||||||
local input = { 1, 2, 3 }
|
local input = { 1, 2, 3 }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.SEQUENCE, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.SEQUENCE, 'Returned bad type: '..table_info.type)
|
||||||
assert(table_info.has_seq == true)
|
assert_equal(table_info.has_seq, true)
|
||||||
assert(table_info.has_map == false)
|
assert_equal(table_info.has_map, false)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Sequence with holes', function ()
|
SUITE:addTest('Sequence with holes', function ()
|
||||||
local input = { 1, nil, 3 }
|
local input = { 1, nil, 3 }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.SEQUENCE, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.SEQUENCE, 'Returned bad type: '..table_info.type)
|
||||||
assert(table_info.has_seq == true)
|
assert_equal(table_info.has_seq, true)
|
||||||
assert(table_info.has_map == false)
|
assert_equal(table_info.has_map, false)
|
||||||
assert(table_info.has_holes == true)
|
assert_equal(table_info.has_holes, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Sequence with hole on start', function ()
|
SUITE:addTest('Sequence with hole on start', function ()
|
||||||
local input = { nil, 2, 3 }
|
local input = { nil, 2, 3 }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.SEQUENCE, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.SEQUENCE, 'Returned bad type: '..table_info.type)
|
||||||
assert(table_info.has_seq == true)
|
assert_equal(table_info.has_seq, true)
|
||||||
assert(table_info.has_map == false)
|
assert_equal(table_info.has_map, false)
|
||||||
assert(table_info.has_holes == true)
|
assert_equal(table_info.has_holes, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Pure Map', function ()
|
SUITE:addTest('Pure Map', function ()
|
||||||
local input = { a = 1, [true] = 2, c = 3 }
|
local input = { a = 1, [true] = 2, c = 3 }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.PURE_MAP, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.PURE_MAP, 'Returned bad type: '..table_info.type)
|
||||||
assert(table_info.has_seq == false)
|
assert_equal(table_info.has_seq, false)
|
||||||
assert(table_info.has_map == true)
|
assert_equal(table_info.has_map, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Boolean set', function ()
|
SUITE:addTest('Boolean set', function ()
|
||||||
local input = { [true] = true, [false] = false }
|
local input = { [true] = true, [false] = false }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.SET, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.SET, 'Returned bad type: '..table_info.type)
|
||||||
assert(table_info.has_seq == false)
|
assert_equal(table_info.has_seq, false)
|
||||||
assert(table_info.has_map == true)
|
assert_equal(table_info.has_map, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('A Mixed table', function ()
|
SUITE:addTest('A Mixed table', function ()
|
||||||
local input = { 300, [300] = 1 }
|
local input = { 300, [300] = 1 }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.has_seq == true)
|
assert_equal(table_info.has_seq, true)
|
||||||
assert(table_info.has_map == true)
|
assert_equal(table_info.has_map, true)
|
||||||
assert(table_info.type == TABLE_TYPE.MIXED, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.MIXED, 'Returned bad type: '..table_info.type)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('String Map', function ()
|
SUITE:addTest('String Map', function ()
|
||||||
local input = { a = 1, b = 2, c = 3 }
|
local input = { a = 1, b = 2, c = 3 }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.STRING_MAP, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.STRING_MAP, 'Returned bad type: '..table_info.type)
|
||||||
assert(table_info.has_seq == false)
|
assert_equal(table_info.has_seq, false)
|
||||||
assert(table_info.has_map == true)
|
assert_equal(table_info.has_map, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Set', function ()
|
SUITE:addTest('Set', function ()
|
||||||
local input = { a = true, b = true, c = true }
|
local input = { a = true, b = true, c = true }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.SET, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.SET, 'Returned bad type: '..table_info.type)
|
||||||
assert(table_info.is_set == true)
|
assert_equal(table_info.is_set, true)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Tabular of sequences', function ()
|
SUITE:addTest('Tabular of sequences', function ()
|
||||||
local input = { a = {1, 2, 3}, b = {4, 5, 6}, c = {7, 8, 9} }
|
local input = { a = {1, 2, 3}, b = {4, 5, 6}, c = {7, 8, 9} }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.is_tabular == true)
|
assert_equal(table_info.is_tabular, {true, true, true})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Tabular of maps', function ()
|
SUITE:addTest('Tabular of maps', function ()
|
||||||
local input = { a = {a = 1, b = 2}, b = {a = 3, b = 4}, c = {a = 2, b = 7} }
|
local input = { a = {a = 1, b = 2}, b = {a = 3, b = 4}, c = {a = 2, b = 7} }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.is_tabular == true)
|
assert_equal(table_info.is_tabular, {a = true, b = true})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Not Tabular, due to no-sub-tables', function ()
|
SUITE:addTest('Not Tabular, due to no-sub-tables', function ()
|
||||||
local input = { a = 1, b = {4}, c = 7 }
|
local input = { a = 1, b = {4}, c = 7 }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.is_tabular == false)
|
assert_equal(table_info.is_tabular, false)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Not Tabular, due to not being identical sub-tables', function ()
|
SUITE:addTest('Not Tabular, due to not being identical sub-tables', function ()
|
||||||
local input = { a = { a = 1 }, b = { b = 2 }, c = { c = 3 } }
|
local input = { a = { a = 1 }, b = { b = 2 }, c = { c = 3 } }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.is_tabular == false)
|
assert_equal(table_info.is_tabular, false)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SUITE:addTest('Not Tabular, due to varying lengths', function ()
|
SUITE:addTest('Not Tabular, due to varying lengths', function ()
|
||||||
local input = { { 1 }, { 2, 3 }, { 4, 5, 6 } }
|
local input = { { 1 }, { 2, 3 }, { 4, 5, 6 } }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.is_tabular == false)
|
assert_equal(table_info.is_tabular, false)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -132,7 +132,7 @@ SUITE:addTest('goto is special', function ()
|
||||||
local input = { ['goto'] = 'hi' }
|
local input = { ['goto'] = 'hi' }
|
||||||
local table_info = analyze_structure(input)[input]
|
local table_info = analyze_structure(input)[input]
|
||||||
|
|
||||||
assert(table_info.type == TABLE_TYPE.PURE_MAP, 'Returned bad type: '..table_info.type)
|
assert_equal(table_info.type, TABLE_TYPE.PURE_MAP, 'Returned bad type: '..table_info.type)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -189,6 +189,48 @@ SUITE:addTest('Can count elements, even though metatable.__index throws errors',
|
||||||
assert_equal(info[input].seq_elems, 2)
|
assert_equal(info[input].seq_elems, 2)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Uniform structure
|
||||||
|
|
||||||
|
SUITE:addTest('Can detect uniform structure', function ()
|
||||||
|
local input = { a = 'b', b = 'a' }
|
||||||
|
local info = analyze_structure(input)
|
||||||
|
|
||||||
|
assert_equal(info[input].is_uniform, true)
|
||||||
|
end)
|
||||||
|
|
||||||
|
SUITE:addTest('Can detect uniform structure with different key value types', function ()
|
||||||
|
local input = { a = 1, b = 4 }
|
||||||
|
local info = analyze_structure(input)
|
||||||
|
|
||||||
|
assert_equal(info[input].is_uniform, true)
|
||||||
|
end)
|
||||||
|
|
||||||
|
SUITE:addTest('Can detect basic non-uniform structure', function ()
|
||||||
|
local input = { a = 'b', b = 5 }
|
||||||
|
local info = analyze_structure(input)
|
||||||
|
|
||||||
|
assert_equal(info[input].is_uniform, false)
|
||||||
|
end)
|
||||||
|
|
||||||
|
SUITE:addTest('Can detect pseudo-uniform structure with nested tables', function ()
|
||||||
|
-- It's pseudo-uniform because of the child having uniform structure with
|
||||||
|
-- equal number of elements.
|
||||||
|
local input = { a = { d = 7 }, b = { p = 3 } }
|
||||||
|
local info = analyze_structure(input)
|
||||||
|
|
||||||
|
assert_equal(info[input].is_uniform, true)
|
||||||
|
end)
|
||||||
|
|
||||||
|
SUITE:addTest('Can detect non-uniform structure with nested tables', function ()
|
||||||
|
local input = { a = { 'a', 'b', 'c' }, b = { p = 3, 'hi' } }
|
||||||
|
local info = analyze_structure(input)
|
||||||
|
|
||||||
|
assert_equal(info[input].is_uniform, false)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- TODO: Add predicate to check for pseudo-uniformness.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- API stuff
|
-- API stuff
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user