r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3]

Maxim
12-Oct-2010
[5205x3]
to-error doesn't create armed errors anymore which is a bit strange... 

in the least they are not triggering errors when used within an extension's 
init block.
one function which I would really like to see added to R3 is a search 
function which searches the body of all resident code and returns 
paths or full text of every place an occurence of your search is 
found.
in this case, I could see where cause-error is used and could learn 
from the mezz code.
Gabriele
12-Oct-2010
[5208]
iirc you just pass an error! value to cause-error
Maxim
12-Oct-2010
[5209x5]
It seems    do  to-error "whatever"    also works.


but I'd like to get the list of valid types and expected args for 
cause-error.
the online-docs just say that the lists should be filled in...  ' 
:-/
I'm building a search function, btw.  so far not bad.  still have 
to solve a little unset! issue
here my simple but effective r3 search function:

;------------------------------------------------------------
search-body: funct [
	data [object! block! function!] "what to search"
	word [word!] "what to find"
	/paths "only returns paths, not their values"
	/indents i "how many tabs when listing?"
	/into blk "Add matches to this block"
	/path pth [lit-path!] "keep track of path"
][
	
	i: any [i 0]
	
	unless into [
		set 'searched-objects copy [] ; will set in "globals"
	]
	
	either block? :data [
		b: data
	][
		b: body-of :data
	]
	
	
	; locals
	item: none
	match?: false
	blk: any [blk copy []]
	pth: any [all [pth copy pth] to-lit-path ""]
	last-set-word: none
	counter: 0
	
	foreach item :b [
		counter: counter + 1
		
		result: switch/default type?/word :item [
			set-word! [
				last-set-word: :item
				false
			]
			object! [
				; prevent endless cycles on self or inter references.
				unless find searched-objects :item [
					append searched-objects :item
					either block? data [

      search-body/indents/into/path :item word i + 1 blk append copy pth 
      counter
					][

      search-body/indents/into/path :item word i + 1 blk append copy pth 
      to-word last-set-word
					]
				]
				true
			]
			function! [
				either word = to-word last-set-word [
					; adds the definition OF the searched item

     append/only blk to-lit-path append/only copy pth last-set-word
					append/only blk mold :item
				][
					if search-body/indents/into/path :item word i + 1 blk pth [
						; adds a function WITH the searched item in it

      append/only blk to-lit-path append/only copy pth last-set-word
						append/only blk mold :item
					]
				]
				true
			]
			integer! tuple! string! [
				if last-set-word [
					if word = to-word last-set-word [

      append/only blk to-lit-path append/only copy pth last-set-word
						append/only blk  :item
					]
				]
				true
			]
			block! [

    search-body/indents/into/path :item word i + 1 blk append copy pth 
    counter
				true
			]
			
			; this is what we search for
			word! [
				either :item = word [
					match?: true
				][
					false
				]
			]
			
		][
			; these types are not specifically managed by the search
			false
		]
	]
	either into [
		match?
	][
		set 'quiet-search? false
		new-line/skip blk true 2
	]
]
;----------------------------------------------
in A107... 

search-body system 'red 
== [
    'contexts/system/red: 255.0.0
    'contexts/user/red: 255.0.0
]

search-body system 'error!
== [
    'contexts/system/map: {make function! [[
    "Temporary function to catch MAP usage changes."
][

    make error! {The MAP function has been rename to MAP-EACH. Update 
    your code.}
]]}
    'contexts/system/cause-error: {make function! [[

    {Causes an immediate error throw with the provided information.}
    err-type [word!]
    err-id [word!]
    args
][
    args: compose [(:args)]
    forall args [
        if any-function? first args [
            change/only args spec-of first args
        ]
    ]
    do make error! [
        type: err-type
        id: err-id
        arg1: first args
        arg2: second args
        arg3: third args
    ]
]]}

    'contexts/system/to-error: {make function! [["Converts to error! 
    value." value][to error! :value]]}
]
Henrik
12-Oct-2010
[5214]
a: [a]

parse [] a

R3 quits. Bug?
Maxim
12-Oct-2010
[5215x2]
oops ... the end of the function should be replaced by:

	either into [
		match?
	][
		either paths [
			blk: extract blk 2
			new-line/all blk true
		][
			new-line/skip blk true 2
		]
	]
henrik, any case where R3 just quits is a bug... no?
Henrik
12-Oct-2010
[5217]
I would assume so, but still asking to be sure.
Maxim
12-Oct-2010
[5218x4]
with above changes, one can use search-body()  using  the paths refinement.... 
like so:

>> search-body/paths system 'error!

