by strick

Can we get a peek at CRPL?

Sure. Sorry there's no documetation.

http://www.yak.net/strick/crpl.tcl.2000-02-01.txt

(there may be some errors due to lack of esacaping < & > .... maybe you should 'view source' and copy from there)

# crpl.tcl
#
# Routines for minimizing typing in tcl
#
# Author: strick
#
# Date: December, 1999

#
# crpl functions
#

if ![llength [info command common]] {
uplevel #0 {

proc crpl {} { return 2000-01-17 }

set crpl_common ""

proc common args {
	global crpl_common
	set crpl_common $args

	#foreach x $crpl_common { set a($x) 0 }
	#foreach x $args { set a($x) 0 }
	#set crpl_common [lsort [array names a]]
}

rename proc crpl_pre_common_proc

crpl_pre_common_proc proc {name vars body} {
	global crpl_common

	# optimize -- only global if appears
	set z {}
	foreach x $crpl_common {
		if [string match "*$x*" $body] {lappend z $x}
	}

	if [llength $z] {
		crpl_pre_common_proc $name $vars "[concat global $z];;; $body"
	} else {
		crpl_pre_common_proc $name $vars "$body"
	}
}

proc crpl_join {args} { join $args }

proc unk_equals {c args} {

	# short simple case:  var=cmd
	if [regexp -nocase {^([a-z0-9_]+)[=]([^=]*)$} $c 0 1 2] {
		if {$2==""} {
		  proc $c args " 
			upvar 1 [list $1] z
			set z \[join \$args \]
		  "
		} else {
		  set cmd [list [list $2]]
		  proc $c args "
			upvar 1 [list $1] z
			set z \[uplevel 1 $cmd \$args \]
		  "
		}
		return [ uplevel 1 [list $c] $args ]
	}


	# short simple case:  var(sub)=cmd
	if [regexp -nocase {^([a-z0-9_]+)[(]([a-z0-9_]*)[)][=]([^=]*)$} $c 0 1 2 3] {
		if {$3==""} {
		  proc $c args " 
			upvar 1 [list $1] z
			set z($2) \[join \$args \]
		  "
		} else {
		  set cmd [list [list $3]]
		  proc $c args "
			upvar 1 [list $1] z
			set z($2) \[uplevel 1 $cmd \$args \]
		  "
		}
		return [ uplevel 1 [list $c] $args ]
	}


	set v [split $c =]
	set n [llength $v]
	set cmd [lindex $v end]
	set z [uplevel 1 [list $cmd] $args]

	for {set i 0} {$i < $n - 1} {incr i} {
		set w [lindex $v $i]
		
		if {$w == ""} continue

		if {$n == 2} { # simple single var
			set x $z
		} elseif {$i == $n - 2} {
			set x [lrange $z $i end]
		} else {
			set x [lindex $z $i]
		}
		
		if [string match /* $w] {
			set level #0
			#set w [string range $w 1 end]
			regsub {^/} $w {} w
		} else {
			set level 1
		}

		switch -glob -- $w {
			"*+" {set op incr}
			"*|" {set op append}
			"*^" {set op lappend}
			"*@" {set op @}
			default {set op set}
		}

		if {$op != "set"} { # chop off extra char
			regsub {.$} $w {} w
		}

		if {$op != "@"} {
		  if [regexp {^([^()]*)[(](.*)[)]$} $w 0 1 2] {
			upvar $level $1 a
			$op a($2) $x	
		  } else {
			upvar $level $w a
			$op a $x	
		  }
		} else {
			upvar $level ${w}n an
			set an [llength $x]
			for {set j 0} {$j < $an} {incr j} {
				upvar $level ${w}$j a
				set a [lindex $x $j]
			}
		}
	}

	return $z
}

proc eval_parens_expr c {
	regsub -all {[A-Za-z_][A-Za-z0-9_]*} $c {$&} c
	regsub -all {[^<>!=][=](?![=])} $c {&=} c
	regsub -all {@([$][A-Za-z_][A-Za-z0-9_]*)} $c {[llength \1]} c
	regsub -all {#([$][A-Za-z_][A-Za-z0-9_]*)} $c {[string length \1]} c
	regsub -all {'[$]([A-Za-z_][A-Za-z0-9_]*)} $c {"\1"} c

	uplevel 1 [list expr $c]
}
proc () {args} {
	upvar 1 __cond__ m
	if $m {
		return ""
	} else {
		uplevel 1 $args
	}
}
proc unk_parens {c args} {
	if [llength $args] { 
		upvar 1 __cond__ m
		set b [ uplevel 1 [list eval_parens_expr $c] ]
		if { $b==0 || $b=="" } {
			set m 0
			return ""
		} else {
			set m 1
			uplevel 1 $args
		}
	} else {
		uplevel 1 [list eval_parens_expr $c]
	}
}
proc unk_tilde {c args} {
	regexp {[~](.*)} $c 0 f
	set z ""
	catch {set z [uplevel 1 [list $f] $args ]}
	return $z
}
proc unk_bquot {c args} {
	regexp {[`](.*)} $c 0 f
	#puts stderr [join [concat [list <<< $f ] $args]]
	puts stderr [concat [list <<< $f ] $args]
	if [set v [catch {uplevel 1 [list $f] $args} x]] {
		global errorCode errorInfo
		puts stderr ">ERROR>$v> ``$x''"
		error $x $errorInfo $errorCode 
	} else {
		puts stderr ">>> ``$x''"
	}
	return $x
}
proc unk_squot {c args} {
	regexp {['](.*)} $c 0 f
	set z [uplevel 1 [list $f] $args ]
	puts stderr "=== ``$z''"
	return $z
}
proc unk_bang {c args} {
	regexp {[!](.*)} $c 0 f
	set z [uplevel 1 [list $f] $args ]
	expr { $z=="" || $z==0 }
}
proc unk_assert {c args} {
	set z [uplevel 1 $args ]
	if !$z {
		error "ASSERTION FAILED: [expr {$c=="@"? $args: $c}]"
	}
}
proc unk_apos {c args} {
	set c [split $c ']
	uplevel 1 $c $args
}
proc unk_apos {c args} {
	set z {}
	foreach c [split $c '] {
		set s 0
		foreach c [split $c `] {
			if {$s} {
				lappend z [lindex $args end]
				set args [lrange $args 0 [expr {[llength $args]-2}]]
			}
			if { $c!="~"} {lappend z $c}
			set s 1
		}
	}
	uplevel 1 $z $args
}
proc unk_comma {c args} {
	regexp {^([-:\w]+)[,](.*)} $c 0 m f
	set z [uplevel 1 [list $f] $args ]
	uplevel 1 [list $m $z]
}
proc unk_li {c list} { 
	lindex $list $c 
}
proc unk_limi {c list} {
	regsub {.$} $c {} c
	lrange $list $c end
}
proc unk_mili {c list} {
	lindex $list [expr {[llength $list]+$c}]
}
		


proc metacrpl {pat cmd} {
	global metacrpl
	lappend metacrpl $pat $cmd
}
metacrpl {^[0-9]+$} unk_li
metacrpl {^[0-9]+-$} unk_limi
metacrpl {^-[0-9]+$} unk_mili
metacrpl {^[`]} unk_bquot
metacrpl {^[']} unk_squot
metacrpl {^[~]} unk_tilde
metacrpl {^[!]} unk_bang
metacrpl {^[@]} unk_assert
metacrpl {^([-:\w]+)[,](.*)} unk_comma
metacrpl {^[(].*[)]$} unk_parens 
metacrpl {^.*[=].*$} unk_equals 
metacrpl {^.*[`'].*$} unk_apos 


rename unknown crpl_pre_unknown
proc unknown {c args} {
	if {$c=="" || $c==":"} {
		join $args
	} else {
		global metacrpl
		set f crpl_pre_unknown
		foreach {p u} $metacrpl {
			if [regexp $p $c] { set f $u ; break }
		}
		uplevel 1 [list $f $c] $args
	}
}

#++ Aliases for rsi:
proc eq { a b } {
	expr { ![ string compare $a $b ] }
}	

proc ne { a b } {
	string compare $a $b
}	

proc zm { a b } {
	string match $a $b
}	

proc zl { a } {
	string length $a 
}	

proc l args { return $args }

proc ll { a } {
	llength $a 
}	

#-- b'th item of list a:
proc li { a b } {
	lindex $a $b
}	
proc zi { a b } {
	string index $a $b
}	

#-- Everything from b through c in list a:
proc lr { a b c } {
	lrange $a $b $c
}	
proc zr { a b c } {
	string range $a $b $c
}	

#-- Get the 0'th, first, 2nd item of list:
##	
##	proc 0  x {
##		lindex $x 0
##	}	
##	
##	proc 1  x {
##		lindex $x 1
##	}	
##	
##	proc 2  x {
##		lindex $x 2
##	}	
##	proc -1  x {
##		lindex $x end
##	}	
##	
##	#-- Get everything but the first:
##	proc 1-  x {
##		lrange $x 1 end
##	}	
##	
#-- Initialize variables to: 
#-- ('uplevel' - does it in scope of caller.)
#-- [n]ull string:
proc n args  {
	foreach x $args {
		uplevel 1 [ list set $x {} ]
	}
}	

#-- [z]ero string:
proc z args  {
	foreach x $args {
		uplevel 1 [ list set $x 0 ]
	}
}	

#-- [e]mpty hash (tcl calls it an array):
proc e args  {
	foreach x $args {
		catch { uplevel 1 [ list unset $x ] }
		uplevel 1 [ list set 	"[ get x ](0)" 0 ]
		uplevel 1 [ list unset "[ get x ](0)" ]
	}
}	

#-- more useful version of foreach:
#-- (sort of like perl map - really like lisp mapcar.)
# - v = vector (list of items) - cmd - command to execute on each.
#-- Returns a list of all the results.
proc map { v cmd } {
	set z {}
	foreach x $v {
		lappend z [ uplevel 1 $cmd [ list $x ] ]
	}
	return $z
}	

#-- Adding/multiplying/ANDing/whatever a list of numbers:
#-- zero = 0 ; op = +
proc reduce_dyadic { zero op list } {
	set z $zero
	foreach x $list {
		set z [ expr "\$z $op \$x" ]
	}
	return $z
}
#++ END carpal section.

# p {name args} - defines proc "name" with arguments "args"
#	(the last argument is the body of the procedure)
#
# Beginning an argument with certain characters causes special behavior:
#	^ promotes to the variable to the caller's scope
#	/ refers to the global variable by that name

proc p {name args} {
	n vars pre

	n=ll $args

	foreach x [lr $args 0 [(n-2)]] {
		switch -glob -- $x {
			^* {
				v=zr $x 1 end
				vars^= __name__$v
				pre|= " upvar 1 \$__name__$v $v ;;"
			}

			/* {
				v=zr $x 1 end
				pre|= "[list global $v];;"
			}

			* {
				vars^= $x
			}
		}
	}

	body=li $args end
	proc $name $vars $pre$body
}

proc pe args { 
	puts stderr "=== $args"
	return $args
}

proc ce args { # catch exception
	set z ""
	catch { set z [ uplevel 1 $args ] }
	return $z
}
proc i0 n { z=
	for {set i 0} {$i<$n} {incr i} {lappend z $i}
	return $z
}
proc io n { z=
	for {set i 1} {$i<=$n} {incr i} {lappend z $i}
	return $z
}

proc do args {
	puts stderr "<<< $args"
	if [set v [catch {uplevel 1 $args} x]] {
		global errorCode errorInfo
		puts stderr ">ERROR>$v> $x"
		error $x $errorInfo $errorCode 
	} else {
		puts stderr ">>> $x"
	}
	return $x
}
proc try {x y {z #}} {upvar 1 _ _
	set t [catch {uplevel 1 $x} _]
	
	### case 1 is not quite right -- need another catch!
	switch $t {
	0	{uplevel 1 $z; return $_}
	1	{uplevel 1 $z; uplevel 1 $y}
	2	{uplevel 1 $z; uplevel 1 {return $_}}
	3	{error BREAK-IN-TRY; break}
	4	{error CONTINUE-IN-TRY; continue}
	default	{error "try default"}
	}
}

}
}

crpl

#TESTS

if {$argv0 == "crpl.tcl"} {
do crpl
do crpl

do puts [(3+4)]

do a=b=c=z=list 1 2 3 4 5 6
do !ll $z
do !ll {}
do !list
do !list a b c
do !!list
do !!list a b c
do ll,list 
do ll,list a b c
do zl,list 
do zl,list a b c
do ll,zl,list a b c
do zl,zl,list a b c
do !ll,list a b c
do puts [(b*10)]
do puts [((a+b)*c)]
do a+=b^=c|==list 10 20 30 40 50
do puts [list $a $b $c $z]
do a@=list 11 12 13
foreach i [lsort,info var ] {
	if [zm err* $i] break
	puts "$i : [~($i)]"
	~parray $i
}


`w(1)=w(2)=w(3)=w(r,!x@,9)=list a b c d e f
`array get w 
`unset w
`w(1)=w(2)=w(3)=w(r,!x@,9)= "a b"
`array get w 
`unset w
`w(1)=w(2)=w(3)=w(r,!x@,9)=
`array get w 
ce `@ expr 0!=1
ce `@test expr 0!=1
ce `@ expr 0==1
ce `@test expr 0==1
`'`ce list a b c
~`continue
ce `break
ce `continue
ce `return 6
`try {a(x)= y} (8)
ce `foreach x [io 9] { try { if {$x==5} break ; pe $x } error }
`p c { try {return 5} {error} ; return 9}
`c
`x=do a=b=c=d=e==list 10 20 30 40 50
`(a)
`(c)
`(x)
`ll,(x)
`0,(x)
`0,0,(x)
`1,(x)
`-1,(x)
`1-,(x)
`1-,1-,(x)
`1-,1-,1-,(x)
`0,1-,1-,1-,(x)
~do error bogus
do (errorCode)
~do break
do (errorCode)
~do continue
do (errorCode)
~do return
do (errorCode)
~do return 3.14
do (errorCode)
do (a+b+c+@x+#x)
do z=pid
do z= pid
do z= pid 1 2 3 4
do z= pid {1 2} {3 4}
do z=
do z=!
do z=~!
```'do ce list a b c
`~`continue
`string'length xyz
`string'match'x* xyz
`string'match`xyz x*

`map {x* y* *y* z *z *} `string'match`xyz
`map {x* y* *y* z *z *} "`string'match`~ xyz"

`y= ok
`(c) (@x)
`(!c) (@x)
`(c-b-a) (@x)
`(!(c-b-a)) (@x)
`(c-b-a) (#x)
`(!(c-b-a)) (#x)
`(@x) ~error bogus
`~(@x) error bogus
`(y=='ok) (@x)
`() : not
`(y='ok) (@x)
`() : not
`(y!='ok) (@x)
`() : not

do common color size
proc a {} { set color red }
proc b {} { puts $color }
`a
`b
`p c { try {return 5} {error} ; return 9}
`c
`p d /y ^n a b { ` $y $n ; y^= $a ; n^= $b ; ` $y $n ; }
`p f /y ^n a b { l $a $b $n $y }
`info arg d
`info arg f
`info body d
`info body f
` $x
`d x lemon lime
`f x fruit veg
`f y fruit veg
'lsort,info command
'map [lsort,info command *=*] info'body
}

			

 


 
Read more of   The Yak's Frequently Questioned Answers   (mod.2010-02-10)

424.   Where do you get StrickPants?   [strick/2007-06-30]
396.   I'm lost at sea and I need to navigate to a non-extradition island republic. Can you help?   [overcode/2003-11-30]
383.   How do I translate to and from Japanese?   [novalis/2003-09-25]
376.   What are three very useful online dictionaries?   [jake/2003-09-22]
341.   Can you give me some pointers for using gpg/pgp and other encryption?   [jake/2002-12-19]
335.   What is Bob?   [gopherdave/2002-11-04]
295.   How do I get a cheap EPOC R5 (Symbian) handheld?   [combee/2001-12-07]
283.   What is the beautiful font used in the movie "Bicentennial Man" ?   [rupe/2001-11-09]
262.   Ricochet is dead for now. What are some alternatives?   [rupe/2001-08-07]
255.   why is the text on some website(such as kernel.org) unreadable in konqueror at the default font size?   [jesse/2001-07-09]
246.   why am i getting errors with when reflashing my TINI from a linux box?   [jesse/2001-06-09]
178.   Why isn't my PCS email working on my Cingular/PB Wireless phone?   [rupe/2001-02-12]
96.   Where can I find information on in-vehicle computer systems?   [rupe/2000-05-24]
93.   Where can I find a GPLed Z80 assembler / disassembler for Linux and DOS?   [rupe/2000-05-11]
57.   How do you make popcorn salad, and is it actually a "salad"?   [mockturtle/2000-02-12]
32.   What are the 'mailer' flags (on the M lines) inside sendmail.cf ?   [strick/2000-01-25]
17.   How can I make a didgeridoo for traveling?   [ult/2002-04-20]
10.   are there ICKY THINGS on the internet?   [strick/2000-01-17]