lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Tue, Sep 28, 2010 at 2:29 AM, Juris Kalnins <juris@mt.lv> wrote:

> What exactly are the semantics of the functions that you propose?
When a value stored inside a field is locked, the value of the field
cannot be changed, what simulates a constant behavior.

> What is the intended use of such feature?
Protect constants values from accidental or malicious changes, like in
any other programming language with constants.

>> myprint = function(...) print('Hi',...) end
>> _G.print = lkset(_G.print)  -- protects against accidental change
>> _G.print = myprint
>>>>>
>>>>> error: attempt to change a locked value:  function: 004755D8
>
> so what exactly gets locked -- value of function 'print' or value
> at the key 'print' in table _G?

What is locked is the value stored inside _G.print field.

> local a = lkset({}) -- is a locked?
Yes. The value stored in a cannot be changed.
So a = nil will fail, but a.test = 1 is ok.

> local b = { k = a } -- is b.k locked?
No.

For your understanding, I must tell the implementation details - no secrets:

The LKBit are in fact 2 bits that represents:
  00 - UNLOCKED, 01 - LOCK, 10 - LOCKED, 11 - UNLOCK.
When you assign a field with a LOCKED value, the patch changes the
bits to 00 - UNLOCKED before store it. The function lkset() sets the
bits to 01 - LOCK. When you assign a LOCK value to a field:
1) if the field is UNLOCKED, it becomes LOCKED
2) if the field is LOCKED, then << 2 options - I will decide later>>
a) error "change a locked..." - this option is the usual constant behavior.
b) if the new and old values are equal then ok else fail - this option
makes lkset idempotent.

> local c, d = {}, {}
> c.k = {}
> d.k = c.k
> c.k = lkset(c.k) -- is d.k locked now?

No. Although both references the same object, each one has its own
storage area.
The patch will lock this area.

> c.k.v = 1 -- does this work?

Yes.

--- UNFINISHED IDEA BEGIN ---
But I was working in a new version of original message adding the function:
  const(value, optional_deep)  <==> lkset(value, true) plus an optional_deep
that makes all the elements inside the table (tree?), constant.

So to make c.k a read-only table, you should write:
  c.k = const(c.k,true)

It is not finish because it is too dangerous.
If the table c.k references a outer table, like _G, it will damage the
whole LuaState.
May be a const(value,deep_level) to control how deep the const will be
applied...
  true means total
  0/false/nil means don't apply inside
  1 or more is the deep level
May be testing if any references reachs _G
.
Note that you still could add new items inside the table.
The table itself is not locked. Just the values stored inside when you
called the const()
--- UNFINISHED IDEA END ---

> setmetatable(c.k, evil_metatable) -- does this work?
Yes for now.

--- UNFINISHED IDEA BEGIN ---
I didn't think about that yet.
Perhaps a convenience parameter in const that makes  __metatable  = false.
  const(tab,deep_level,lock_metatable)
--- UNFINISHED IDEA END ---

-----------------------------------------
Someone would like to help?

A good knowledge of table implementation in Lua will shorten the work.
A environment ready to make lots of benchmarks to measure the impact
on regular Lua code will help too.


-- 
Nilson