Context madness bugs?

Started by m35, November 20, 2008, 12:19:16 AM

Previous topic - Next topic

m35

newLISP v.9.9.94 on Win32 IPv4, execute 'newlisp -h' for more info.

> (setq FISH:test 10)
10
> (delete FISH)
true
> (setq FISH:test 20)

ERR: context expected in function setf : FISH
Can you only create a context that way once? Also note the "setf" in the error.


newLISP v.9.9.94 on Win32 IPv4, execute 'newlisp -h' for more info.

> (setq FISH:FISH FISH)
FISH
> (delete 'FISH:FISH)
This crashes with a segment fault.

newBert

#1
Quote from: "m35"Also note the "setf" in the error.

It's because 'setf' = 'setq'


newLISP v.9.9.94 on Win32 IPv4, execute 'newlisp -h' for more info.

> setq
setq <40802D>
> setf
setf <40802D>
>


May be the explanation is in the newLISP Manual and Reference at 'delete'


Quote    ;; in contexts, the quote may be omitted

    (delete foo)  → foo:x, foo:y deleted



In the last example only the symbols inside context foo will be deleted but not the context symbol foo itself. It will be converted to a normal unprotected symbol and contain nil.



Note that deleting a symbol that is part of a function which is currently executing can crash the system or have other unforeseen effects.

:-)
<r><I>>Bertrand<e></e></I> − <COLOR color=\"#808080\">><B>newLISP<e></e></B> v.10.7.6 64-bit <B>>on Linux<e></e></B> (<I>>Linux Mint 20.1<e></e></I>)<e></e></COLOR></r>

Lutz

#2
The first example is correctly explained by newBert: When deleting a context, then all symbols in it get deleted, and the context symbol is demoted to a normal symbol.



Only this way it is possible to have variables holding contexts:


(setq FISH:test 10) => 10
(setq FOO FISH) => FISH

FOO:test => 10


FOO is now a variable holding a context. FOO:test and FISH:test point to the same piece of memory. If I do:


(set 'FOO:test 1234) => 1234

FISH:test => 1234


then FOO and FISH point to the same context. When the interpreter sees: CCC:xxx, it checks first if CCC exists as a context or a normal variable. If neither has been seen before, CCC will be created as a context. If CCC exists already as a normal variable, the interpreter expects CCC to hold a context else will throw an error.



The only way to to elevate a normal symbol back to a context symbol is using the 'context' primitive itself.



Demoting context symbols to normal symbols after deletion was introduced in version 9.1.6 to make it possible to create a context from a local variable in a function. Jeff requested this to be able to create transient contexts, which do only exist during the life of the function execution:


(define (foo x)
    (let (ctx 999)
        (println "ctx:" ctx)
        (context 'ctx) ; create a context from local variable
        (set 'ctx:x 123)
        (println "current context:" (context))
        (println "symbols in ctx: " (symbols ctx))
        (println "ctx:x: " ctx:x)
        (println "x:" x)
        (delete 'ctx)
))

> (foo 10)
ctx:999
current context:ctx
symbols in ctx: (x)
ctx:x: 123
x:10
true
>


This construct is only possible using that demotion feature, because we cannot delete the local 'ctx' , which is part of the function defined. I don't think that transient contexts are a necessary feature, but Jeff felt very strong about this and came up with some interesting examples.



It is this new 'demotion' feature introduced in 9.1.6 which causes the crash observed in the second self-referential m35 example, when doing (setq C:C C) (delete 'C:C), or also when doing (set 'C:test C) (delete 'C:test). The deletion of C:test deletes at first the contents of it which is C itself.



'delete' is a low level newLISP function which has no usage in normal newLISP programming, but I will see if this special case can be taken care of without impact on code size or performance.



ps: fixed in 9.9.95, will delete without crash.

m35

#3
Ah ok, thanks for the detailed explanations guys. I probably should have mentioned I was just trying to remove symbols out of contexts. Now that I understand better what's going on, I see I could have used workarounds.


newLISP v.9.9.94 on Win32 IPv4, execute 'newlisp -h' for more info.

> (setf FISH:test 100)
100
> (delete 'FISH)
true
> (delete 'FISH)
true
> (setf FISH:test 100)
100

The first delete demotes the context symbol to a normal symbol, and the second delete removes the symbol. Of course as you mentioned Lutz, using (context FISH) after the first delete would work as well.


newLISP v.9.9.94 on Win32 IPv4, execute 'newlisp -h' for more info.

> (setf FISH:test FISH)
FISH
> (setf FISH:test 123)
123
> (delete 'FISH:test)
true
> (symbols FISH)
()

First set the symbol to a non-context value, then delete the symbol.

Thanks for fixing the crash in my first post Lutz. I think it's good to have the same behavior regardless of whether the symbol points to a context or not.