aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorV1K1NGbg <victor@ilchev.com>2024-08-22 17:48:57 -0300
committerHisham Muhammad <hisham@gobolinux.org>2024-10-21 13:30:51 -0300
commit68a5ee0d17a366cd49c4fa9ff6ac887fe917acd8 (patch)
tree71e70b9534f3da3197ed12249d797ff71956deb7 /src
parentf2697b158f0b94f615dffee553ac18cfbd72cd52 (diff)
downloadluarocks-68a5ee0d17a366cd49c4fa9ff6ac887fe917acd8.tar.gz
luarocks-68a5ee0d17a366cd49c4fa9ff6ac887fe917acd8.tar.bz2
luarocks-68a5ee0d17a366cd49c4fa9ff6ac887fe917acd8.zip
Teal: convert luarocks.type_check
Diffstat (limited to 'src')
-rw-r--r--src/luarocks/type_check.tl (renamed from src/luarocks/type_check.lua)100
1 files changed, 62 insertions, 38 deletions
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.tl
index 21085ef9..1b332be0 100644
--- a/src/luarocks/type_check.lua
+++ b/src/luarocks/type_check.tl
@@ -1,20 +1,42 @@
1 1
2local type_check = {} 2local record type_check
3 type_check_table: function(version: string, tbl: {any: any}, typetbl: TableSchema, context: string): boolean, string --! tbl and typetbl types)
4
5 record TableSchema
6 fields: {string: TableSchema}
7 _type: string
8 _name: string
9 _pattern: string
10 _version: string
11 _more: boolean
12 _mandatory: boolean
13 _any: TableSchema
14 end
15
16 MAGIC_PLATFORMS: TableSchema
17end
3 18
4local cfg = require("luarocks.core.cfg") 19local cfg = require("luarocks.core.cfg")
5local fun = require("luarocks.fun") 20local fun = require("luarocks.fun")
6local util = require("luarocks.util") 21local util = require("luarocks.util")
7local vers = require("luarocks.core.vers") 22local vers = require("luarocks.core.vers")
23
24local type TableSchema = type_check.TableSchema
8-------------------------------------------------------------------------------- 25--------------------------------------------------------------------------------
9 26
10-- A magic constant that is not used anywhere in a schema definition 27-- A magic constant that is not used anywhere in a schema definition
11-- and retains equality when the table is deep-copied. 28-- and retains equality when the table is deep-copied.
12type_check.MAGIC_PLATFORMS = 0xEBABEFAC 29type_check.MAGIC_PLATFORMS = {}
13 30
14do 31do
15 local function fill_in_version(tbl, version) 32 local function fill_in_version(tbl: TableSchema, version?: string)
16 for _, v in pairs(tbl) do 33
17 if type(v) == "table" then 34 if not tbl.fields then --! validation
35 return
36 end
37
38 for _, v in pairs(tbl.fields) do
39 if v is TableSchema then
18 if v._version == nil then 40 if v._version == nil then
19 v._version = version 41 v._version = version
20 end 42 end
@@ -23,14 +45,13 @@ do
23 end 45 end
24 end 46 end
25 47
26 local function expand_magic_platforms(tbl) 48 local function expand_magic_platforms(tbl: TableSchema)
27 for k,v in pairs(tbl) do 49 for k,v in pairs(tbl.fields) do
28 if v == type_check.MAGIC_PLATFORMS then 50 if v == type_check.MAGIC_PLATFORMS then
29 tbl[k] = { 51 tbl.fields[k] = {
30 _any = util.deep_copy(tbl) 52 _any = util.deep_copy(tbl as {string: any}) as TableSchema
31 } 53 }
32 tbl[k]._any[k] = nil 54 tbl.fields[k]._any.fields[k] = nil
33 elseif type(v) == "table" then
34 expand_magic_platforms(v) 55 expand_magic_platforms(v)
35 end 56 end
36 end 57 end
@@ -41,17 +62,17 @@ do
41 -- and the value is a schema specification. Schema versions are considered 62 -- and the value is a schema specification. Schema versions are considered
42 -- incremental: version "2.0" only needs to specify what's new/changed from 63 -- incremental: version "2.0" only needs to specify what's new/changed from
43 -- version "1.0". 64 -- version "1.0".
44 function type_check.declare_schemas(inputs) 65 function type_check.declare_schemas(inputs: {string: TableSchema}): {string : TableSchema}, {string}
45 local schemas = {} 66 local schemas: {string: TableSchema} = {}
46 local parent_version 67 local parent_version: string
47 68
48 local versions = fun.reverse_in(fun.sort_in(util.keys(inputs), vers.compare_versions)) 69 local versions = fun.reverse_in(fun.sort_in(util.keys(inputs), vers.compare_versions))
49 70
50 for _, version in ipairs(versions) do 71 for _, version in ipairs(versions) do
51 local schema = inputs[version] 72 local schema = inputs[version]
52 if parent_version ~= nil then 73 if parent_version then
53 local copy = util.deep_copy(schemas[parent_version]) 74 local copy: TableSchema = util.deep_copy(schemas[parent_version] as {any: any}) as TableSchema
54 util.deep_merge(copy, schema) 75 util.deep_merge(copy as {any: any}, schema as {any: any})
55 schema = copy 76 schema = copy
56 end 77 end
57 fill_in_version(schema, version) 78 fill_in_version(schema, version)
@@ -66,7 +87,7 @@ end
66 87
67-------------------------------------------------------------------------------- 88--------------------------------------------------------------------------------
68 89
69local function check_version(version, typetbl, context) 90local function check_version(version: string, typetbl: TableSchema, context: string): boolean, string
70 local typetbl_version = typetbl._version or "1.0" 91 local typetbl_version = typetbl._version or "1.0"
71 if vers.compare_versions(typetbl_version, version) then 92 if vers.compare_versions(typetbl_version, version) then
72 if context == "" then 93 if context == "" then
@@ -78,6 +99,8 @@ local function check_version(version, typetbl, context)
78 return true 99 return true
79end 100end
80 101
102
103
81--- Type check an object. 104--- Type check an object.
82-- The object is compared against an archetypical value 105-- The object is compared against an archetypical value
83-- matching the expected type -- the actual values don't matter, 106-- matching the expected type -- the actual values don't matter,
@@ -90,8 +113,7 @@ end
90-- @return boolean or (nil, string): true if type checking 113-- @return boolean or (nil, string): true if type checking
91-- succeeded, or nil and an error message if it failed. 114-- succeeded, or nil and an error message if it failed.
92-- @see type_check_table 115-- @see type_check_table
93local function type_check_item(version, item, typetbl, context) 116local function type_check_item(version: string, item: any, typetbl: TableSchema, context: string): boolean, string
94 assert(type(version) == "string")
95 117
96 if typetbl._version and typetbl._version ~= "1.0" then 118 if typetbl._version and typetbl._version ~= "1.0" then
97 local ok, err = check_version(version, typetbl, context) 119 local ok, err = check_version(version, typetbl, context)
@@ -100,7 +122,6 @@ local function type_check_item(version, item, typetbl, context)
100 end 122 end
101 end 123 end
102 124
103 local item_type = type(item) or "nil"
104 local expected_type = typetbl._type or "table" 125 local expected_type = typetbl._type or "table"
105 126
106 if expected_type == "number" then 127 if expected_type == "number" then
@@ -108,32 +129,32 @@ local function type_check_item(version, item, typetbl, context)
108 return nil, "Type mismatch on field "..context..": expected a number" 129 return nil, "Type mismatch on field "..context..": expected a number"
109 end 130 end
110 elseif expected_type == "string" then 131 elseif expected_type == "string" then
111 if item_type ~= "string" then 132 if not item is string then
112 return nil, "Type mismatch on field "..context..": expected a string, got "..item_type 133 return nil, "Type mismatch on field "..context..": expected a string, got "..type(item)
113 end 134 end
114 local pattern = typetbl._pattern 135 local pattern = typetbl._pattern
115 if pattern then 136 if pattern then
116 if not item:match("^"..pattern.."$") then 137 if not item:match("^"..pattern.."$") then --! cast or tostring
117 local what = typetbl._name or ("'"..pattern.."'") 138 local what = typetbl._name or ("'"..pattern.."'")
118 return nil, "Type mismatch on field "..context..": invalid value '"..item.."' does not match " .. what 139 return nil, "Type mismatch on field "..context..": invalid value '"..item.."' does not match " .. what
119 end 140 end
120 end 141 end
121 elseif expected_type == "table" then 142 elseif expected_type == "table" then
122 if item_type ~= expected_type then 143 if not item is table then
123 return nil, "Type mismatch on field "..context..": expected a table" 144 return nil, "Type mismatch on field "..context..": expected a table"
124 else 145 else
125 return type_check.type_check_table(version, item, typetbl, context) 146 return type_check.type_check_table(version, item, typetbl, context)
126 end 147 end
127 elseif item_type ~= expected_type then 148 elseif type(item) ~= expected_type then
128 return nil, "Type mismatch on field "..context..": expected "..expected_type 149 return nil, "Type mismatch on field "..context..": expected "..expected_type
129 end 150 end
130 return true 151 return true
131end 152end
132 153
133local function mkfield(context, field) 154local function mkfield(context: string, field: any): string
134 if context == "" then 155 if context == "" then
135 return tostring(field) 156 return tostring(field)
136 elseif type(field) == "string" then 157 elseif field is string then
137 return context.."."..field 158 return context.."."..field
138 else 159 else
139 return context.."["..tostring(field).."]" 160 return context.."["..tostring(field).."]"
@@ -162,30 +183,33 @@ end
162-- to be used by error messages. 183-- to be used by error messages.
163-- @return boolean or (nil, string): true if type checking 184-- @return boolean or (nil, string): true if type checking
164-- succeeded, or nil and an error message if it failed. 185-- succeeded, or nil and an error message if it failed.
165function type_check.type_check_table(version, tbl, typetbl, context) 186function type_check.type_check_table(version: string, tbl: {any: any}, typetbl: TableSchema, context: string): boolean, string
166 assert(type(version) == "string")
167 assert(type(tbl) == "table")
168 assert(type(typetbl) == "table")
169 187
170 local ok, err = check_version(version, typetbl, context) 188 local ok, err = check_version(version, typetbl, context)
171 if not ok then 189 if not ok then
172 return nil, err 190 return nil, err
173 end 191 end
174 192
193 if not typetbl.fields then --! validation
194 -- if there are no fields, exit the checker
195 return true
196 end
197
175 for k, v in pairs(tbl) do 198 for k, v in pairs(tbl) do
176 local t = typetbl[k] or typetbl._any 199 local t = typetbl.fields[tostring(k)] or typetbl._any
177 if t then 200 if t then
178 local ok, err = type_check_item(version, v, t, mkfield(context, k)) 201 ok, err = type_check_item(version, v, t, mkfield(context, k))
179 if not ok then return nil, err end 202 if not ok then return nil, err end
180 elseif typetbl._more then 203 elseif typetbl._more then
181 -- Accept unknown field 204 -- Accept unknown field
182 else 205 else
183 if not cfg.accept_unknown_fields then 206 if not cfg.accept_unknown_fields then
184 return nil, "Unknown field "..k 207 return nil, "Unknown field "..tostring(k)
185 end 208 end
186 end 209 end
187 end 210 end
188 for k, v in pairs(typetbl) do 211
212 for k, v in pairs(typetbl.fields) do
189 if k:sub(1,1) ~= "_" and v._mandatory then 213 if k:sub(1,1) ~= "_" and v._mandatory then
190 if not tbl[k] then 214 if not tbl[k] then
191 return nil, "Mandatory field "..mkfield(context, k).." is missing." 215 return nil, "Mandatory field "..mkfield(context, k).." is missing."
@@ -195,10 +219,10 @@ function type_check.type_check_table(version, tbl, typetbl, context)
195 return true 219 return true
196end 220end
197 221
198function type_check.check_undeclared_globals(globals, typetbl) 222function type_check.check_undeclared_globals(globals: {string: any}, typetbl: TableSchema): boolean, string --! tbl and typetbl types
199 local undeclared = {} 223 local undeclared = {}
200 for glob, _ in pairs(globals) do 224 for glob, _ in pairs(globals) do
201 if not (typetbl[glob] or typetbl["MUST_"..glob]) then 225 if not (typetbl.fields[glob] or typetbl.fields["MUST_"..glob]) then
202 table.insert(undeclared, glob) 226 table.insert(undeclared, glob)
203 end 227 end
204 end 228 end