World: r3wp
[rebcode] Rebcode discussion
older newer | first last |
Pekr 17-Oct-2005 [489] | shadwolf - the nice thing is, that for specific domain, you can create your own sub-language using parse and let it generate rebcode for you :-) |
BrianH 17-Oct-2005 [490] | For some kinds of coding I would actually find rebcode to be a more comfortable dialect. For instance, you don't have to worry about whether someone has redefined add. |
Pekr 17-Oct-2005 [491] | shadwolf - really no reason to use it on a daily basis, but cool to have for fast tasks - without it real-time image manipulation in rebol was impossible for e.g.! |
BrianH 17-Oct-2005 [492x2] | At least in this case, you can count on any crashes or security holes being your fault instead of someone else's. |
Kaj, I have found myself amost writing brat and barf many times already. I guess my inner child has a dirty mind :) | |
shadwolf 17-Oct-2005 [494x2] | yea i know the complain message (1st one ) what for joking ^^ |
things like list sorting in widgets like table or listview in rebgui could profit form rebcode optimisation | |
BrianH 17-Oct-2005 [496x5] | On the note of people redefining stuff out from under you, here's a quick redefine that can make the user-defined rewrite rules a little safer: rebcode: func [ "Create and return a rebcode VM function." args [block!] body [block!] /rewrite rules [block!] ][ either rewrite [ rewrite: tail rebcode*/userdef-rule rebcode-define rules make rebcode! args body clear rewrite ] [ make rebcode! args body ] ] |
It uses internal features, and so may have to be adjusted features as the assembler is refined. | |
Sorry, it uses internal features, and so may have to be adjusted as the assembler is refined. | |
Whoops, slight adjustment needed :( rebcode: func [ "Create and return a rebcode VM function." args [block!] body [block!] /rewrite rules [block!] ][ either rewrite [ rewrite: tail rebcode*/userdef-rule rebcode-define rules body: make rebcode! args body clear rewrite :body ] [ make rebcode! args body ] ] | |
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 [535x4] | 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:( | |
older newer | first last |