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

World: r3wp

[rebcode] Rebcode discussion

BrianH
17-Oct-2005
[500]
Of course you can put the rewrite part in a different function and 
save the compare/either if you want.
Volker
17-Oct-2005
[501x2]
Another alternate syntax:
find-last-other: rebcode[s c /local c2 eq? f] probe altsyn [
 s: tail back
 while[ 
  c2: pick s 1 eq c 
  eq?: gett
  f: gett ift[ head? s f: gett not ] sett f
 ] [
  s: back
 ] 
 sett eq? either [return none][return s] 
]
BrianH
18-Oct-2005
[503x2]
OK Volker, what would that code mean in REBOL do or rebcode dialects? 
I'm having a little trouble getting it. Translate!
Is it equivalent to (indented for my clarity)


find-last-other: rebcode [s [block!] c [integer!] /local c2 eq f] 
[
    tail s
    back s
    while [
        pick c2 s 1
        eq c c2
        gett eq?
        gett f
        ift [
            head? s
            gett f
            not f
        ]
        sett f
    ] [
        back s
    ]
    sett eq?
    either [return none] [return s]
]
Pekr
18-Oct-2005
[505]
Please look into latest Blog article, which is rebcode related. RT 
invites us for last round of suggestions, as after the release, another 
suggestions would have to wait several months ....
BrianH
18-Oct-2005
[506]
On that note, a request: Please integrate the HERE (or OFFSET, you 
decide) directive I requested, RAMBO 3924. This will make BRAW useful 
for handwritten code; right now BRAW is only practical for compiler-generated 
code with no user-defined rewrite rules, because of the offset calculations 
required.
Pekr
18-Oct-2005
[507]
not sure if we should not use different Chnnel? Which one, as we 
will chat here, our request will scroll-off ....
BrianH
18-Oct-2005
[508x7]
Well, it's already in RAMBO.
BTW, I figured something out and am writing it up. I'll post it when 
it's ready.
I found an advantage to the new opcode-always-first syntax of rebcode 
that hadn't occured to me before, while examining the source of the 
assembler.


With the old assembly syntax, the binding of the opcodes to the internal 
rebcodes object was performed by a bind of the whole code block, 
and all subblocks (except fot the do blocks). This bind was performed 
to all words, including those used as arguments and variables. Because 
of this the assembly opcodes were essentially keywords that could 
not be used as variables or as the names of externally referenced 
values like the functions called by apply. This made it very difficult 
to integrate with external code. Also, since more opcodes are being 
added all the time, your parameters and other variables could end 
up converted to keywords in future revisions of the VM and your code 
could stop working.


Now, all opcodes are the first word in a statement, no keywords are 
anywhere else in rebcode statements and the every statement starts 
with an opcode. The assembler is able to just bind the first word 
in each statement to the rebcodes object during the syntax check, 
and to simply reject any statement that isn't valid syntax, including 
invalid opcodes. You can even use the opcode words as variables in 
your code, or refer to external values by those names without any 
difficulty. This simplified syntax would be easier to execute as 
well.


The implication of this is that rebcode is now a strict statement-based 
dialect, instead of an expression-based one like the do dialect. 
The advantage to this is that you can always tell where a statement 
begins, where it ends, and what it is operating on. This kind of 
code is easy to follow and quick to execute. It can be trickier to 
write though, as you have to decompose those expressions you are 
used to writing into their component parts.
Fortunately, this kind of code is easy to generate as well. The rewriter 
can do some basic transforms to make the syntax that you write easier 
for you. For example, Volker's suggested alternate syntax (to my 
best guess of what he meant) could be implemented with something 
like this:

