]> git.e2factory.org Git - e2factory.git/commitdiff
strict: change API to support fields with nil values
authorTobias Ulmer <tu@emlix.com>
Fri, 23 Nov 2012 17:44:28 +0000 (18:44 +0100)
committerTobias Ulmer <tu@emlix.com>
Tue, 26 Feb 2013 18:07:11 +0000 (19:07 +0100)
Previously, locked tables could not contain members set to nil,
since Lua is a bit confused about setting something to nil versus it not
existing at all.

Also all members are renamed fields, since "member" is an OO concept,
but the strict module doesn't particularily deal with objects.

The documentation was also slightly improved.

strict.unlock is now implemented, but still untested.

Signed-off-by: Tobias Ulmer <tu@emlix.com>
generic/plugin.lua
generic/strict.lua
local/scm.lua

index 111952a8a91838ada7f6dca1c7096c38f574bd13..396dcd7baff1103ee02310594de0a70116d9dc6d 100644 (file)
@@ -84,7 +84,7 @@ local function load_plugin(dir, p, ctx)
     local e = err.new("loading plugin failed: %s", p)
     local plugin_file = string.format("%s/%s", dir, p)
 
-    strict.declare(_G, {plugin_descriptor = {}})
+    strict.declare(_G, {"plugin_descriptor"})
 
     local chunk, msg = loadfile(plugin_file)
     if not chunk then
@@ -92,12 +92,13 @@ local function load_plugin(dir, p, ctx)
     end
     chunk()
     if not plugin_descriptor then
+        strict.undeclare(_G, {"plugin_descriptor"})
         return false, e:append("no plugin descriptor in plugin: %s",
         plugin_file)
     end
     local pd = plugin_descriptor
 
-    strict.undeclare(_G, {plugin_descriptor = {}})
+    strict.undeclare(_G, {"plugin_descriptor"})
 
     if type(pd.description) ~= "string" then
         e:append("description missing in plugin descriptor")
index 402254a0a4a9e4c2f0301b9ca4db948befa61de2..2d8be78af4727b9a0c8a709a21139211070b1d1e 100644 (file)
@@ -33,7 +33,7 @@ local function what()
     return d and d.what or "C"
 end
 
---- Lock a table against adding members explicitly or by implicit assignment.
+--- Lock a table against adding fields explicitly or by implicit assignment.
 -- @param t table to lock
 function strict.lock(t)
     assert(type(t) == "table")
@@ -48,7 +48,7 @@ function strict.lock(t)
         local mt = getmetatable(t)
         if not mt.__declared[k] and what() ~= "C" then
             error("assignment in "..tostring(t)..
-                " to undeclared variable '"..tostring(k).."'")
+                " to undeclared field '"..tostring(k).."'")
         end
 
         -- error("assignment to "..tostring(t).."["..
@@ -70,15 +70,24 @@ function strict.lock(t)
     return t
 end
 
---- Unlock a table that was protected against adding and assigning to members.
--- Not implemented yet.
--- @param t table to unlock
+--- Unlock a table that was protected against adding and assigning to fields.
+-- @param t table to unlock.
+-- @return the unlocked table.
 function strict.unlock(t)
     assert(type(t) == "table")
-    error("strict.unlock() is not implemented yet")
+
+    if not strict.islocked(t) then
+        error("table is not locked")
+    end
+
+    setmetatable(t, nil)
+
+    return t
 end
 
 --- Test whether a table is locked.
+-- The implementation determines this by looking at certain keys, it's therefore
+-- not 100% accurate.
 -- @param t table to check
 -- @return true if it's locked, false if not
 function strict.islocked(t)
@@ -92,45 +101,47 @@ function strict.islocked(t)
     return false
 end
 
---- Declare new members of a table and assign them a value.
--- Note that declaring already declared members causes an error message to be
--- raised.
--- @param t table to declare members in
--- @param values table of member (key) / value pairs.
-function strict.declare(t, values)
+--- Declare new fields of a table.
+-- Note that declaring existing fields raise a fatal error.
+-- @param t table to declare fields in
+-- @param fields array of field strings to declare.
+-- @return the modified table
+function strict.declare(t, fields)
     assert(type(t) == "table")
-    assert(type(values) == "table")
+    assert(type(fields) == "table")
     local mt = getmetatable(t)
 
-    for k, v in pairs(values) do
-        if mt.__declared[k] then
-            error("variable '"..k.."' is already declared")
+    for _,f in ipairs(fields) do
+        assert(type(f) == "string")
+
+        if mt.__declared[f] then
+            error("field '"..f.."' is already declared")
         end
-        mt.__declared[k] = true
-        rawset(t, k, v)
+        mt.__declared[f] = true
     end
 
     return t
 end
 
---- Remove members from a table.
--- Note that the members must be declared, otherwise a fatal error is raised.
--- Also note that values in the values table are ignored, only keys are
--- considered.
--- @param t table to remove members from
--- @param values table of members to delete. Must be in key/value form.
-function strict.undeclare(t, values)
+--- Remove fields from a table.
+-- Note that the fields must be declared, otherwise a fatal error is raised.
+-- @param t table to remove fields from
+-- @param fields array of field strings to remove.
+-- @return the modified table
+function strict.undeclare(t, fields)
     assert(type(t) == "table")
-    assert(type(values) == "table")
+    assert(type(fields) == "table")
     local mt = getmetatable(t)
 
-    for k, v in pairs(values) do
-        if not mt.__declared[k] then
-            error("variable '"..k.."' was not declared in the first place")
+    for _,f in ipairs(fields) do
+        assert(type(f) == "string")
+
+        if not mt.__declared[f] then
+            error("field '"..f.."' was not declared")
         end
 
-        mt.__declared[k] = nil
-        rawset(t, k, nil)
+        mt.__declared[f] = nil
+        rawset(t, f, nil)
     end
 
     return t
index 5a195aaacd97584769dd84dfdc659efa2bb18360..caba4cf46ec0a51de0d1558f57269f1aabbe68ab 100644 (file)
@@ -89,10 +89,9 @@ function scm.register_interface(name)
     -- we have lots of calls like scm.<function>(...). Register the interface
     -- function in the scm module to support those calls.
     if strict.islocked(scm) then
-        strict.declare(scm, {[name]=func})
-    else
-        scm[name] = func
+        strict.declare(scm, {name})
     end
+    scm[name] = func
 
     return true, nil
 end