Shiny is a simple interpreted scripting language with aspects similar to Lua, Ruby and Perl. Anyone familiar with C derivative languages should find Shiny easy to pick up.
This is a little script I use to dump radio streams from an RSS feed supplied by my ISP.
#!/home/sean/bin/shiny
assert args.exists 2 "missing find parameter"
find: args[2]
# rss is pulled in by cron
rss: io.slurp '/home/sean/.radio.rss'
# grab the first channel only
items: rss.replace re/^.*<channel>(.*)<\/channel>.*$/gsm '%(a)s'
# extract an xml tag
search: function
txt: in tag: in a: 'unknown'
txt.match re/<%(tag)s>\s*(.*?)\s*<\/%(tag)s>/sm
out a
end
# cycle through radio stations searching name and description fields
each items.find re/<item>(.*?)<\/item>/sm item
name: search item 'title'
link: search item 'link'
desc: search item 'description'
if name.match re/%(find)s/i or desc.match re/%(find)s/i
print "%s\n\t%s\n\t%s" name desc link
end
end
Variables can be any string that does not clash with a core key word. They must begin with a letter [a-zA-Z], optionally followed by letters, digits, or underscores [a-zA-Z0-9_]*. The colon (:) is used to assign data to a variable. Data typing is dynamic.
> x: 3.14 > y: 'hello world'
Variables are created in the local scope by default, unless prefixed with one or more scope or object identifiers.
> global.x: 3.14
Numbers are all floating point (real). The common infix arithmetic can be used with C-like precedence:
> print 1+2/3 1.67
A math library is available:
> x: -42 > print math.abs x 42 > print x.abs 42
For efficiency reasons, numbers are not true objects in Shiny, but they are treated as pseudo objects when assigned to a variable. The second dot (.) notation above implicity treats the math library functions as the x numeric variable's methods.
Numbers are passed by value.
More to come.
Strings may be specified using relatively standard single or double quote notation. Single quotes (') return a literal string unmodified except for any backslash () escaped single quotes. Double quotes (") replace most backslash () escape codes common to C type languages, and also perform automatic string formatting for percent sign (%) escape sequences, like those used by the C sprintf function.
> x: 'hello world' > y: "multi\nline\ntext" > z: "a formatted string with number '%d' and sub-string '%s'" 3.14 x
Like Numbers, Strings are pseudo objects. A string library is available to manipulate them.
> print string.length x 11 > print x.length 11
Strings are passed by value.
More to come.
Regular Expressions are used with various string library functions. They are specified using an re/pattern/flags notation, with Perl compatible syntax and modifier flags.
> x: 'hello world' > print x.replace re/[aeiou]+/ '_' h_llo world > print x.split re/\s+/ object 152684360 0: hello 1: world > if x.match re/hello/ print 'yes!' else print 'no!' end yes!
Sub-strings matched in parentheses during regex execution are exposed as variables in the local scope, and named a, b, c and so on.
> x.match re/(\w+)\s+(\w+)/ > print a hello > print b world
Regex are passed by value.
Functions are just closures assigned to a variable name.
say_hi: function print 'hi!' end
Functions can import arguments with the in key word. Arguments are supplied to functions by placing them inline after the function call separated only by white space, without parentheses or commas.
say_hi_to: function print "hi %s!" in end say_hi_to 'tom'
One important point to note is that the argument syntax generally disallows optional arguments except where data type differentiation is used. Functions that accept a variable number of arguments are still possible when an explicit argument count is supplied, or when an object is passed with named variables.
Functions can return zero or one value with the out key word:
max_value: function
a: in b: in
if a > b
out a
else
out b
end
end
print max_value 1 2
A function has a local variable scope. All variables up the scope chain, from local to any caller(s) to global, are directly visible to a function by name for reading only. To write to a variable outside the local scope, a spcific scope prefix must still be used.
Functions are passed by reference.
Objects are closures too, created like persistent functions. They use a prototype framework to create new objects either directly or by cloning. Any functions defined inside an object are automatically methods, which can reference their parent object with the this key word.
Create a raw object from the default super prototype:
x: object
greet: 'hi'
function say_hi
print greet
end
end
x.say_hi
Create a object derived from another, either as a simple copy:
y: copy x
..or as an extendable copy (like inheritance):
y: object extend x greet 'hello there' end y.say_hi
Objects can also be used as an associative array:
array: { a: 1 b: 2 c: 'three' }
Object methods and variables can be referenced using the dot (.) notation, or with familiar square brackets ([]) array access notation. These are the same:
print y.greet print y['greet']
Objects are passed by reference.
More to come.
All control structures and code blocks end with e end key word.
if condition [or|and condition [...]] block else block end
while condition [or|and condition [...]] block end
for start stop step var block end
each iterable var block end each pair iterable key var block end
The key word print writes a single argument to stdout with a trailing line break.
The key word bye exits Shiny.
The key word type takes a single argument and returns the data type as a string.
> x: 42 > print type x number
The key word assert takes a condition argument and an error message. If the condition is false, the error message is written to stderr and Shiny exits.
The io library exists to do simple I/O.
Or shell commands. Any string delimited by back ticks () is automatically executed in the system shell environment, and the result returned as a string. Back ticked strings perform all the same formating as double quoted (") strings.
> print `ls -al` total 52 -rw-r--r-- 1 sean sean 55 2008-11-30 02:28 Makefile -rw-r--r-- 1 sean sean 47379 2008-11-30 02:28 shiny.c
eof