== [
    'contexts/system/map:
    'contexts/system/cause-error:
    'contexts/system/to-error:
]
I hope the  above function makes it easier for you guys to track 
down where words are being used and defined.  :-)
note, it only accumulates then within objects and functions for now.
in some cases block, might trigger a match but it doesn't seem completely 
functional, but for me, the above is enough.
BrianH
12-Oct-2010
[5222]
Maxim, to answer your questions about cause-error: Three arguments, 
the first two being words from system/catalog/errors, the last one 
eiither being a single value of any type or a block of up to three 
values, depending on which error you are generating. All the info 
you need about a particular error is in system/catalog/errors. The 
number of arguments in the argument block is fixed, per error. The 
usage is in the phrasing of the error message. Pick arguments that 
when molded and put in that position in the error message would make 
the error message make sense.
Maxim
12-Oct-2010
[5223]
thx  :-)
BrianH
12-Oct-2010
[5224x3]
For instance, when I needed to come up with the right error to trigger 
when a function refinement was incompatible with the datatype of 
another argument, there wasn't an explicit error for that. But after 
looking through the catalog, I came up with this:
>> cause-error 'script 'cannot-use [load-module/as block!]
** script error: cannot use load-module/as on block! value
It will do until there is a better error for that situation.
CAUSE-ERROR is mezzanine in R3 and 2.7.7, so just source it :)
Gregg
12-Oct-2010
[5227]
Could the above notes be added to cause-error docs?
BrianH
12-Oct-2010
[5228]
Sounds like a good idea.
Maxim
12-Oct-2010
[5229]
yes, that would be a good first clue, since the current docs give 
no indication on how to proceed right now... 


I should have sourced cause-error, and I usually do... but this time 
well... I guess I assumed it was a native  :-)
BrianH
12-Oct-2010
[5230]
First thing I do when wondering about a function is HELP it. That 
tells me the basics, and also mentions its datatype.
Maxim
12-Oct-2010
[5231x2]
yep.
step 2 is source it  ;-)
BrianH
12-Oct-2010
[5233x2]
Yup :)
Step three is experiments at the console, calling it with test data.
Maxim
12-Oct-2010
[5235]
Q:  does reflect unbind the blocks it returns?
BrianH
12-Oct-2010
[5236]
It unbinds function code blocks, but intentionally binds object word 
blocks.
Maxim
12-Oct-2010
[5237x3]
is there a way to get a bound copy of a function's body?  sometimes, 
its nice to be able to figure out why a sub-function isn't doing 
what its supposed to...


this could be subject to protection schemes... so that a protected 
member cannot be shown via its function body.
this is also true of the stack function... it should not cross any 
protection... since doing so reveals what *it* calls...
(though I'm not saying it currently does just raising up the issue 
if it wasn't planned already)
Andreas
12-Oct-2010
[5240x2]
http://www.rebol.com/r3/docs/functions/cause-error.html
I took Brian's notes from above and edited some basic CAUSE-ERROR 
docs around them.
BrianH
12-Oct-2010
[5242x2]
No bound copy of a function body, for security reasons. The kind 
of hot-patching that was possible in R2 was always a security hole. 
Plus, it's not task-safe. For that matter, BODY-OF always returns 
a copy or constructed value, never the original, and code that currently 
uses it relies on this.
BODY-OF doesn't return the original for objects or modules either.
Maxim
12-Oct-2010
[5244x2]
the copy I don't mind... that's cool, its the fact that it always 
unbinds (which is what you seem to say).  its not a security hole 
if the functions aren't hidden or protected in some way.


I just want to know what a function within a function actually is 
calling... if its unbound... well I can't make any real inspection 
tool or debugger... right now I can go a lot further than R2, except 
this ... unless I didn't properly understand you.
its a bit like a dll, you only have access to the dll within a debugger 
if it was compiled with debugging... I'd like that to still be the 
case within rebol.
BrianH
12-Oct-2010
[5246]
There are two ways of hiding values. The tricky way is to use PROTECT/hide 
on a publically visible context. The more common, easier way is to 
use contexts that aren't publically accesible. There is no way that 
a reflector can tell if a bound context is not accessible, but the 
unbind trick prevents that kind of hack. And since inaccesible contexts 
might contain private information like encryption keys that might 
not belong to the person running the R3 process, there is no security 
setting that can make this safe to not do.
Maxim
12-Oct-2010
[5247]
I just finished a very powerfull new version of the search tool... 
it now even allows you to search for any value, even unset!. ( I 
just did a search to find all unset words in the whole system and 
it works without a hitch... )


also, if some data in the system is a string, it tries to find a 
formed value of your search value inside of it:-)
Steeve
12-Oct-2010
[5248]
Maxim, I felt the same back In time. A tool like anamonitor is not 
anymore possible. (cry on my face)
BrianH
12-Oct-2010
[5249]
But DRM is. Whether you consider that an advantage or not though...
Maxim
12-Oct-2010
[5250]
well, we can, but its severely limits debugging and frankly there 
is a way to do .   any context should have the possibility of having 
a private/public flag on it... its that simple. whenever you try 
to reflect a private context, it returns unset! (unbound) values.
BrianH
12-Oct-2010
[5251]
It is assumed that people doing debugging have access to the source. 
And in the case of source written in REBOL, that is likely the case 
now.
Steeve
12-Oct-2010
[5252]
Though debuging the source and a runtime session, is not the same 
thing.
Maxim
12-Oct-2010
[5253x2]
but you cannot resolve the run-time in data. since things are bound 
dynamically.  the name of a func is useless... we need to be able 
to trace it back to its context by getting its value.


this doesn't give us the context, but at least we can see what the 
function really is.
if things really need to be private, then anything which comes from 
a private context could just be flagged as such and inspection routines 
wouldn't return their values.