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

World: r3wp

[Core] Discuss core issues

BrianH
27-Jan-2010
[15709x4]
There aren't many native changes in R3 except architectural: R3's 
main changes:

- Fixes the off-by-one error for PICK and POKE (and path indexes) 
of non-positive indexes

- Ordinal functions now return #[none] on out-of-bounds rather than 
throwing an error
- Expansion of capabilities of FOREACH, subjects of SELECT

- Datatype conversion changes, mostly minor except to/from binaries

- Removed "features" that were more trouble than they were worth, 
and have been replaced by new features (backported)

- Removed features that haven't been replaced yet (like [throw] function 
attributes)
- Major changes in the port and GUI models and PARSE
Note that the off-by-one error of AT with non-positive indexes probably 
won't be fixed.
CureCode dismissed tickets are a good place to start - most of those 
were requests for R2 compatibility where inappropriate.
I apologize - most of the CureCode dismissed tickets are requests 
by meijeru for consistency. Only some are compatibility requests.
Maxim
28-Jan-2010
[15713]
is there a listing of changed natives?  I rarely find that they make 
things better, if they change the api of a function.
BrianH
28-Jan-2010
[15714x2]
There hasn't yet been a final list, but someone (probably me) should 
go through CureCode and make a draft list in DocBase. And there's 
the change list for the releases too, though that is mostly CureCode 
references.
Almost all of the changes have been for the better, though some were 
mostly for greater consistency. Changing the API is OK if the old 
one was really bad, and if there is a rationale for having any change 
be OK. For instance, changes are much more restricted in new R2 releases 
since the continuing existence and development of R2 is the justification 
for allowing the more radical changes in R3.
Maxim
28-Jan-2010
[15716x2]
if it means I have to revise 5 MB of code, any change isn't welcome 
 ;-)
unless I have a  precise list of changes so I can quickly detect 
side-effects.
BrianH
28-Jan-2010
[15718]
In theory, the combined test suite and combined docs should tell 
you the differences. When I get the time I can compile a list of 
relevant CureCode tickets.
Maxim
28-Jan-2010
[15719x2]
We really need a simple list of changes compiled in a single file, 
I have no clue how and when the process of 2.7.7 occured, and really, 
I've got A LOT of other "cats to whip".


FYI, this not a negative comment, just stating that unless someone 
builds a (similar to prior versions) simple list of all changes, 
I won't be able to use 2.7.7... as previous versions have bitten 
me, I can't risk running code in an untrusted environment... I feel 
others with serious tools and services might feel the same..  a single 
little change change cause havoc like data destruction which is only 
apparent, once the process is done.
(same for 2.7.8) 


the point being that all the effort going into it ends up being wasted 
on the most serious users.
BrianH
28-Jan-2010
[15721]
There were no changes in 2.7.7 that would cause semantic blowups, 
unless your code would fail when any of the new words are defined. 
The same will be the case with 2.7.8 (except the LATIN1? and ASCII? 
functions will no longer work poorly). I was just waiting for Carl 
to get done with the web site changes so there would be a place to 
put the release notes - they're already in the blog comments.
Maxim
28-Jan-2010
[15722]
ok, perfect.
BrianH
28-Jan-2010
[15723]
The blog comments here: http://www.rebol.com/cgi-bin/blog.r?view=0447#comments
BrianH
30-Jan-2010
[15724x11]
Here's the source to the new 2.7.8 functions that were posted earlier 
today, for those who haven't seen it on chat. I'm posting one function 
per message so bear with me for a sec. Not posting them in !REBOL2 
because that is just for release discussion.
; Fake immediate! and internal! typesets, for documentation
immediate!: reduce [

 none! logic! integer! decimal! money! char! pair! tuple! time! date!
	datatype! word! set-word! get-word! lit-word! refinement! event!
] ; percent! typeset!
internal!: reduce [end! unset! symbol!] ; frame! handle!
resolve: func [

 "Copy context by setting values in the target from those in the source."
	[catch]
	target [object! port!]
	source [object! port!]

 /only from [block! integer!] "Only specific words (exports) or new 
 words in target (index to tail)"

 /all "Set all words, even those in the target that already have a 
 value"
][
	either only [
		from: either integer? from [

   ; Only set words in the target positioned at the number from or later
			unless positive? from [throw-error 'script 'out-of-range from]
			intersect words-of source at words-of target from
		] [

   ; Only set the words in the target that are also in the from block
			intersect words-of source intersect words-of target from
		]
		foreach word from pick [

   [unless value? in target word [error? set/any in target word get/any 
   word]]
			[error? set/any in target word get/any word]
		] not all ; See below for what this means
	] [

  either all [ ; Override all target words even if they have values
			error? set/any bind words-of source target get/any source
		] [ ; Only set target words if they aren't yet set
			foreach word intersect words-of source words-of target [

    unless value? in target word [error? set/any in target word get/any 
    word]
			]
		]
	]
	also target set [source target from] none
]
; Note: This is native in R3 and supports module! too.

; Implementation note: INTERSECT returns the values from its first 
argument,