use [dest here rule r1 r2 r3 rs0 rs1 rs2 rs3] [

    foreach rule [r1 r2 r3 rs0 rs1 rs2 rs3] [set rule make block! 10]
    insert rs1 ['label word! | '?? word |]
    parse rebcode*/opcode-rule [
        some [here: lit-word! [
            '| (
                insert tail rs0 reduce [here/1 '|]
            ) |
            'word! '| (

                unless find rs1 here/1 [insert tail r1 reduce [here/1 '|]]
            ) |
            'word! [block! | word!] '| (

                unless find rs2 here/1 [insert tail r2 reduce [here/1 here/3 '|]]
            ) |
            'word! [block! | word!] [block! | word!] '| (

                unless find rs3 here/1 [insert tail r3 reduce [here/1 here/3 here/4 
                '|]]
            ) |
            into ['integer! '| 'word! | 'word! '| 'integer!] [
                '| (
                    insert tail r1 reduce [here/1 '|]
                    insert tail rs1 reduce [here/1 'integer! '|]
                ) |
                [block! | word!] '| (
                    insert tail r2 reduce [here/1 here/3 '|]

                    insert tail rs2 reduce [here/1 'integer! here/3 '|]
                )
            ]
            [block! | word!] [
                '| (
                    insert insert tail rs1 copy/part here 2 '|
                ) |
                [block! | word!] [
                    '| (

                        insert insert tail rs2 copy/part here 3 '|
                    ) |
                    [block! | word!] '| (

                        insert insert tail rs3 copy/part here 4 '|
                    )
                ]
            ]
        ]]
    ]

    foreach rule [r1 r2 r3 rs0 rs1 rs2 rs3] [clear back tail get rule]
    rule: [

        set dest set-word! here: r1  #==> (here/1) (to-word dest) (dest) 
        .

        set dest set-word! here: r2  #==> (here/1) (to-word dest) (here/3) 
        (dest) .

        set dest set-word! here: r3  #==> (here/1) (to-word dest) (here/3) 
        (here/4) (dest) .
        set dest set-word! here: rs0 #==> (here/1) (dest) .

        set dest set-word! here: rs1 #==> (here/1) (here/2) (dest) .

        set dest set-word! here: rs2 #==> (here/1) (here/2) (here/3) (dest) 
        .

        set dest set-word! here: rs3 #==> (here/1) (here/2) (here/3) (here/4) 
        (dest) .
        set dest set-word! #==> .
    ]
    rebcode-define rule
]
Well Volker, what do you think of your alternate syntax? Note that 
opcodes that take any-type! instead of word! in their first parameter 
don't get their parameter abstracted out, and how easy it is to add 
exceptions. The direct branches might be a good idea to skip rather 
than abstracting the word and skipping the integer, but you can decide 
for yourself.
I'll check back here later - time to sleep :)
Here's a refined and commented version:

use [dest here rule r1 r2 r3 rs0 rs1 rs2 rs3] [
    ; Initialize the new rules

    foreach rule [r1 r2 r3 rs0 rs1 rs2 rs3] [set rule make block! 10]
    ; Set the exceptions
    insert rs1 ['label word! | '?? word |]
    ; Build the new rules based on the standard rules
    parse rebcode*/opcode-rule [
        ; Note: Opcodes currently take at most 3 parameters
        some [here: lit-word! [
            '| (
                insert tail rs0 reduce [here/1 '|]
            ) |
            'word! '| (

                unless find rs1 here/1 [insert tail r1 reduce [here/1 '|]]
            ) |
            'word! [block! | word!] '| (

                unless find rs2 here/1 [insert tail r2 reduce [here/1 here/3 '|]]
            ) |
            'word! [block! | word!] [block! | word!] '| (

                unless find rs3 here/1 [insert tail r3 reduce [here/1 here/3 here/4 
                '|]]
            ) |
            into ['integer! '| 'word! | 'word! '| 'integer!] [
                '| (
                    unless find rs1 here/1 [
                        insert tail r1 reduce [here/1 '|]

                        insert tail rs1 reduce [here/1 'integer! '|]
                    ]
                ) |
                [block! | word!] '| (
                    unless find rs2 here/1 [
                        insert tail r2 reduce [here/1 here/3 '|]

                        insert tail rs2 reduce [here/1 'integer! here/3 '|]
                    ]
                )
            ]
            [block! | word!] [
                '| (
                    insert insert tail rs1 copy/part here 2 '|
                ) |
                [block! | word!] [
                    '| (

                        insert insert tail rs2 copy/part here 3 '|
                    ) |
                    [block! | word!] '| (

                        insert insert tail rs3 copy/part here 4 '|
                    )
                ]
            ]
        ]]
    ]
    ; Clear the trailing | from each new rule

    foreach rule [r1 r2 r3 rs0 rs1 rs2 rs3] [clear back tail get rule]
    ; Define the new rewrite rules and install them

    ; Note: A set-word establishes the default word parameter. The rules

    ;       convert this to an explicit parameter one opcode at a time.
    rebcode-define [

        set dest set-word! here: r1  #==> (here/1) (to-word dest) (dest) 
        .

        set dest set-word! here: r2  #==> (here/1) (to-word dest) (here/3) 
        (dest) .

        set dest set-word! here: r3  #==> (here/1) (to-word dest) (here/3) 
        (here/4) (dest) .
        set dest set-word! here: rs0 #==> (here/1) (dest) .

        set dest set-word! here: rs1 #==> (here/1) (here/2) (dest) .

        set dest set-word! here: rs2 #==> (here/1) (here/2) (here/3) (dest) 
        .

        set dest set-word! here: rs3 #==> (here/1) (here/2) (here/3) (here/4) 
        (dest) .
        set dest set-word! #==> .
    ]
]
Volker
18-Oct-2005
[515x2]
Yes Brian, you got it right. A set-word is the first argument to 
all following instructions. I am not about it. Its more like expressions, 
Makes gouping easier imho, like 
 string-char: pick string 1 eq char
instead of
 pick string-char string 1
 eq string-char char

My experimtens:  http://polly.rebol.it/test/test/rebcode/altsyn1.r
. Have to look into Gabs rewrite-rules. http://polly.rebol.it/test/test/rebcode/altsyn1.r
about
  insert [] 1
would be
  [] insert 1
a bit like smalltalk-syntax.
BrianH
18-Oct-2005
[517x2]
I think it is a bit more difficult to understand, but it made for 
a good experiment in rebuilding the standard opcode rules. That code 
framework will come in handy for me later.
By the way, I showed my father both dialects, yours and the current 
assembler. I had to explain what yours was doing; the standard dialect 
he just got, although he asked what a few of the opcodes meant. He's 
not a programmer (at least not recently) so that speaks well for 
the readability of the rebcode dialect.
Oldes
18-Oct-2005
[519x3]
How to traverse with series in rebcode? I wanted to make ucs2 encoder 
using rebcode but found out, that I'm not able to traverse the series 
by 2 chars
x: rebcode[str][copy s2 str -1 until [copy s s2 2 print s next s2 
tail? s2]] x "abcdefgh"
gives error
BrianH
18-Oct-2005
[522]
skip str 2
Oldes
18-Oct-2005
[523x6]
that's the same error
that was just a quick example
And other thing is, that I'm still missing better binary support
for example:
>> to-integer #{FF00}
== 65280
>> x: rebcode[][set b #{FF00} to-int i b print i] x
== 0
that's no good:( I cannot use rebcode to speed up any from my RSWF 
dialect functions as all of them are base on dealing with datatypes 
like UI16 UI32 SI16 SI32, FP and other which simply Rebol do not 
support:(
BrianH
18-Oct-2005
[529]
Are deciding that REBOL is bigendian? What about when it runs on 
x86 machines?
Oldes
18-Oct-2005
[530x4]
what about to add some options switch?
if I want to make binary structure, I now what binary type it is
and I want to make binaries all the time:(
event in the UTF8 you can specify if it is bigendian in the first 
bytest of the text
BrianH
18-Oct-2005
[534]
I tend to use struct! for that, when available. That is what I suggested 
struct! in REBOL/Core, and they agreed but haven't implemented it 
yet. I'm hoping for 2.7.0 :)
Oldes
18-Oct-2005
[535x5]
Me as well, but that is only for signed integers
Most of the time I have to use these ugly functions:
ints-to-sbs: func[

 ints [block!]	 "Block of integers, that I want to convert to SBs"

 /complete l-bits "Completes the bit-stream => l-bits stores the nBits 
 info of the values"
	;/maxb mb
	/local b b2 l bits sb
][
	ints: reduce ints
	max-bits: 0
	bits: make block! length? ints
	foreach i ints [
		;b: enbase/base load rejoin ["#{" to-hex i "}"] 2
		b: enbase/base head reverse int-to-ui32 i 2
		b: find b either i < 0 [#"0"][#"1"]
		b: copy either none? b [either i >= 0 ["00"]["11"]][back b]
		;insert b either i >= 0 [#"0"][#"1"]
		if max-bits < l: length? b [max-bits: l]
		append bits b
	]
	foreach b bits [
		if max-bits > l: length? b [
			insert/dup b b/1 max-bits - l
		]
	]
	either complete [
		sb: int-to-bits max-bits l-bits
		foreach b bits [insert tail sb b]
		sb
	][	
		bits
	]
]

int-to-FB: func[i /local x y fb][
	x: to integer! i
	y: to integer! (either x = 0 [i][i // x]) * 65535

 fb: rejoin [either x = 0 ["0"][first ints-to-sbs to block! x] int-to-bits 
 y 16]
	if all [x = 0 i < 0][fb/1: #"1"]
	fb
]
Unfortunately I'm not able to do it in Rebcode:(
Never mind, I will wait, maybe one day it will come.
BrianH
18-Oct-2005
[540x5]
In the meanwhile, ou can do it yourself:

pickz hi b 0
pickz lo b 1
lsl hi 8
add hi lo
skip b 2
for bigendian
Better yet, change the add to or, it should be faster.
Less likely to cause problems with large unsigned numbers too, it 
you are implementing unsigned int32s.
What are you trying to do with that function? I'm having a little 
trouble understanding its purpose, though I seem to get most of the 
parts.
Pekr
18-Oct-2005
[545x2]
Oldes - put it in RAMBO - or just guys let's decide what channel 
will we use for last-minute suggestions! Remember - if you don't 
get your desired functionality now, your wait might be quite long 
...
And posting your code here I can guarantee you, that Carl will not 
scroll thru them ;-)
BrianH
18-Oct-2005
[547]
The code I've posted here recently is for you all. I've posted the 
request code to RAMBO.
Pekr
18-Oct-2005
[548]
My suggestion goes mainly to Oldes now, who wishes to have rebcode 
supporting binary datatype and ability to switch endianness .....
Geomol
18-Oct-2005
[549]
In rebcode, the pick opcode can be used with both binaries and images. 
If you have an image, it's rgb values can be reached as image/rgb, 
and that is a binary serie. Each value is 0-255, and you then have 
to multiply the index by 3 and use an offset to reach the red, green 
or blue component of a pixel. It's also possible to work on the image 
as an image! datatype, and then it's not necessary to multiply the 
index by 3, as the full pixel is addressed, but the value isn't a 
tuple, as we're used to, but the binary version of a tuple as an 
integer. E.g. green (0.255.0 or #{00ff00}) is 65'280.


Now to my questions. Are there shortcuts or tricks to make it easier 
to work with pixel-valus in rebcode? Should it be possible to use 
tuples, or will that slow things down too much? What do others do?