; and WORDS-OF returns a block of words that are bound to its argument, 
so
;     intersect words-of source words-of target
; returns a block of words bound to source.
single?: funco [
	"Returns TRUE if the series length is 1."

 series  [series! port! tuple! bitset! struct!] ; map! object! gob! 
 any-word!
][1 = length? :series]

; Note: Type spec same as LENGTH?, which also supports the extra 
types in R3
collect-words: func [

 "Collect unique words used in a block (used for context construction)."
	block [block!]
	/deep "Include nested blocks"
	/set "Only include set-words"
	/ignore "Ignore prior words"
	words [object! port! block!] "Words to ignore"
	/local rule word blk w
][

 deep: either deep [[path! | set-path! | lit-path! | into rule]] [any-block!]
	word: either set [set-word!] [any-word!]
	blk: []
	parse block rule: [
		set w word (insert tail blk to-word to-string w) | deep | skip
	]
	also either ignore [
		unless block? words [words: words-of words]
		difference blk intersect blk words
	] [
		unique blk
	] (clear blk set [block words] none)
]
; Note: In R3 this is native, called by MAKE OBJECT!

;   The words are not supposed to be bound, thus the to-word to-string.
ascii?: funct [

 "Returns TRUE if value or string is in ASCII character range (below 
 128)."
	value [string! file! email! url! tag! issue! char! integer!]
] compose [
	ascii: (charset [#"^(00)" - #"^(7F)"])

 either any-string? value [parse/all/case value [any ascii]] [value 
 < 128]
]
; Note: Native in R3.
latin1?: func [

 "Returns TRUE if value or string is in Latin-1 character range (below 
 256)."

 value [string! file! email! url! tag! issue! char! integer!] ; Not 
 binary!
][ ; R2 has Latin-1 chars and strings
	either integer? value [value < 256] [true]
]

; Note: Native (and more meaningful) in R3. For forwards compatibility.
invalid-utf?: funct [

 "Checks for proper UTF encoding and returns NONE if correct or position 
 where the error occurred."
	data [binary!]
	/utf "Check encodings other than UTF-8"
	num [integer!] "Bit size - positive for BE negative for LE"
] compose [
	ascii: (charset [#"^(00)" - #"^(7F)"])
	utf8+1: (charset [#"^(C2)" - #"^(DF)"])
	utf8+2: (charset [#"^(E0)" - #"^(EF)"])
	utf8+3: (charset [#"^(F0)" - #"^(F4)"])
	utf8rest: (charset [#"^(80)" - #"^(BF)"])
	switch/default any [num 8] [
		8 [ ; UTF-8
			unless parse/all/case data [(pos: none) any [
				pos: ascii | utf8+1 utf8rest |
				utf8+2 2 utf8rest | utf8+3 3 utf8rest
			]] [as-binary pos]
		]
		16 [ ; UTF-16BE
			pos: data
			while [not tail? pos] [
				hi: first pos
				case [
					none? lo: pick pos 2 [break/return pos]
					55296 > w: hi * 256 + lo [pos: skip pos 2]  ; #{D800}
					57343 < w [pos: skip pos 2]  ; #{DFFF}
					56319 < w [break/return pos]  ; #{DBFF}
					none? hi: pick pos 3 [break/return pos]
					none? lo: pick pos 4 [break/return pos]
					56320 > w: hi * 256 + lo [break/return pos]  ; #{DC00}
					57343 >= w [pos: skip pos 4]  ; #{DFFF}
				]
				none
			] ; none = valid, break/return pos = invalid
		]
		-16 [ ; UTF-16LE
			pos: data
			while [not tail? pos] [
				lo: first pos
				case [
					none? hi: pick pos 2 [break/return pos]
					55296 > w: hi * 256 + lo [pos: skip pos 2]  ; #{D800}
					57343 < w [pos: skip pos 2]  ; #{DFFF}
					56319 < w [break/return pos]  ; #{DBFF}
					none? lo: pick pos 3 [break/return pos]
					none? hi: pick pos 4 [break/return pos]
					56320 > w: hi * 256 + lo [break/return pos]  ; #{DC00}
					57343 >= w [pos: skip pos 4]  ; #{DFFF}
				]
				none
			] ; none = valid, break/return pos = invalid
		]
		32 [ ; UTF-32BE
			pos: data
			while [not tail? pos] [
				if any [
					4 > length? pos
					negative? c: to-integer pos
					1114111 < c  ; to-integer #{10FFFF}
				] [break/return pos]
			]
		]
		-32 [ ; UTF-32LE
			pos: data
			while [not tail? pos] [
				if any [
					4 > length? pos

     negative? c: also to-integer reverse/part pos 4 reverse/part pos 
     4
					1114111 < c  ; to-integer #{10FFFF}
				] [break/return pos]
			]
		]
	] [
		throw-error 'script 'invalid-arg num
	]
]

; Note: Native in R3, which doesn't support or screen the /utf option 
yet.

; See http://en.wikipedia.org/wiki/Unicodefor charset/value explanations.
; Aliases copied from R3 mezz-file
ls: :list-dir
pwd: :what-dir
rm: :delete
mkdir: :make-dir

cd: func [
	"Change directory (shell shortcut function)."
	[catch]

 'path [file! word! path! unset! string! paren!] "Accepts %file, :variables 
 and just words (as dirs)"
][

 ; Workaround for R3 change in lit-word! parameters with paren! arguments
	if paren? get/any 'path [set/any 'path do path] 
	switch/default type?/word get/any 'path [
		unset! [print what-dir]
		file! [change-dir path]
		string! [change-dir to-rebol-file path]
		word! path! [change-dir to-file path]

 ] [throw-error 'script 'expect-arg reduce ['cd 'path type? get/any 
 'path]]
]

more: func [
	"Print file (shell shortcut function)."
	[catch]

 'file [file! word! path! string! paren!] "Accepts %file, :variables 
 and just words (as file names)"
][

 ; Workaround for R3 change in lit-word! parameters with paren! arguments
	if paren? :file [set/any 'file do :file] 
	print read switch/default type?/word get/any 'file [
		file! [file]
		string! [to-rebol-file file]
		word! path! [to-file file]

 ] [throw-error 'script 'expect-arg reduce ['more 'file type? get/any 
 'file]]
]
So there we are, by request. Any comments?
Any FUNCO references were left over from R2/Forward, from which this 
source was copied. It was changed to FUNC in R2.
Henrik
31-Jan-2010
[15735x2]
LS won't work the same on R2 as in R3, AFAIR?
sorry, that woulc be CD and it seems it might work.
Graham
31-Jan-2010
[15737]
would be nice if we can the sdk to 2.7.7 ...
Will
31-Jan-2010
[15738x2]
what about a mv function where the target isn't relative to the origin? 
would be nice
if it's of use and Dock agree, this function has just been added 
to latest cheyenne svn:
relative-path: func [src dst /local i][
		src: remove parse src "/"
		dst: remove parse get-modes dst 'full-path "/"
		if src/1 <> dst/1 [return none]					;-- requires same root

		i: 1 + length? src 
		repeat c i - 1 [if src/:c <> dst/:c [i: c break]]	
		dst: to-file at dst i
		src: at src i
		if not tail? src [loop length? src [insert dst %../]]
		dst
	]
Henrik
31-Jan-2010
[15740]
I think we already have something like this. It's called TO-RELATIVE-FILE.
Will
31-Jan-2010
[15741]
Thanks Henrik, I wasn't aware, is this recent? still a mv function 
would be nice to have
Henrik
31-Jan-2010
[15742x3]
I wrote it, I think, 2-3 years ago. BrianH refined it for R2-Forward 
and R3.
As I recall, MV isn't possible due to limitations in R2 ports, but 
I may be wrong. You would have to load the entire file into memory 
and save it at the destination. If there already is a MV function, 
then I'm wrong.
It seems that R3 doesn't have a MV function. RENAME can't be used 
for it.
Will
31-Jan-2010
[15745x3]
as you can rename from one directory to another with a relative target, 
the mv would only need the target to be converted to relative to 
origin and it should work, no?
to-relative-file works only one way, not good
what-dir
;   %/Users/alpha/
  to-relative-file %/Users/alpha/Pictures/IMG_0003.JPG
;   %Pictures/IMG_0003.JPG
  to-relative-file %/Users/                           
;   %/Users/		;this should be %../
Henrik
31-Jan-2010
[15748x3]
seems that BrianH has changed it a lot. I wanted to compare a specific 
source and destination.
From the help:

Returns the relative portion of a file if in a subdirectory,
So it seems to work as advertised, but this isn't enough.
Will
31-Jan-2010
[15751x2]
althought the definition is right "Returns the relative portion of 
a file if in a subdirectory, or the original if not." the function 
name would have suggested to me that in the secon case I get a %../ 
but no
secon -> second
Henrik
31-Jan-2010
[15753x3]
Will, this is the one I did:

get-path: func [
  "Calculates the relative path between two directories."
  p1 p2 /local i p3
] [
  p1: clean-path p1
  p2: clean-path p2
  p3: copy %""
  until [
    any [
      find/match p2 p1
      not p1: first split-path p1
      not append p3 %../
    ]
  ]
  append p3 find/match p2 p1
  either p3 = %"" [%./][p3]
]
hmm... there's some useful stuff here.
http://rebol.hmkdesign.dk/files/file-utilities.r
BrianH
31-Jan-2010
[15756x3]
Yeah, sorry, TO-RELATIVE-FILE doesn't do full relative, it's mostly 
a variant of CLEAN-PATH. I wrote the R2/Forward version for use in 
DevBase 2, included it in 2.7.6, then ported it to R3. It's one of 
the two functions where the flow went the other way (IN-DIR being 
the other).
It wasn't based on any preexisting function (not even yours, Henrik), 
it was in response to a real need of REBOL apps, particularly DevBase, 
where the base path is the app path. Carl considered it useful enough 
to include in 2.7.6, same as IN-DIR.
It was originally used to clean up saved file/directory preferences, 
where the default app behavior follows the portable app model: Data 
and settings going in subdirectories of the app directory. If they 
aren't subdirectories, they're absolute paths.